diff options
Diffstat (limited to 'lib/kernel/test')
87 files changed, 18682 insertions, 17438 deletions
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 9e972b4f95..efe3a68531 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2013. All Rights Reserved. +# Copyright Ericsson AB 1997-2016. 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. @@ -79,7 +79,8 @@ MODULES= \ zlib_SUITE \ loose_node \ sendfile_SUITE \ - standard_error_SUITE + standard_error_SUITE \ + multi_load_SUITE APP_FILES = \ appinc.app \ @@ -112,7 +113,7 @@ RELSYSDIR = $(RELEASE_PATH)/kernel_test # ---------------------------------------------------- ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include +ERL_COMPILE_FLAGS += EBIN = . @@ -147,8 +148,8 @@ release_tests_spec: make_emakefile $(INSTALL_DIR) "$(RELSYSDIR)" $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) $(APP_FILES) "$(RELSYSDIR)" - $(INSTALL_DATA) kernel.spec kernel_smoke.spec $(EMAKEFILE)\ - $(COVERFILE) "$(RELSYSDIR)" + $(INSTALL_DATA) kernel.spec kernel_smoke.spec kernel_bench.spec \ + $(EMAKEFILE) $(COVERFILE) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/lib/kernel/test/appinc1.erl b/lib/kernel/test/appinc1.erl index fc9180b35a..b571208834 100644 --- a/lib/kernel/test/appinc1.erl +++ b/lib/kernel/test/appinc1.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/appinc1x.erl b/lib/kernel/test/appinc1x.erl index b05cd55b43..3aa6f3dcb9 100644 --- a/lib/kernel/test/appinc1x.erl +++ b/lib/kernel/test/appinc1x.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/appinc2.erl b/lib/kernel/test/appinc2.erl index 7e92e7e092..a665e628a2 100644 --- a/lib/kernel/test/appinc2.erl +++ b/lib/kernel/test/appinc2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/appinc2A.erl b/lib/kernel/test/appinc2A.erl index f0e2cd4277..378eb179f2 100644 --- a/lib/kernel/test/appinc2A.erl +++ b/lib/kernel/test/appinc2A.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/appinc2B.erl b/lib/kernel/test/appinc2B.erl index 17623621bb..35b7016906 100644 --- a/lib/kernel/test/appinc2B.erl +++ b/lib/kernel/test/appinc2B.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/appinc2top.erl b/lib/kernel/test/appinc2top.erl index f3d9715a2a..3b6dc4ea31 100644 --- a/lib/kernel/test/appinc2top.erl +++ b/lib/kernel/test/appinc2top.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index 0c198b90ae..866043cfb4 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -19,7 +19,7 @@ %% -module(application_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2 @@ -40,14 +40,14 @@ shutdown_func/1, do_shutdown/1, shutdown_timeout/1, shutdown_deadlock/1]). -define(TESTCASE, testcase_name). --define(testcase, ?config(?TESTCASE, Config)). +-define(testcase, proplists:get_value(?TESTCASE, Config)). -export([init_per_testcase/2, end_per_testcase/2, start_type/0, start_phase/0, conf_change/0]). -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(2)). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [failover, failover_comp, permissions, load, @@ -81,21 +81,15 @@ end_per_group(_GroupName, Config) -> init_per_testcase(otp_2973=Case, Config) -> - code:add_path(?config(data_dir,Config)), - Dog = test_server:timetrap(?default_timeout), - [{?TESTCASE, Case}, {watchdog, Dog}|Config]; + code:add_path(proplists:get_value(data_dir,Config)), + [{?TESTCASE, Case}|Config]; init_per_testcase(Case, Config) -> - Dog = test_server:timetrap(?default_timeout), - [{?TESTCASE, Case}, {watchdog, Dog}|Config]. + [{?TESTCASE, Case}|Config]. end_per_testcase(otp_2973, Config) -> - code:del_path(?config(data_dir,Config)), - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), + code:del_path(proplists:get_value(data_dir,Config)), ok; -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -define(UNTIL(Seq), loop_until_true(fun() -> Seq end)). @@ -120,10 +114,8 @@ loop_until_true(Fun) -> %% Should be started in a CC view with: %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -failover(suite) -> []; -failover(doc) -> - ["Tests failover and takeover for distributed applications. Tests", - "start, load etc implicitly."]; +%% Tests failover and takeover for distributed applications. Tests +%% start, load etc implicitly. failover(Conf) when is_list(Conf) -> %% start a help process to check the start type StPid = spawn_link(?MODULE, start_type, []), @@ -133,14 +125,14 @@ failover(Conf) when is_list(Conf) -> NoSyncTime = config_fun_fast(config_fo(NodeNames)), WithSyncTime = config_fun(config_fo(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), Cps = [Cp1, Cp2, Cp3], wait_for_ready_net(), - % Start app1 and make sure cp1 starts it + %% Start app1 and make sure cp1 starts it {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), ?UNTIL(is_loaded(app1, Cps)), @@ -150,12 +142,12 @@ failover(Conf) when is_list(Conf) -> false = is_started(app1, Cp2), ok = get_start_type(#st{normal = 3}), - % Stop cp1 and make sure cp2 starts app1 + %% Stop cp1 and make sure cp2 starts app1 stop_node_nice(Cp1), ?UNTIL(is_started(app1, Cp2)), ok = get_start_type(#st{normal = 3}), - % Restart cp1 and make sure it restarts app1 + %% Restart cp1 and make sure it restarts app1 {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp1_2, application, load, [app1()]), @@ -164,8 +156,8 @@ failover(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app1, Cp2)), ok = get_start_type(#st{takeover = 3}), - % Test [{cp1, cp2}, cp3] - % Start app_sp and make sure cp2 starts it (cp1 has more apps started) + %% Test [{cp1, cp2}, cp3] + %% Start app_sp and make sure cp2 starts it (cp1 has more apps started) {[ok,ok,ok],[]} = rpc:multicall([Cp1_2, Cp2, Cp3], application, load, [app_sp()]), {[ok,ok,ok],[]} = @@ -175,17 +167,17 @@ failover(Conf) when is_list(Conf) -> false = is_started(app_sp, Cp3), ok = get_start_type(#st{normal = 3}), - % Stop cp2 and make sure cp1 starts app_sp + %% Stop cp2 and make sure cp1 starts app_sp stop_node_nice(Cp2), ?UNTIL(is_started(app_sp, Cp1_2)), ok = get_start_type(#st{failover = 3}), - % Stop cp1 and make sure cp3 starts app_sp + %% Stop cp1 and make sure cp3 starts app_sp stop_node_nice(Cp1_2), ?UNTIL(is_started(app_sp, Cp3)), ok = get_start_type(#st{normal = 3, failover = 3}), - % Restart cp2 and make sure it restarts app_sp + %% Restart cp2 and make sure it restarts app_sp {ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp2_2, application, load, [app_sp()]), @@ -194,16 +186,16 @@ failover(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app_sp, Cp3)), ok = get_start_type(#st{takeover = 3}), - % Restart cp1 and make sure it doesn't restart app_sp + %% Restart cp1 and make sure it doesn't restart app_sp {ok, Cp1_3} = start_node_config(Ncp1, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp1_3, application, load, [app_sp()]), ok = rpc:call(Cp1_3, application, start, [app_sp, permanent]), - test_server:sleep(500), + ct:sleep(500), false = is_started(app_sp, Cp1_3), true = is_started(app_sp, Cp2_2), - % Force takeover to cp1 + %% Force takeover to cp1 ok = rpc:call(Cp1_3, application, takeover, [app_sp, permanent]), ?UNTIL(is_started(app_sp, Cp1_3)), ?UNTIL(not is_started(app_sp, Cp2_2)), @@ -225,11 +217,9 @@ failover(Conf) when is_list(Conf) -> %% Should be started in a CC view with: %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -failover_comp(suite) -> []; -failover_comp(doc) -> - ["Tests failover and takeover for distributed applications. Tests", - "start, load etc implicitly. The applications do not use start_phases," - "i.e the failover should be trasfered to normal start type."]; +%% Tests failover and takeover for distributed applications. Tests +%% start, load etc implicitly. The applications do not use start_phases +%% i.e. the failover should be transfered to normal start type. failover_comp(Conf) when is_list(Conf) -> %% start a help process to check the start type StPid = spawn_link(?MODULE, start_type, []), @@ -239,14 +229,14 @@ failover_comp(Conf) when is_list(Conf) -> NoSyncTime = config_fun_fast(config(NodeNames)), WithSyncTime = config_fun(config(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), Cps = [Cp1, Cp2, Cp3], wait_for_ready_net(), - % Start app1 and make sure cp1 starts it + %% Start app1 and make sure cp1 starts it {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), ?UNTIL(is_loaded(app1, Cps)), @@ -256,12 +246,12 @@ failover_comp(Conf) when is_list(Conf) -> false = is_started(app1, Cp2), ok = get_start_type(#st{normal = 3}), - % Stop cp1 and make sure cp2 starts app1 + %% Stop cp1 and make sure cp2 starts app1 stop_node_nice(Cp1), ?UNTIL(is_started(app1, Cp2)), ok = get_start_type(#st{normal = 3}), - % Restart cp1 and make sure it restarts app1 + %% Restart cp1 and make sure it restarts app1 {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp1_2, application, load, [app1()]), @@ -271,8 +261,8 @@ failover_comp(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app1, Cp2)), ok = get_start_type(#st{takeover = 3}), - % Test [{cp1, cp2}, cp3] - % Start app3 and make sure cp2 starts it (cp1 has more apps started) + %% Test [{cp1, cp2}, cp3] + %% Start app3 and make sure cp2 starts it (cp1 has more apps started) {[ok,ok,ok],[]} = rpc:multicall([Cp1_2, Cp2, Cp3], application, load, [app3()]), ?UNTIL(is_loaded(app3, [Cp1_2, Cp2, Cp3])), @@ -283,17 +273,17 @@ failover_comp(Conf) when is_list(Conf) -> false = is_started(app3, Cp3), ok = get_start_type(#st{normal = 3}), - % Stop cp2 and make sure cp1 starts app3 + %% Stop cp2 and make sure cp1 starts app3 stop_node_nice(Cp2), ?UNTIL(is_started(app3, Cp1_2)), ok = get_start_type(#st{normal = 3}), - % Stop cp1 and make sure cp3 starts app3 + %% Stop cp1 and make sure cp3 starts app3 stop_node_nice(Cp1_2), ?UNTIL(is_started(app3, Cp3)), ok = get_start_type(#st{normal = 6}), - % Restart cp2 and make sure it restarts app3 + %% Restart cp2 and make sure it restarts app3 {ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp2_2, application, load, [app3()]), @@ -303,17 +293,17 @@ failover_comp(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app3, Cp3)), ok = get_start_type(#st{takeover = 3}), - % Restart cp1 and make sure it doesn't restart app3 + %% Restart cp1 and make sure it doesn't restart app3 {ok, Cp1_3} = start_node_config(Ncp1, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp1_3, application, load, [app3()]), true = is_loaded(app3, Cp1_3), ok = rpc:call(Cp1_3, application, start, [app3, permanent]), - test_server:sleep(5000), + ct:sleep(5000), false = is_started(app3, Cp1_3), true = is_started(app3, Cp2_2), - % Force takeover to cp1 + %% Force takeover to cp1 ok = rpc:call(Cp1_3, application, takeover, [app3, permanent]), ?UNTIL(is_started(app3, Cp1_3)), ?UNTIL(not is_started(app3, Cp2_2)), @@ -335,23 +325,21 @@ failover_comp(Conf) when is_list(Conf) -> %% Should be started in a CC view with: %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -permissions(suite) -> []; -permissions(doc) -> - ["Tests permissions for distributed applications."]; +%% Tests permissions for distributed applications. permissions(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config2(NodeNames)), WithSyncTime = config_fun(config2(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), Cps = [Cp1, Cp2, Cp3], wait_for_ready_net(), - % Start app1 and make sure cp1 starts it + %% Start app1 and make sure cp1 starts it {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), ?UNTIL(is_loaded(app1, Cps)), @@ -360,50 +348,50 @@ permissions(Conf) when is_list(Conf) -> ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), - % Unpermit app1 on cp1, make sure cp2 starts it + %% Unpermit app1 on cp1, make sure cp2 starts it ok = rpc:call(Cp1, application, permit, [app1, false]), false = is_started(app1, Cp1), true = is_started(app1, Cp2), - % Unpermit app1 on cp2, make sure cp3 starts it + %% Unpermit app1 on cp2, make sure cp3 starts it ok = rpc:call(Cp2, application, permit, [app1, false]), false = is_started(app1, Cp1), false = is_started(app1, Cp2), true = is_started(app1, Cp3), - % Permit cp2 again + %% Permit cp2 again ok = rpc:call(Cp2, application, permit, [app1, true]), false = is_started(app1, Cp1), false = is_started(app1, Cp3), true = is_started(app1, Cp2), - % Start app3, make sure noone starts it + %% Start app3, make sure noone starts it {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app3()]), ?UNTIL(is_loaded(app3, Cps)), {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app3, permanent]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app3, Cp1), false = is_started(app3, Cp2), false = is_started(app3, Cp3), - % Permit app3 on Cp3 + %% Permit app3 on Cp3 ok = rpc:call(Cp3, application, permit, [app3, true]), true = is_started(app3, Cp3), - % Permit app3 on Cp2, make sure it starts it + %% Permit app3 on Cp2, make sure it starts it ok = rpc:call(Cp2, application, permit, [app3, true]), true = is_started(app3, Cp2), false = is_started(app3, Cp3), - % Permit app3 on Cp1, make sure it doesn't start it + %% Permit app3 on Cp1, make sure it doesn't start it ok = rpc:call(Cp1, application, permit, [app3, true]), false = is_started(app3, Cp1), true = is_started(app3, Cp2), false = is_started(app3, Cp3), - % Stop Cp2, make sure Cp1 starts app3 + %% Stop Cp2, make sure Cp1 starts app3 stop_node_nice(Cp2), ?UNTIL(is_started(app3, Cp1)), @@ -415,15 +403,13 @@ permissions(Conf) when is_list(Conf) -> %% Should be started in a CC view with: %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -load(suite) -> []; -load(doc) -> - ["Tests loading of distributed applications."]; +%% Tests loading of distributed applications. load(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config3(NodeNames)), WithSyncTime = config_fun(config3(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), @@ -439,7 +425,7 @@ load(Conf) when is_list(Conf) -> false = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Load app1 with different specs and make sure we get an error + %% Load app1 with different specs and make sure we get an error {[{error,_},{error,_}],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1(), d1(NodeNames)]), {error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]), @@ -452,15 +438,13 @@ load(Conf) when is_list(Conf) -> %%----------------------------------------------------------------- %% Same test as load/1, only with code path cache enabled. %%----------------------------------------------------------------- -load_use_cache(suite) -> []; -load_use_cache(doc) -> - ["Tests loading of distributed applications. Code path cache enabled."]; +%% Tests loading of distributed applications. Code path cache enabled. load_use_cache(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config3(NodeNames)), WithSyncTime = config_fun(config3(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_with_cache(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_with_cache(Ncp2, NoSyncTime, Conf), {ok, Cp3} = start_node_with_cache(Ncp3, WithSyncTime, Conf), @@ -475,7 +459,7 @@ load_use_cache(Conf) when is_list(Conf) -> ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), - % Load app1 with different specs and make sure we get an error + %% Load app1 with different specs and make sure we get an error {[{error,_},{error,_}],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1(), d1(NodeNames)]), {error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]), @@ -489,9 +473,7 @@ load_use_cache(Conf) when is_list(Conf) -> %% Should be started in a CC view with: %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -start_phases(suite) -> []; -start_phases(doc) -> - ["Tests new start phases and failover."]; +%% Tests new start phases and failover. start_phases(Conf) when is_list(Conf) -> %% start a help process to check the start type SpPid = spawn_link(?MODULE, start_phase, []), @@ -553,17 +535,15 @@ start_phases(Conf) when is_list(Conf) -> ok. -script_start(doc) -> - ["Start distributed applications from within a boot script. Test ", - "same as failover."]; -script_start(suite) -> []; +%% Start distributed applications from within a boot script. Test +%% same as failover. script_start(Conf) when is_list(Conf) -> %% start a help process to check the start type StPid = spawn_link(?MODULE, start_type, []), yes = global:register_name(st_type, StPid), - % Create the .app files and the boot script + %% Create the .app files and the boot script ok = create_app(), {{KernelVer,StdlibVer}, _} = create_script("latest"), case is_real_system(KernelVer, StdlibVer) of @@ -578,7 +558,7 @@ script_start(Conf) when is_list(Conf) -> NoSyncTime = config_fun_fast(config_fo(NodeNames)), WithSyncTime = config_fun(config_fo(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), {ok, Cp2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest), {ok, Cp3} = start_node_boot_config(Ncp3, WithSyncTime, Conf, latest), @@ -590,16 +570,16 @@ script_start(Conf) when is_list(Conf) -> false = is_started(app1, Cp2), ok = get_start_type(#st{normal = 9}), - % Stop cp1 and make sure cp2 starts app1, app2 normally (no - % start_phases defined) and app_sp as failover (start_phases - % defined) + %% Stop cp1 and make sure cp2 starts app1, app2 normally (no + %% start_phases defined) and app_sp as failover (start_phases + %% defined) stop_node_nice(Cp1), ?UNTIL(is_started(app1, Cp2)), ?UNTIL(is_started(app2, Cp2)), ?UNTIL(is_started(app_sp, Cp2)), ok = get_start_type(#st{normal = 6, failover = 3}), - % Restart cp1, Cp1 takesover app1 and app2 + %% Restart cp1, Cp1 takesover app1 and app2 {ok, Cp1_2} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), global:sync(), ?UNTIL(is_started(app1, Cp1_2)), @@ -610,20 +590,20 @@ script_start(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app2, Cp2)), ok = get_start_type(#st{takeover = 6}), - % Stop cp2 and make sure cp1 starts app_sp. + %% Stop cp2 and make sure cp1 starts app_sp. false = is_started(app_sp, Cp1_2), stop_node_nice(Cp2), ?UNTIL(is_started(app_sp, Cp1_2)), ok = get_start_type(#st{failover = 3}), - % Stop cp1 and make sure cp3 starts app1, app2 and app_sp + %% Stop cp1 and make sure cp3 starts app1, app2 and app_sp stop_node_nice(Cp1_2), ?UNTIL(is_started(app_sp, Cp3)), ?UNTIL(is_started(app1, Cp3)), ?UNTIL(is_started(app2, Cp3)), ok = get_start_type(#st{normal = 6, failover = 3}), - % Restart cp2 and make sure it takesover app1, app2 and app_sp + %% Restart cp2 and make sure it takesover app1, app2 and app_sp {ok, Cp2_2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest), global:sync(), ?UNTIL(is_started(app_sp, Cp2_2)), @@ -634,7 +614,7 @@ script_start(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app2, Cp3)), ok = get_start_type(#st{takeover = 9}), - % Restart cp1 and make sure it takesover app1, app2 + %% Restart cp1 and make sure it takesover app1, app2 {ok, Cp1_3} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), global:sync(), ?UNTIL(is_started(app1, Cp1_3)), @@ -645,7 +625,7 @@ script_start(Conf) when is_list(Conf) -> ?UNTIL(not is_started(app2, Cp2_2)), ok = get_start_type(#st{takeover = 6}), - % Force takeover to cp1 + %% Force takeover to cp1 ok = rpc:call(Cp1_3, application, takeover, [app_sp, permanent]), ?UNTIL(is_started(app_sp, Cp1_3)), ?UNTIL(not is_started(app_sp, Cp2_2)), @@ -668,15 +648,13 @@ script_start(Conf) when is_list(Conf) -> ok. -permit_false_start_local(doc) -> - ["Start local applications with permission false. Set", - "permit true on different nodes."]; -permit_false_start_local(suite) -> []; +%% Start local applications with permission false. Set +%% permit true on different nodes. permit_false_start_local(Conf) when is_list(Conf) -> %% This configuration does not start dist_ac. Config = write_config_file(fun config_perm/1, Conf), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), {ok, Cp1} = start_node(Ncp1, Config), {ok, Cp2} = start_node(Ncp2, Config), @@ -694,99 +672,99 @@ permit_false_start_local(Conf) when is_list(Conf) -> {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, load, [app3()]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app1, Cp1), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - %Permit a not started application + %% Permit a not started application ok = rpc:call(Cp1, application, permit, [app3, true]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app3, Cp1), false = is_started(app3, Cp2), false = is_started(app3, Cp3), - %Permit a not loaded application + %% Permit a not loaded application {error,{not_loaded,app_notloaded}} = rpc:call(Cp1, application, permit, [app_notloaded, true]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app_notloaded, Cp1), false = is_started(app_notloaded, Cp2), false = is_started(app_notloaded, Cp3), - %Unpermit a not started application + %% Unpermit a not started application ok = rpc:call(Cp1, application, permit, [app3, false]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app3, Cp1), false = is_started(app3, Cp2), false = is_started(app3, Cp3), - %Unpermit a not loaded application + %% Unpermit a not loaded application {error,{not_loaded,app_notloaded}} = rpc:call(Cp1, application, permit, [app_notloaded, false]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app_notloaded, Cp1), false = is_started(app_notloaded, Cp2), false = is_started(app_notloaded, Cp3), - % Permit app1 on CP1 and make sure it is started + %% Permit app1 on CP1 and make sure it is started ok = rpc:call(Cp1, application, permit, [app1, true]), ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Permit it again + %% Permit it again ok = rpc:call(Cp1, application, permit, [app1, true]), - test_server:sleep(1000), + ct:sleep(1000), true = is_started(app1, Cp1), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Permit app2 on CP1 and make sure it is started + %% Permit app2 on CP1 and make sure it is started ok = rpc:call(Cp1, application, permit, [app2, true]), ?UNTIL(is_started(app2, Cp1)), false = is_started(app2, Cp2), false = is_started(app2, Cp3), - % Permit app1 on CP2 and make sure it is started + %% Permit app1 on CP2 and make sure it is started ok = rpc:call(Cp2, application, permit, [app1, true]), ?UNTIL(is_started(app1, Cp2)), true = is_started(app1, Cp1), false = is_started(app1, Cp3), - % Unpermit app1 on CP1 and make sure it is stopped + %% Unpermit app1 on CP1 and make sure it is stopped ok = rpc:call(Cp1, application, permit, [app1, false]), ?UNTIL(false =:= is_started(app1, Cp1)), true = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Unpermit it agin + %% Unpermit it agin ok = rpc:call(Cp1, application, permit, [app1, false]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app1, Cp1), true = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Permit app1 on CP1 and make sure it is started + %% Permit app1 on CP1 and make sure it is started ok = rpc:call(Cp1, application, permit, [app1, true]), ?UNTIL(is_started(app1, Cp1)), true = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Unpermit app1 on CP1 and make sure it is stopped + %% Unpermit app1 on CP1 and make sure it is stopped ok = rpc:call(Cp1, application, permit, [app1, false]), ?UNTIL(false =:= is_started(app1, Cp1)), true = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Unpermit app1 on CP2 and make sure it is stopped + %% Unpermit app1 on CP2 and make sure it is stopped ok = rpc:call(Cp2, application, permit, [app1, false]), - test_server:sleep(1000), + ct:sleep(1000), ?UNTIL(false =:= is_started(app1, Cp2)), false = is_started(app1, Cp1), false = is_started(app1, Cp3), - % Unpermit app2 on CP1 and make sure it is stopped + %% Unpermit app2 on CP1 and make sure it is stopped ok = rpc:call(Cp1, application, permit, [app2, false]), ?UNTIL(false =:= is_started(app2, Cp2)), false = is_started(app2, Cp1), @@ -798,16 +776,14 @@ permit_false_start_local(Conf) when is_list(Conf) -> ok. -permit_false_start_dist(doc) -> - ["Start distributed applications with permission false. Set", - "permit true on different nodes."]; -permit_false_start_dist(suite) -> []; +%% Start distributed applications with permission false. Set +%% permit true on different nodes. permit_false_start_dist(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config_perm2(NodeNames)), WithSyncTime = config_fun(config_perm2(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), @@ -822,36 +798,36 @@ permit_false_start_dist(Conf) when is_list(Conf) -> {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app2()]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app1, Cp1), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - %Permit a not started application + %% Permit a not started application ok = rpc:call(Cp1, application, permit, [app2, true]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app2, Cp1), false = is_started(app2, Cp2), false = is_started(app2, Cp3), - %Permit a not loaded application + %% Permit a not loaded application {error,{not_loaded,app3}} = rpc:call(Cp1, application, permit, [app3, true]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app3, Cp1), false = is_started(app3, Cp2), false = is_started(app3, Cp3), - %Unpermit a not started application + %% Unpermit a not started application ok = rpc:call(Cp1, application, permit, [app2, false]), {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, start, [app2, permanent]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app2, Cp1), false = is_started(app2, Cp2), false = is_started(app2, Cp3), - %Unpermit a not loaded application + %% Unpermit a not loaded application {error,{not_loaded,app3}} = rpc:call(Cp1, application, permit, [app3, false]), {[ok,ok,ok],[]} = @@ -859,42 +835,42 @@ permit_false_start_dist(Conf) when is_list(Conf) -> ?UNTIL(is_loaded(app3, Cps)), {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app3, permanent]), - test_server:sleep(1000), + ct:sleep(1000), false = is_started(app3, Cp1), false = is_started(app3, Cp2), false = is_started(app3, Cp3), - % Permit app1 on CP1 and make sure it is started + %% Permit app1 on CP1 and make sure it is started ok = rpc:call(Cp1, application, permit, [app1, true]), ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Permit it again + %% Permit it again ok = rpc:call(Cp1, application, permit, [app1, true]), ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Permit app2 on CP1 and make sure it is started + %% Permit app2 on CP1 and make sure it is started ok = rpc:call(Cp1, application, permit, [app2, true]), ?UNTIL(is_started(app2, Cp1)), false = is_started(app2, Cp2), false = is_started(app2, Cp3), - % Permit app1 on CP2 and make sure it is not started + %% Permit app1 on CP2 and make sure it is not started ok = rpc:call(Cp2, application, permit, [app1, true]), - test_server:sleep(1000), + ct:sleep(1000), true = is_started(app1, Cp1), false = is_started(app1, Cp2), false = is_started(app1, Cp3), - % Crash CP1 and make sure app1, but not app2, is started on CP2 + %% Crash CP1 and make sure app1, but not app2, is started on CP2 stop_node_nice(Cp1), ?UNTIL(is_started(app1, Cp2)), false = is_started(app2, Cp2), - % Restart CP1 again, check nothing is running on it + %% Restart CP1 again, check nothing is running on it {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), global:sync(), ok = rpc:call(Cp1_2, application, load, [app1()]), @@ -909,19 +885,19 @@ permit_false_start_dist(Conf) when is_list(Conf) -> false = is_started(app1, Cp1_2), false = is_started(app2, Cp1_2), - % Permit app3 on CP3 and make sure it is started + %% Permit app3 on CP3 and make sure it is started ok = rpc:call(Cp3, application, permit, [app3, true]), ?UNTIL(is_started(app3, Cp3)), false = is_started(app3, Cp1_2), false = is_started(app3, Cp2), - % Permit app3 on CP1 and make sure it is moved there from CP3 + %% Permit app3 on CP1 and make sure it is moved there from CP3 ok = rpc:call(Cp1_2, application, permit, [app3, true]), ?UNTIL(is_started(app3, Cp1_2)), false = is_started(app3, Cp2), false = is_started(app3, Cp3), - % Unpermit app3 on CP3 and CP1 and make sure it is stopped + %% Unpermit app3 on CP3 and CP1 and make sure it is stopped ok = rpc:call(Cp3, application, permit, [app3, false]), ok = rpc:call(Cp1_2, application, permit, [app3, false]), ?UNTIL(false =:= is_started(app3, Cp1_2)), @@ -933,27 +909,25 @@ permit_false_start_dist(Conf) when is_list(Conf) -> stop_node_nice(Cp3), ok. -nodedown_start(doc) -> - ["app1 distributed as [cp1, cp2]. Call application:start(app1) on", - "cp2, but not on cp1. Kill cp1. Make sure app1 is started on cp2."]; -nodedown_start(suite) -> []; +%% app1 distributed as [cp1, cp2]. Call application:start(app1) on +%% cp2, but not on cp1. Kill cp1. Make sure app1 is started on cp2. nodedown_start(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), NoSyncTime = config_fun_fast(config4(NodeNames)), WithSyncTime = config_fun(config4(NodeNames)), - % Test [cp1, cp2] + %% Test [cp1, cp2] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), wait_for_ready_net(), - % Start app1 and make sure cp1 starts it + %% Start app1 and make sure cp1 starts it {[ok,ok],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1()]), _ = rpc:cast(Cp2, application, start, [app1, permanent]), - test_server:sleep(1000), + ct:sleep(1000), - % Crash CP1 and make sure app1 is started on CP2 + %% Crash CP1 and make sure app1 is started on CP2 stop_node_nice(Cp1), ?UNTIL(is_started(app1, Cp2)), @@ -961,8 +935,7 @@ nodedown_start(Conf) when is_list(Conf) -> ok. -ensure_started(suite) -> []; -ensure_started(doc) -> ["Test application:ensure_started/1."]; +%% Test application:ensure_started/1. ensure_started(_Conf) -> {ok, Fd} = file:open("app1.app", [write]), @@ -981,8 +954,7 @@ ensure_started(_Conf) -> ok = application:unload(app1), ok. -ensure_all_started(suite) -> []; -ensure_all_started(doc) -> ["Test application:ensure_all_started/1-2."]; +%% Test application:ensure_all_started/1-2. ensure_all_started(_Conf) -> {ok, Fd1} = file:open("app1.app", [write]), @@ -1069,11 +1041,9 @@ ensure_all_started(_Conf) -> %% Ticket: OTP-1586 %% Slogan: recursive load of applications fails %%----------------------------------------------------------------- -otp_1586(suite) -> []; -otp_1586(doc) -> - ["Test recursive load of applications."]; +%% Test recursive load of applications. otp_1586(Conf) when is_list(Conf) -> - Dir = ?config(priv_dir,Conf), + Dir = proplists:get_value(priv_dir,Conf), {ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]), w_app5(Fd), file:close(Fd), @@ -1090,21 +1060,19 @@ otp_1586(Conf) when is_list(Conf) -> %% Slogan: start of distrib apps fails when the nodes start %% simultaneously %%----------------------------------------------------------------- -otp_2078(suite) -> []; -otp_2078(doc) -> - ["Test start of distrib apps fails when the nodes start simultaneously."]; +%% Test start of distrib apps fails when the nodes start simultaneously. otp_2078(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), NoSyncTime = config_fun_fast(config4(NodeNames)), WithSyncTime = config_fun(config4(NodeNames)), - % Test [cp1, cp2] + %% Test [cp1, cp2] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), Cps = [Cp1, Cp2], wait_for_ready_net(), - % Start app1 and make sure cp1 starts it + %% Start app1 and make sure cp1 starts it {[ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), ?UNTIL(is_loaded(app1, Cps)), @@ -1112,8 +1080,8 @@ otp_2078(Conf) when is_list(Conf) -> ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), - % Start app1 on cp2; make sure it works (the bug was that this start - % returned error) + %% Start app1 on cp2; make sure it works (the bug was that this start + %% returned error) ok = rpc:call(Cp2, application, start, [app1, permanent]), true = is_started(app1, Cp1), false = is_started(app1, Cp2), @@ -1122,15 +1090,13 @@ otp_2078(Conf) when is_list(Conf) -> stop_node_nice(Cp2), ok. -otp_2012(suite) -> []; -otp_2012(doc) -> - ["Test change of configuration parameters without changing code."]; +%% Test change of configuration parameters without changing code. otp_2012(Conf) when is_list(Conf) -> %% start a help process to check the config change CcPid = spawn_link(?MODULE, conf_change, []), yes = global:register_name(conf_change, CcPid), - % Write a .app file + %% Write a .app file {ok, Fd} = file:open("app1.app", [write]), w_app1(Fd), file:close(Fd), @@ -1138,7 +1104,7 @@ otp_2012(Conf) when is_list(Conf) -> w_app1(Fd2), file:close(Fd2), - % Start app1 + %% Start app1 ok = application:load(app1()), ok = application:start(app1, permanent), @@ -1149,7 +1115,7 @@ otp_2012(Conf) when is_list(Conf) -> ok = application_controller:config_change(EnvBefore), ok = get_conf_change([{[], [{new1, hi}, {new2, moi}], []}]), - % Start app2 + %% Start app2 ok = application:load(app2()), ok = application:start(app2, permanent), @@ -1173,11 +1139,9 @@ otp_2012(Conf) when is_list(Conf) -> %% Ticket: OTP-2718 %% Slogan: transient app which fails during start is ignored %%----------------------------------------------------------------- -otp_2718(suite) -> []; -otp_2718(doc) -> - ["Test fail of transient app at start."]; +%% Test fail of transient app at start. otp_2718(Conf) when is_list(Conf) -> - {ok, Cp1} = start_node_args(cp1, "-pa " ++ ?config(data_dir,Conf)), + {ok, Cp1} = start_node_args(cp1, "-pa " ++ proplists:get_value(data_dir,Conf)), wait_for_ready_net(), %% normal exit from the application @@ -1185,7 +1149,7 @@ otp_2718(Conf) when is_list(Conf) -> ?UNTIL(is_loaded(trans_normal, Cp1)), {error, {{'EXIT',normal},_}} = rpc:call(Cp1, application, start, [trans_normal, transient]), - test_server:sleep(2000), + ct:sleep(2000), false = is_started(trans_normal, Cp1), %% abnormal exit from the application @@ -1193,7 +1157,7 @@ otp_2718(Conf) when is_list(Conf) -> {error, {bad_return,{{trans_abnormal_sup,start,[normal,[]]}, {'EXIT',abnormal}}}} = rpc:call(Cp1, application, start, [trans_abnormal, transient]), - test_server:sleep(3000), + ct:sleep(3000), {badrpc,nodedown} = which_applications(Cp1), ok. @@ -1201,11 +1165,9 @@ otp_2718(Conf) when is_list(Conf) -> %% Ticket: OTP-2973 %% Slogan: application:start does not test if an appl is already starting... %%----------------------------------------------------------------- -otp_2973(suite) -> []; -otp_2973(doc) -> - ["Test of two processes simultanously starting the same application."]; +%% Test of two processes simultanously starting the same application. otp_2973(Conf) when is_list(Conf) -> - % Write a .app file + %% Write a .app file {ok, Fd} = file:open("app0.app", [write]), w_app(Fd, app0()), file:close(Fd), @@ -1222,14 +1184,14 @@ otp_2973(Conf) when is_list(Conf) -> {Pid2, res, Res2x} -> {Res1x, Res2x} after 2000 -> - test_server:fail(timeout_pid2) + ct:fail(timeout_pid2) end; {Pid2, res, Res2x} -> receive {Pid1, res, Res1x} -> {Res1x, Res2x} after 2000 -> - test_server:fail(timeout_pid1) + ct:fail(timeout_pid1) end end, @@ -1243,11 +1205,11 @@ otp_2973(Conf) when is_list(Conf) -> _ -> Txt = io_lib:format("Illegal results from start: ~p ~p ", [Res1, Res2]), - test_server:fail(lists:flatten(Txt)) + ct:fail(lists:flatten(Txt)) end, - % Write a .app file + %% Write a .app file {ok, Fda} = file:open("app_start_error.app", [write]), w_app_start_error(Fda), file:close(Fda), @@ -1261,14 +1223,14 @@ otp_2973(Conf) when is_list(Conf) -> {Pid2, res, Res2y} -> {Res1y, Res2y} after 2000 -> - test_server:fail(timeout_pid2) + ct:fail(timeout_pid2) end; {Pid2, res, Res2y} -> receive {Pid1, res, Res1y} -> {Res1y, Res2y} after 2000 -> - test_server:fail(timeout_pid1) + ct:fail(timeout_pid1) end end, @@ -1278,7 +1240,7 @@ otp_2973(Conf) when is_list(Conf) -> ok; _ -> Txta = io_lib:format("Illegal results from start ~p ~p ",[Res1a, Res2a]), - test_server:fail(lists:flatten(Txta)) + ct:fail(lists:flatten(Txta)) end, ok. @@ -1289,36 +1251,34 @@ otp_2973(Conf) when is_list(Conf) -> %% Ticket: OTP-3184 %% Slogan: crash the node if permanent appl has illegal env parameter values %%----------------------------------------------------------------- -otp_3184(suite) -> []; -otp_3184(doc) -> - ["When a distributed application is started the permit flag is checked " - "that the permit flag is not changed during the start. " - "Te check must only be made if the application is started on the own node"]; +%% When a distributed application is started the permit flag is checked +%% that the permit flag is not changed during the start. +%% The check must only be made if the application is started on the own node. otp_3184(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), NoSyncTime = config_fun_fast(config3184(NodeNames)), WithSyncTime = config_fun(config3184(NodeNames)), - % Test [cp1, cp2] + %% Test [cp1, cp2] {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), wait_for_ready_net(), - % Start app1 and make sure it is not started + %% Start app1 and make sure it is not started {[ok,ok],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1()]), - test_server:sleep(3000), + ct:sleep(3000), false = is_started(app1, Cp1), false = is_started(app1, Cp2), - % Start app1 on cp1 + %% Start app1 on cp1 ok = rpc:call(Cp1, application, permit, [app1, true]), ok = rpc:call(Cp1, application, start, [app1, permanent]), ok = rpc:call(Cp2, application, start, [app1, permanent]), ?UNTIL(is_started(app1, Cp1)), false = is_started(app1, Cp2), - % Check that the application is marked as running in application_controller + %% Check that the application is marked as running in application_controller X = rpc:call(Cp1, application_controller, info, []), {value, {running, Xrunning}} = lists:keysearch(running, 1, X), {value, Xapp1} = lists:keysearch(app1, 1, Xrunning), @@ -1337,15 +1297,13 @@ otp_3184(Conf) when is_list(Conf) -> %% Ticket: OTP-3002 %% Slogan: crash the node if permanent appl has illegal env parameter values %%----------------------------------------------------------------- -otp_3002(suite) -> []; -otp_3002(doc) -> - ["crash the node if permanent appl has illegal env parameter values."]; +%% crash the node if permanent appl has illegal env parameter values. otp_3002(Conf) when is_list(Conf) -> - % Create the boot script + %% Create the boot script {{KernelVer,StdlibVer}, {LatestDir, LatestName}} = create_script_3002("script_3002"), - ?t:format(0, "LatestDir = ~p~n", [LatestDir]), - ?t:format(0, "LatestName = ~p~n", [LatestName]), + ct:pal(?HI_VERBOSITY, "LatestDir = ~p~n", [LatestDir]), + ct:pal(?HI_VERBOSITY, "LatestName = ~p~n", [LatestName]), case is_real_system(KernelVer, StdlibVer) of true -> @@ -1371,10 +1329,9 @@ otp_3002(Conf) when is_list(Conf) -> %% when it received dist_ac_app_stopped). %%----------------------------------------------------------------- -otp_4066(suite) -> []; -otp_4066(doc) -> ["Check that application stop don't cause dist_ac crash"]; +%% Check that application stop don't cause dist_ac crash. otp_4066(Conf) when is_list(Conf) -> - % Write config files + %% Write config files [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), Host = from($@, atom_to_list(node())), Cp1 = list_to_atom(Ncp1 ++ "@" ++ Host), @@ -1382,12 +1339,12 @@ otp_4066(Conf) when is_list(Conf) -> AllNodes = [Cp1, Cp2], App1Nodes = {app1, AllNodes}, - Dir = ?config(priv_dir,Conf), + Dir = proplists:get_value(priv_dir,Conf), {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), [write]), write_config(FdC, config_4066(AllNodes, 5000, [App1Nodes])), file:close(FdC), - % Write the app1.app file + %% Write the app1.app file {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]), w_app1(FdA12), file:close(FdA12), @@ -1402,29 +1359,29 @@ otp_4066(Conf) when is_list(Conf) -> ok = rpc:call(Cp1, application, start, [app1]), wait_until_started(app1, [Cp1]), - test_server:format("--- App1 started at Cp1 ---~n", []), + io:format("--- App1 started at Cp1 ---~n", []), print_dac_state(AllNodes), - % Cp2 previously crashed on this stop + %% Cp2 previously crashed on this stop ok = rpc:call(Cp1, application, stop, [app1]), wait_until_stopped(app1, [Cp1]), - test_server:format("--- App1 stopped at Cp1 ---~n", []), + io:format("--- App1 stopped at Cp1 ---~n", []), print_dac_state(AllNodes), ok = rpc:call(Cp1, application, start, [app1]), wait_until_started(app1, [Cp1]), - test_server:format("--- App1 started at Cp1 ---~n", []), + io:format("--- App1 started at Cp1 ---~n", []), print_dac_state(AllNodes), ok = rpc:call(Cp2, application, load, [app1, App1Nodes]), ok = rpc:call(Cp2, application, start, [app1]), - test_server:format("--- App1 started at Cp2 ---~n", []), + io:format("--- App1 started at Cp2 ---~n", []), print_dac_state(AllNodes), stop_node_nice(Cp1), wait_until_started(app1, [Cp2]), - test_server:format("--- Cp1 crashed; failover to Cp2 ---~n", []), + io:format("--- Cp1 crashed; failover to Cp2 ---~n", []), print_dac_state(Cp2), stop_node_nice(Cp2), @@ -1440,7 +1397,7 @@ write_config(Fd, Config) -> print_dac_state(Node) when is_atom(Node) -> State = gen_server:call({dist_ac, Node}, info), - test_server:format(" * dist_ac state on node ~p:~n ~p~n", + io:format(" * dist_ac state on node ~p:~n ~p~n", [Node, State]); print_dac_state(Nodes) when is_list(Nodes) -> lists:foreach(fun (N) -> print_dac_state(N) end, Nodes). @@ -1450,9 +1407,7 @@ print_dac_state(Nodes) when is_list(Nodes) -> %% Ticket: OTP-4227 %% Slogan: Bad return value from application. %%----------------------------------------------------------------- -otp_4227(suite) -> []; -otp_4227(doc) -> - ["Test start of depending app when required app crashed."]; +%% Test start of depending app when required app crashed. otp_4227(Conf) when is_list(Conf) -> NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), NoSyncTime = config_fun_fast(config_4227(NodeNames)), @@ -1475,11 +1430,11 @@ otp_4227(Conf) when is_list(Conf) -> %% Start app9 and brutally kill it, then try to start app10 ok = rpc:call(Cp1, application, start, [app9]), - test_server:sleep(1000), + ct:sleep(1000), Pid9 = rpc:call(Cp1, erlang, whereis, [ch_sup19]), true = erlang:is_pid(Pid9), true = erlang:exit(Pid9, kill), - test_server:sleep(1000), + ct:sleep(1000), %% This gave {error, no_report} before the patch {error, {not_running, app9}} = @@ -1518,7 +1473,7 @@ otp_5363(Conf) when is_list(Conf) -> %% the code, but only that the correct processes ARE killed. OldPath = code:get_path(), - code:add_patha(?config(data_dir,Conf)), + code:add_patha(proplists:get_value(data_dir,Conf)), try ok = application:load(app_group_leader()), ok = application:start(group_leader), @@ -1532,7 +1487,7 @@ otp_5363(Conf) when is_list(Conf) -> undefined = whereis(nisse); Bad -> io:format("~p\n", [Bad]), - ?t:fail() + ct:fail(failed) end after code:set_path(OldPath) @@ -1543,14 +1498,12 @@ otp_5363(Conf) when is_list(Conf) -> %% Ticket: OTP-5606 %% Slogan: Problems with starting a distributed application %%----------------------------------------------------------------- -otp_5606(suite) -> []; -otp_5606(doc) -> - ["Test of several processes simultanously starting the same " - "distributed application."]; +%% Test of several processes simultaneously starting the same +%% distributed application. otp_5606(Conf) when is_list(Conf) -> %% Write a config file - Dir = ?config(priv_dir, Conf), + Dir = proplists:get_value(priv_dir, Conf), {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]), NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf), (config4(NodeNames))(Fd, 10000), @@ -1586,7 +1539,7 @@ otp_5606(Conf) when is_list(Conf) -> [Res1, Res2, Res3, Res4] -> Txt = io_lib:format("Illegal results from start ~p ~p ~p ~p", [Res1, Res2, Res3, Res4]), - test_server:fail(lists:flatten(Txt)) + ct:fail(lists:flatten(Txt)) end, {error, {already_started, app1}} = @@ -1601,7 +1554,7 @@ otp_5606_loop(ResL) when length(ResL)<4 -> {_Pid, Res} -> otp_5606_loop([Res|ResL]) after 5000 -> - test_server:fail(timeout_waiting_for_res) + ct:fail(timeout_waiting_for_res) end; otp_5606_loop(ResL) -> ResL. @@ -1613,9 +1566,7 @@ loop5606(Pid) -> Pid ! {self(), Res} end. -get_env(suite) -> []; -get_env(doc) -> - ["Tests get_env/* functions"]; +%% Tests get_env/* functions. get_env(Conf) when is_list(Conf) -> {ok, _} = application:get_env(kernel, error_logger), undefined = application:get_env(undefined_app, a), @@ -1627,14 +1578,12 @@ get_env(Conf) when is_list(Conf) -> %% Should be started in a CC view with: %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -get_key(suite) -> []; -get_key(doc) -> - ["Tests read the .app keys."]; +%% Tests read the .app keys. get_key(Conf) when is_list(Conf) -> NodeNames = [Ncp1, _Ncp2, _Ncp3] = node_names([cp1, cp2, cp3], Conf), WithSyncTime = config_fun(config_inc(NodeNames)), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_config(Ncp1, WithSyncTime, Conf), ok = rpc:call(Cp1, application, load, [appinc(), d3(NodeNames)]), @@ -1731,8 +1680,7 @@ get_key(Conf) when is_list(Conf) -> %%% Testing of change of distributed parameter. %%%----------------------------------------------------------------- -distr_changed_tc1(suite) -> []; -distr_changed_tc1(doc) -> ["Test change of distributed parameter."]; +%% Test change of distributed parameter. distr_changed_tc1(Conf) when is_list(Conf) -> {OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {_Ncp1, _Ncp2, _Ncp3}, _Config2} = @@ -1757,7 +1705,7 @@ distr_changed_tc1(Conf) when is_list(Conf) -> rpc:multicall([Cp1, Cp2, Cp3], application_controller, config_change, [OldEnv]), - test_server:sleep(7000), + ct:sleep(7000), DcInfo1 = rpc:call(Cp1, dist_ac, info, []), DcInfo2 = rpc:call(Cp2, dist_ac, info, []), @@ -1778,7 +1726,7 @@ distr_changed_tc1(Conf) when is_list(Conf) -> ok; EWa1 -> X1 = io_lib:format("distribution error: Cp1 ~p ",[EWa1]), - test_server:fail(lists:flatten(X1)) + ct:fail(lists:flatten(X1)) end, case lists:sort(Wa2) of @@ -1786,7 +1734,7 @@ distr_changed_tc1(Conf) when is_list(Conf) -> ok; EWa2 -> X2 = io_lib:format("distribution error: Cp2 ~p ",[EWa2]), - test_server:fail(lists:flatten(X2)) + ct:fail(lists:flatten(X2)) end, case lists:sort(Wa3) of @@ -1794,7 +1742,7 @@ distr_changed_tc1(Conf) when is_list(Conf) -> ok; EWa3 -> X3 = io_lib:format("distribution error: Cp3 ~p ",[EWa3]), - test_server:fail(lists:flatten(X3)) + ct:fail(lists:flatten(X3)) end, DcInfo1n = rpc:call(Cp1, dist_ac, info, []), @@ -1816,9 +1764,7 @@ distr_changed_tc1(Conf) when is_list(Conf) -> ok. -distr_changed_tc2(suite) -> []; -distr_changed_tc2(doc) -> ["Test change of distributed parameter, " - "move appls by crashing a node."]; +%% Test change of distributed parameter, move appls by crashing a node. distr_changed_tc2(Conf) when is_list(Conf) -> {OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {Ncp1, _Ncp2, _Ncp3}, Config2} = @@ -1843,21 +1789,16 @@ distr_changed_tc2(Conf) when is_list(Conf) -> rpc:multicall([Cp1, Cp2, Cp3], application_controller, config_change, [OldEnv]), - test_server:sleep(4000), + ct:sleep(4000), stop_node_nice(Cp1), - test_server:sleep(10000), + ct:sleep(10000), -% _DcInfo1 = rpc:call(Cp1, dist_ac, info, []), _DcInfo2 = rpc:call(Cp2, dist_ac, info, []), _DcInfo3 = rpc:call(Cp3, dist_ac, info, []), -% ?t:format(0,"#### DcInfo1 ~n~p~n",[_DcInfo1]), -% DcWa1 = which_applications(Cp1), DcWa2 = which_applications(Cp2), DcWa3 = which_applications(Cp3), -% Wa1 = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, -% [], DcWa1), Wa2 = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, [], DcWa2), Wa3 = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, @@ -1869,7 +1810,7 @@ distr_changed_tc2(Conf) when is_list(Conf) -> ok; EWa2 -> X2 = io_lib:format("distribution error: Cp2 ~p ",[EWa2]), - test_server:fail(lists:flatten(X2)) + ct:fail(lists:flatten(X2)) end, case lists:sort(Wa3) of @@ -1877,12 +1818,12 @@ distr_changed_tc2(Conf) when is_list(Conf) -> ok; EWa3 -> X3 = io_lib:format("distribution error: Cp3 ~p ",[EWa3]), - test_server:fail(lists:flatten(X3)) + ct:fail(lists:flatten(X3)) end, {ok, Cp1} = start_node_boot(Ncp1, Config2, dc), - test_server:sleep(10000), + ct:sleep(10000), _DcInfo1rs = rpc:call(Cp1, dist_ac, info, []), _DcInfo2rs = rpc:call(Cp2, dist_ac, info, []), @@ -1904,7 +1845,7 @@ distr_changed_tc2(Conf) when is_list(Conf) -> ok; EWa1rs -> X1rs = io_lib:format("distribution error: Cp1 ~p ",[EWa1rs]), - test_server:fail(lists:flatten(X1rs)) + ct:fail(lists:flatten(X1rs)) end, case lists:sort(Wa2rs) of @@ -1912,7 +1853,7 @@ distr_changed_tc2(Conf) when is_list(Conf) -> ok; EWa2rs -> X2rs = io_lib:format("distribution error: Cp2 ~p ",[EWa2rs]), - test_server:fail(lists:flatten(X2rs)) + ct:fail(lists:flatten(X2rs)) end, case lists:sort(Wa3rs) of @@ -1920,7 +1861,7 @@ distr_changed_tc2(Conf) when is_list(Conf) -> ok; EWa3rs -> X3rs = io_lib:format("distribution error: Cp3 ~p ",[EWa3rs]), - test_server:fail(lists:flatten(X3rs)) + ct:fail(lists:flatten(X3rs)) end, @@ -1939,15 +1880,12 @@ distr_changed_tc2(Conf) when is_list(Conf) -> %%%----------------------------------------------------------------- %%% Testing of application configuration change %%%----------------------------------------------------------------- -config_change(suite) -> - []; -config_change(doc) -> - ["Test change of application configuration"]; +%% Test change of application configuration. config_change(Conf) when is_list(Conf) -> %% Change to data_dir {ok, CWD} = file:get_cwd(), - DataDir = ?config(data_dir, Conf), + DataDir = proplists:get_value(data_dir, Conf), ok = file:set_cwd(DataDir), %% Find out application data from boot script @@ -2009,10 +1947,7 @@ get_appls([], Res) -> Res. -persistent_env(suite) -> - []; -persistent_env(doc) -> - ["Test set_env/4 and unset_env/3 with persistent true"]; +%% Test set_env/4 and unset_env/3 with persistent true. persistent_env(Conf) when is_list(Conf) -> ok = application:set_env(appinc, own2, persist, [{persistent, true}]), ok = application:set_env(appinc, key1, persist, [{persistent, true}]), @@ -2056,10 +1991,7 @@ persistent_env(Conf) when is_list(Conf) -> %%%----------------------------------------------------------------- %%% Tests the 'shutdown_func' kernel config parameter %%%----------------------------------------------------------------- -shutdown_func(suite) -> - []; -shutdown_func(doc) -> - ["Tests the 'shutdown_func' kernel config parameter"]; +%% Tests the 'shutdown_func' kernel config parameter. shutdown_func(Config) when is_list(Config) -> {ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_func"), wait_for_ready_net(), @@ -2077,10 +2009,10 @@ shutdown_func(Config) when is_list(Config) -> {'DOWN', Mref, _, Pid, noconnection} -> ok after 10000 -> - test_server:fail(timeout) + ct:fail(timeout) end after 10000 -> - test_server:fail(timeout) + ct:fail(timeout) end. @@ -2098,7 +2030,7 @@ do_shutdown(Reason) -> %%% Tests the 'shutdown_timeout' kernel config parameter %%%----------------------------------------------------------------- shutdown_timeout(Config) when is_list(Config) -> - DataDir = ?config(data_dir,Config), + DataDir = proplists:get_value(data_dir,Config), {ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_timeout"), wait_for_ready_net(), ok = rpc:call(Cp1, application, set_env, [kernel, shutdown_timeout, 1000]), @@ -2121,7 +2053,7 @@ shutdown_timeout(Config) when is_list(Config) -> %%% Provokes a (previous) application shutdown deadlock %%%----------------------------------------------------------------- shutdown_deadlock(Config) when is_list(Config) -> - DataDir = ?config(data_dir,Config), + DataDir = proplists:get_value(data_dir,Config), code:add_path(filename:join([DataDir,deadlock])), %% ok = rpc:call(Cp1, application, start, [sasl]), ok = application:start(deadlock), @@ -2596,7 +2528,7 @@ is_started(Name, Node) -> false -> false end. -% Waits until application Name is started on at least one node. +%% Waits until application Name is started on at least one node. wait_until_started(Name, Nodes) -> case lists:member(true, lists:map(fun (N) -> @@ -2606,11 +2538,11 @@ wait_until_started(Name, Nodes) -> true -> true; false -> - test_server:sleep(500), + ct:sleep(500), wait_until_started(Name, Nodes) end. -% Waits until application Name is stopped on all nodes. +%% Waits until application Name is stopped on all nodes. wait_until_stopped(Name, Nodes) -> case lists:member(true, lists:map(fun (N) -> @@ -2620,7 +2552,7 @@ wait_until_stopped(Name, Nodes) -> false -> true; true -> - test_server:sleep(500), + ct:sleep(500), wait_until_stopped(Name, Nodes) end. @@ -2662,13 +2594,13 @@ start_node_args(Name, Args) -> start_node_boot_3002(Name, Boot) -> Pa = filename:dirname(code:which(?MODULE)), - ?t:format(0, "start_node_boot ~p~n", - [" -pa " ++ Pa ++ " -env ERL_CRASH_DUMP erl_crash_dump." ++ - atom_to_list(Name) ++ " -boot " ++ Boot ++ - " -sasl dummy \"missing "]), + ct:pal(?HI_VERBOSITY, "start_node_boot ~p~n", + [" -pa " ++ Pa ++ " -env ERL_CRASH_DUMP erl_crash_dump." ++ + atom_to_list(Name) ++ " -boot " ++ Boot ++ + " -sasl dummy \"missing "]), test_server:start_node(Name, slave, [{args, " -pa " ++ Pa ++ - " -env ERL_CRASH_DUMP erl_crash_dump." ++ + " -env ERL_CRASH_DUMP erl_crash_dump." ++ atom_to_list(Name) ++ " -boot " ++ Boot ++ " -sasl dummy \"missing "}]). @@ -2678,18 +2610,20 @@ start_node_boot_config(Name, SysConfigFun, Conf, Boot) -> start_node_boot(Name, Config, Boot) -> Pa = filename:dirname(code:which(?MODULE)), - ?t:format(0, "start_node_boot ~p~n",[" -pa " ++ Pa ++ " -config " ++ Config ++ - " -boot " ++ atom_to_list(Boot)]), - test_server:start_node(Name, slave, [{args, " -pa " ++ Pa ++ " -config " ++ Config ++ - " -boot " ++ atom_to_list(Boot)}]). + ct:pal(?HI_VERBOSITY, + "start_node_boot ~p~n",[" -pa " ++ Pa ++ " -config " ++ Config ++ + " -boot " ++ atom_to_list(Boot)]), + test_server:start_node(Name, slave, + [{args, " -pa " ++ Pa ++ " -config " ++ Config ++ + " -boot " ++ atom_to_list(Boot)}]). start_node_config_sf(Name, SysConfigFun, Conf) -> ConfigFile = write_config_file(SysConfigFun, Conf), - DataDir = ?config(data_dir, Conf), % is it used? + DataDir = proplists:get_value(data_dir, Conf), % is it used? start_node(Name, ConfigFile, " -pa " ++ DataDir). write_config_file(SysConfigFun, Conf) -> - Dir = ?config(priv_dir, Conf), + Dir = proplists:get_value(priv_dir, Conf), {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]), SysConfigFun(Fd), file:close(Fd), @@ -2713,8 +2647,8 @@ get_start_type(Expected) -> get_start_type(Expected, 30*5, #st{}). get_start_type(_Expected, 0, Ack) -> - test_server:format("====== ~p ======~n", [Ack]), - test_server:fail(not_valid_start_type); + io:format("====== ~p ======~n", [Ack]), + ct:fail(not_valid_start_type); get_start_type(Expected, Times, Ack0) -> #st{normal = N0, local = L0, takeover = T0, failover = F0} = Ack0, global:send(st_type, {st, read, self()}), @@ -2760,13 +2694,13 @@ get_start_phase(Expected) -> Expected -> ok; {sp, T1, I1, So1, Sp1, G1} -> - test_server:format("=============== {sp,T,I,So,Sp,G} ~p ~n",[" "]), - test_server:format("=========== got ~p ~n", + io:format("=============== {sp,T,I,So,Sp,G} ~p ~n",[" "]), + io:format("=========== got ~p ~n", [{sp, T1, I1, So1, Sp1, G1}]), - test_server:format("====== expected ~p ~n", [Expected]), - test_server:fail(not_valid_start_phase) + io:format("====== expected ~p ~n", [Expected]), + ct:fail(not_valid_start_phase) after 5000 -> - test_server:fail(not_valid_start_phase) + ct:fail(not_valid_start_phase) end. start_phase() -> @@ -2797,10 +2731,10 @@ get_conf_change(Expected) -> {cc, Expected} -> ok; {cc, List} -> - test_server:format("====== ~p ======~n",[{cc, List}]), - test_server:fail(not_valid_conf_change) + io:format("====== ~p ======~n",[{cc, List}]), + ct:fail(not_valid_conf_change) after 5000 -> - test_server:fail(not_valid_conf_change_to) + ct:fail(not_valid_conf_change_to) end. conf_change() -> @@ -2896,7 +2830,7 @@ create_script_3002(ScriptName) -> distr_changed_prep(Conf) when is_list(Conf) -> - % Write .app files + %% Write .app files {ok, Fd1} = file:open("app1.app", [write]), w_app1(Fd1), file:close(Fd1), @@ -2917,7 +2851,7 @@ distr_changed_prep(Conf) when is_list(Conf) -> file:close(Fd6), - % Create the .app files and the boot script + %% Create the .app files and the boot script {{KernelVer,StdlibVer}, _} = create_script_dc("dc"), case is_real_system(KernelVer, StdlibVer) of @@ -2933,13 +2867,13 @@ distr_changed_prep(Conf) when is_list(Conf) -> NoSyncTime = config_fun_fast(config_dc(NodeNames)), WithSyncTime = config_fun(config_dc(NodeNames)), - Dir = ?config(priv_dir,Conf), + Dir = proplists:get_value(priv_dir,Conf), {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]), (config_dc2(NodeNames))(Fd_dc2), file:close(Fd_dc2), Config2 = filename:join(Dir, "sys2"), - % Test [cp1, cp2, cp3] + %% Test [cp1, cp2, cp3] {ok, Cp1} = start_node_boot_config(Ncp1, NoSyncTime, Conf, dc), {ok, Cp2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, dc), {ok, Cp3} = start_node_boot_config(Ncp3, WithSyncTime, Conf, dc), diff --git a/lib/kernel/test/application_SUITE_data/app_start_error.erl b/lib/kernel/test/application_SUITE_data/app_start_error.erl index 531a10d442..aedcb537d8 100644 --- a/lib/kernel/test/application_SUITE_data/app_start_error.erl +++ b/lib/kernel/test/application_SUITE_data/app_start_error.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/application_SUITE_data/group_leader.erl b/lib/kernel/test/application_SUITE_data/group_leader.erl index e791437272..f18cef179b 100644 --- a/lib/kernel/test/application_SUITE_data/group_leader.erl +++ b/lib/kernel/test/application_SUITE_data/group_leader.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2016. 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/kernel/test/application_SUITE_data/group_leader_sup.erl b/lib/kernel/test/application_SUITE_data/group_leader_sup.erl index ade8de8470..6e0df632c3 100644 --- a/lib/kernel/test/application_SUITE_data/group_leader_sup.erl +++ b/lib/kernel/test/application_SUITE_data/group_leader_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2016. 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/kernel/test/application_SUITE_data/trans_abnormal_sup.erl b/lib/kernel/test/application_SUITE_data/trans_abnormal_sup.erl index 98d7e90235..bc2bf84089 100644 --- a/lib/kernel/test/application_SUITE_data/trans_abnormal_sup.erl +++ b/lib/kernel/test/application_SUITE_data/trans_abnormal_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/application_SUITE_data/trans_normal_sup.erl b/lib/kernel/test/application_SUITE_data/trans_normal_sup.erl index 233a79d8c3..c839888e39 100644 --- a/lib/kernel/test/application_SUITE_data/trans_normal_sup.erl +++ b/lib/kernel/test/application_SUITE_data/trans_normal_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/application_SUITE_data/transient.erl b/lib/kernel/test/application_SUITE_data/transient.erl index a58bc4600e..83cdacf673 100644 --- a/lib/kernel/test/application_SUITE_data/transient.erl +++ b/lib/kernel/test/application_SUITE_data/transient.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl index c3840f3d16..2369dd8b71 100644 --- a/lib/kernel/test/bif_SUITE.erl +++ b/lib/kernel/test/bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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. @@ -22,35 +22,33 @@ init_per_group/2,end_per_group/2]). -export([ - spawn1/1, spawn2/1, spawn3/1, spawn4/1, + spawn1/1, spawn2/1, spawn3/1, spawn4/1, - - spawn_link1/1, spawn_link2/1, spawn_link3/1, spawn_link4/1, - - spawn_opt2/1, spawn_opt3/1, spawn_opt4/1, spawn_opt5/1, + spawn_link1/1, spawn_link2/1, spawn_link3/1, spawn_link4/1, - spawn_failures/1, - run_fun/1, - wilderness/1]). + spawn_opt2/1, spawn_opt3/1, spawn_opt4/1, spawn_opt5/1, --export([init_per_testcase/2, end_per_testcase/2]). + spawn_failures/1, + + run_fun/1, + decode_packet_delim/1, + wilderness/1]). --include_lib("test_server/include/test_server.hrl"). +-export([init_per_testcase/2, end_per_testcase/2]). -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(1)). +-include_lib("common_test/include/ct.hrl"). init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), + Config. + +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [{group, spawn_tests}, {group, spawn_link_tests}, @@ -76,360 +74,333 @@ end_per_group(_GroupName, Config) -> Config. -spawn1(doc) -> ["Test spawn/1"]; -spawn1(suite) -> - []; +%% Test spawn/1. spawn1(Config) when is_list(Config) -> - ?line Node = node(), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - % spawn - ?line P = spawn(fun() -> Parent ! {self(), fetch_proc_vals(self())} end), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(false, normal, FA, 0, PV) - end, + Node = node(), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + %% spawn + P = spawn(fun() -> Parent ! {self(), fetch_proc_vals(self())} end), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(false, normal, FA, 0, PV) + end, ok. -spawn2(doc) -> ["Test spawn/2"]; -spawn2(suite) -> - []; +%% Test spawn/2. spawn2(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(spawn2), + {ok, Node} = start_node(spawn2), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), - % spawn_link - ?line P = spawn(Node, - fun() -> Parent ! {self(), fetch_proc_vals(self())} end), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(false, normal, FA, 0, PV) - end, + %% spawn_link + P = spawn(Node, + fun() -> Parent ! {self(), fetch_proc_vals(self())} end), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(false, normal, FA, 0, PV) + end, - ?line true = stop_node(Node), + true = stop_node(Node), ok. -spawn3(doc) -> ["Test spawn/3"]; -spawn3(suite) -> - []; +%% Test spawn/3. spawn3(Config) when is_list(Config) -> - ?line Node = node(), - - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - % spawn_link - ?line P = spawn(?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end]), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(false, normal, FA, 0, PV) - end, + Node = node(), + + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + %% spawn_link + P = spawn(?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end]), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(false, normal, FA, 0, PV) + end, ok. -spawn4(doc) -> ["Test spawn/4"]; -spawn4(suite) -> - []; +%% Test spawn/4. spawn4(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(spawn4), - - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - % spawn_link - ?line P = spawn(Node, - ?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end]), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(false, normal, FA, 0, PV) - end, - - ?line true = stop_node(Node), + {ok, Node} = start_node(spawn4), + + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + %% spawn_link + P = spawn(Node, + ?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end]), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(false, normal, FA, 0, PV) + end, + + true = stop_node(Node), ok. -spawn_link1(doc) -> ["Test spawn_link/1"]; -spawn_link1(suite) -> - []; +%% Test spawn_link/1. spawn_link1(Config) when is_list(Config) -> - ?line Node = node(), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - % spawn_link - ?line P = spawn_link(fun() -> Parent ! {self(), fetch_proc_vals(self())} end), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(true, normal, FA, 0, PV) - end, + Node = node(), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + %% spawn_link + P = spawn_link(fun() -> Parent ! {self(), fetch_proc_vals(self())} end), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(true, normal, FA, 0, PV) + end, ok. -spawn_link2(doc) -> ["Test spawn_link/2"]; -spawn_link2(suite) -> - []; +%% Test spawn_link/2. spawn_link2(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(spawn_link2), + {ok, Node} = start_node(spawn_link2), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), - % spawn_link - ?line P = spawn_link(Node, - fun() -> Parent ! {self(), fetch_proc_vals(self())} end), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(true, normal, FA, 0, PV) - end, + %% spawn_link + P = spawn_link(Node, + fun() -> Parent ! {self(), fetch_proc_vals(self())} end), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(true, normal, FA, 0, PV) + end, - ?line true = stop_node(Node), + true = stop_node(Node), ok. -spawn_link3(doc) -> ["Test spawn_link/3"]; -spawn_link3(suite) -> - []; +%% Test spawn_link/3. spawn_link3(Config) when is_list(Config) -> - ?line Node = node(), - - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - % spawn_link - ?line P = spawn_link(?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end]), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(true, normal, FA, 0, PV) - end, + Node = node(), + + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + %% spawn_link + P = spawn_link(?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end]), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(true, normal, FA, 0, PV) + end, ok. -spawn_link4(doc) -> ["Test spawn_link/4"]; -spawn_link4(suite) -> - []; +%% Test spawn_link/4. spawn_link4(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(spawn_link4), - - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - % spawn_link - ?line P = spawn_link(Node, - ?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end]), - ?line receive - {P, PV} -> - ?line Node = node(P), - ?line check_proc_vals(true, normal, FA, 0, PV) - end, - - ?line true = stop_node(Node), + {ok, Node} = start_node(spawn_link4), + + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + %% spawn_link + P = spawn_link(Node, + ?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end]), + receive + {P, PV} -> + Node = node(P), + check_proc_vals(true, normal, FA, 0, PV) + end, + + true = stop_node(Node), ok. -spawn_opt2(doc) -> ["Test spawn_opt/2"]; -spawn_opt2(suite) -> - []; +%% Test spawn_opt/2. spawn_opt2(Config) when is_list(Config) -> - ?line Node = node(), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - - ?line P1 = spawn_opt(fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end, - [{fullsweep_after, 0},{min_heap_size, 1000}, - link, {priority, max}]), - ?line receive - {P1, PV1} -> - ?line Node = node(P1), - ?line check_proc_vals(true, max, 0, 1000, PV1) - end, - ?line P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end, - [{min_heap_size, 10}]), - ?line receive - {P2, PV2} -> - ?line Node = node(P2), - ?line check_proc_vals(false, normal, FA, 10, PV2) - end, + Node = node(), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + + P1 = spawn_opt(fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end, + [{fullsweep_after, 0},{min_heap_size, 1000}, + link, {priority, max}]), + receive + {P1, PV1} -> + Node = node(P1), + check_proc_vals(true, max, 0, 1000, PV1) + end, + P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end, + [{min_heap_size, 10}]), + receive + {P2, PV2} -> + Node = node(P2), + check_proc_vals(false, normal, FA, 10, PV2) + end, ok. -spawn_opt3(doc) -> ["Test spawn_opt/3"]; -spawn_opt3(suite) -> - []; +%% Test spawn_opt/3. spawn_opt3(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(spawn_opt3), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - ?line P1 = spawn_opt(Node, - fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end, - [{fullsweep_after,0}, {min_heap_size,1000}, - link, {priority, max}]), - ?line receive - {P1, PV1} -> - ?line Node = node(P1), - ?line check_proc_vals(true, max, 0, 1000, PV1) - end, - ?line P2 = spawn_opt(Node, - fun() -> Parent ! {self(), fetch_proc_vals(self())} end, - [{min_heap_size, 10}]), - ?line receive - {P2, PV2} -> - ?line Node = node(P2), - ?line check_proc_vals(false, normal, FA, 10, PV2) - end, - ?line true = stop_node(Node), + {ok, Node} = start_node(spawn_opt3), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + P1 = spawn_opt(Node, + fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end, + [{fullsweep_after,0}, {min_heap_size,1000}, + link, {priority, max}]), + receive + {P1, PV1} -> + Node = node(P1), + check_proc_vals(true, max, 0, 1000, PV1) + end, + P2 = spawn_opt(Node, + fun() -> Parent ! {self(), fetch_proc_vals(self())} end, + [{min_heap_size, 10}]), + receive + {P2, PV2} -> + Node = node(P2), + check_proc_vals(false, normal, FA, 10, PV2) + end, + true = stop_node(Node), ok. -spawn_opt4(doc) -> ["Test spawn_opt/4"]; -spawn_opt4(suite) -> - []; +%% Test spawn_opt/4. spawn_opt4(Config) when is_list(Config) -> - ?line Node = node(), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - ?line P1 = spawn_opt(?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end], - [{fullsweep_after,0}, {min_heap_size,1000}, - link, {priority, max}]), - ?line receive - {P1, PV1} -> - ?line Node = node(P1), - ?line check_proc_vals(true, max, 0, 1000, PV1) - end, - ?line P2 = spawn_opt(?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end], - [{min_heap_size, 10}]), - ?line receive - {P2, PV2} -> - ?line Node = node(P2), - ?line check_proc_vals(false, normal, FA, 10, PV2) - end, + Node = node(), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + P1 = spawn_opt(?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end], + [{fullsweep_after,0}, {min_heap_size,1000}, + link, {priority, max}]), + receive + {P1, PV1} -> + Node = node(P1), + check_proc_vals(true, max, 0, 1000, PV1) + end, + P2 = spawn_opt(?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end], + [{min_heap_size, 10}]), + receive + {P2, PV2} -> + Node = node(P2), + check_proc_vals(false, normal, FA, 10, PV2) + end, ok. -spawn_opt5(doc) -> ["Test spawn_opt/5"]; -spawn_opt5(suite) -> - []; +%% Test spawn_opt/5. spawn_opt5(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(spawn_opt5), - ?line Parent = self(), - ?line {_, _, FA, _} = fetch_proc_vals(self()), - ?line P1 = spawn_opt(Node, - ?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end], - [{fullsweep_after,0}, {min_heap_size,1000}, - link, {priority, max}]), - ?line receive - {P1, PV1} -> - ?line Node = node(P1), - ?line check_proc_vals(true, max, 0, 1000, PV1) - end, - ?line P2 = spawn_opt(Node, - ?MODULE, - run_fun, - [fun() -> - Parent ! {self(), fetch_proc_vals(self())} - end], - [{min_heap_size, 10}]), - ?line receive - {P2, PV2} -> - ?line Node = node(P2), - ?line check_proc_vals(false, normal, FA, 10, PV2) - end, - ?line true = stop_node(Node), + {ok, Node} = start_node(spawn_opt5), + Parent = self(), + {_, _, FA, _} = fetch_proc_vals(self()), + P1 = spawn_opt(Node, + ?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end], + [{fullsweep_after,0}, {min_heap_size,1000}, + link, {priority, max}]), + receive + {P1, PV1} -> + Node = node(P1), + check_proc_vals(true, max, 0, 1000, PV1) + end, + P2 = spawn_opt(Node, + ?MODULE, + run_fun, + [fun() -> + Parent ! {self(), fetch_proc_vals(self())} + end], + [{min_heap_size, 10}]), + receive + {P2, PV2} -> + Node = node(P2), + check_proc_vals(false, normal, FA, 10, PV2) + end, + true = stop_node(Node), ok. -spawn_failures(doc) -> - ["Test failure behavior of spawn bifs"]; -spawn_failures(suite) -> - []; +%% Test failure behavior of spawn bifs. spawn_failures(Config) when is_list(Config) -> - ?line ThisNode = node(), - ?line {ok, Node} = start_node(spawn_remote_failure), - - % unknown nodes - test_server:format("Testing unknown nodes~n", []), - ?line CrashPid1 = (catch spawn_opt('unknown@node', - erlang, - nodes, - [], - [])), - ?line true = is_pid(CrashPid1), - ?line ThisNode = node(CrashPid1), - ?line CrashPid2 = (catch spawn_opt('unknown@node', - fun () -> erlang:nodes() end, - [])), - ?line true = is_pid(CrashPid2), - ?line ThisNode = node(CrashPid2), - - ?line CrashPid3 = (catch spawn('unknown@node', - erlang, - nodes, - [])), - ?line true = is_pid(CrashPid3), - ?line ThisNode = node(CrashPid3), - ?line CrashPid4 = (catch spawn('unknown@node', - fun () -> erlang:nodes() end)), - ?line true = is_pid(CrashPid4), - ?line ThisNode = node(CrashPid4), - - ?line OTE = process_flag(trap_exit,true), - ?line CrashPid5 = (catch spawn_link('unknown@node', - erlang, - nodes, - [])), + ThisNode = node(), + {ok, Node} = start_node(spawn_remote_failure), + + %% unknown nodes + io:format("Testing unknown nodes~n", []), + CrashPid1 = (catch spawn_opt('unknown@node', + erlang, + nodes, + [], + [])), + true = is_pid(CrashPid1), + ThisNode = node(CrashPid1), + CrashPid2 = (catch spawn_opt('unknown@node', + fun () -> erlang:nodes() end, + [])), + true = is_pid(CrashPid2), + ThisNode = node(CrashPid2), + + CrashPid3 = (catch spawn('unknown@node', + erlang, + nodes, + [])), + true = is_pid(CrashPid3), + ThisNode = node(CrashPid3), + CrashPid4 = (catch spawn('unknown@node', + fun () -> erlang:nodes() end)), + true = is_pid(CrashPid4), + ThisNode = node(CrashPid4), + + OTE = process_flag(trap_exit,true), + CrashPid5 = (catch spawn_link('unknown@node', + erlang, + nodes, + [])), receive {'EXIT', CrashPid5, noconnection} -> - ?line true = is_pid(CrashPid5), - ?line ThisNode = node(CrashPid5) + true = is_pid(CrashPid5), + ThisNode = node(CrashPid5) end, - ?line CrashPid6 = (catch spawn_link('unknown@node', - fun () -> erlang:nodes() end)), + CrashPid6 = (catch spawn_link('unknown@node', + fun () -> erlang:nodes() end)), receive {'EXIT', CrashPid6, noconnection} -> - ?line true = is_pid(CrashPid6), - ?line ThisNode = node(CrashPid6) + true = is_pid(CrashPid6), + ThisNode = node(CrashPid6) end, process_flag(trap_exit,OTE), case OTE of false -> receive {'EXIT', P, R} -> - ?line test_server:fail({'EXIT', P, R}) + ct:fail({'EXIT', P, R}) after 0 -> ok end; @@ -437,123 +408,125 @@ spawn_failures(Config) when is_list(Config) -> ok end, - % bad node - test_server:format("Testing bad nodes~n", []), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt("Node",erlang,nodes,[],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt("Node", - fun () -> - erlang:nodes() - end, - [])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link("Node", - fun () -> - erlang:nodes() - end)), - ?line {'EXIT', {badarg, _}} = (catch spawn("Node",erlang,nodes,[])), - ?line {'EXIT', {badarg, _}} = (catch spawn("Node", - fun () -> - erlang:nodes() - end)), - - % bad module - test_server:format("Testing bad modules~n", []), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,"erlang",nodes,[],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt("erlang",nodes,[],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,"erlang",nodes,[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link("erlang",nodes,[])), - ?line {'EXIT', {badarg, _}} = (catch spawn(Node,"erlang",nodes,[])), - ?line {'EXIT', {badarg, _}} = (catch spawn("erlang",nodes,[])), - - % bad function - test_server:format("Testing bad functions~n", []), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,"nodes",[],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,not_a_fun,[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,"nodes",[],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(not_a_fun,[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,"nodes",[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,not_a_fun)), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(erlang,"nodes",[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(not_a_fun)), - ?line {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,"nodes",[])), - ?line {'EXIT', {badarg, _}} = (catch spawn(Node,not_a_fun)), - ?line {'EXIT', {badarg, _}} = (catch spawn(erlang,"nodes",[])), - ?line {'EXIT', {badarg, _}} = (catch spawn(not_a_fun)), - - - % bad argument - test_server:format("Testing bad arguments~n", []), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[a|b],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[a|b],[])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,nodes,[a|b])), - ?line {'EXIT', {badarg, _}} = (catch spawn_link(erlang,nodes,[a|b])), - ?line {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,nodes,[a|b])), - ?line {'EXIT', {badarg, _}} = (catch spawn(erlang,nodes,[a|b])), - - % bad option - test_server:format("Testing bad options~n", []), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[],[a|b])), - ?line {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[],[a|b])), - - - ?line true = stop_node(Node), + %% bad node + io:format("Testing bad nodes~n", []), + {'EXIT', {badarg, _}} = (catch spawn_opt("Node",erlang,nodes,[],[])), + {'EXIT', {badarg, _}} = (catch spawn_opt("Node", + fun () -> + erlang:nodes() + end, + [])), + {'EXIT', {badarg, _}} = (catch spawn_link("Node", + fun () -> + erlang:nodes() + end)), + {'EXIT', {badarg, _}} = (catch spawn("Node",erlang,nodes,[])), + {'EXIT', {badarg, _}} = (catch spawn("Node", + fun () -> + erlang:nodes() + end)), + + %% bad module + io:format("Testing bad modules~n", []), + {'EXIT', {badarg, _}} = (catch spawn_opt(Node,"erlang",nodes,[],[])), + {'EXIT', {badarg, _}} = (catch spawn_opt("erlang",nodes,[],[])), + {'EXIT', {badarg, _}} = (catch spawn_link(Node,"erlang",nodes,[])), + {'EXIT', {badarg, _}} = (catch spawn_link("erlang",nodes,[])), + {'EXIT', {badarg, _}} = (catch spawn(Node,"erlang",nodes,[])), + {'EXIT', {badarg, _}} = (catch spawn("erlang",nodes,[])), + + %% bad function + io:format("Testing bad functions~n", []), + {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,"nodes",[],[])), + {'EXIT', {badarg, _}} = (catch spawn_opt(Node,not_a_fun,[])), + {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,"nodes",[],[])), + {'EXIT', {badarg, _}} = (catch spawn_opt(not_a_fun,[])), + {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,"nodes",[])), + {'EXIT', {badarg, _}} = (catch spawn_link(Node,not_a_fun)), + {'EXIT', {badarg, _}} = (catch spawn_link(erlang,"nodes",[])), + {'EXIT', {badarg, _}} = (catch spawn_link(not_a_fun)), + {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,"nodes",[])), + {'EXIT', {badarg, _}} = (catch spawn(Node,not_a_fun)), + {'EXIT', {badarg, _}} = (catch spawn(erlang,"nodes",[])), + {'EXIT', {badarg, _}} = (catch spawn(not_a_fun)), + + + %% bad argument + io:format("Testing bad arguments~n", []), + {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[a|b],[])), + {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[a|b],[])), + {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,nodes,[a|b])), + {'EXIT', {badarg, _}} = (catch spawn_link(erlang,nodes,[a|b])), + {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,nodes,[a|b])), + {'EXIT', {badarg, _}} = (catch spawn(erlang,nodes,[a|b])), + + %% bad option + io:format("Testing bad options~n", []), + {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[],[a|b])), + {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[],[a|b])), + + + true = stop_node(Node), ok. check_proc_vals(Link, Priority, FullsweepAfter, MinHeapSize, {Ls, P, FA, HS}) -> - ?line Link = lists:member(self(), Ls), - ?line Priority = P, + Link = lists:member(self(), Ls), + Priority = P, FullsweepAfter = FA, true = (HS >= MinHeapSize), - ?line ok. + ok. fetch_proc_vals(Pid) -> - ?line PI = process_info(Pid), - ?line {value,{links, Ls}} = lists:keysearch(links, 1, PI), - ?line {value,{priority,P}} = lists:keysearch(priority, 1, PI), + PI = process_info(Pid), + {value,{links, Ls}} = lists:keysearch(links, 1, PI), + {value,{priority,P}} = lists:keysearch(priority, 1, PI), {value,{garbage_collection,Gs}} = lists:keysearch(garbage_collection, 1, PI), {value,{fullsweep_after,FA}} = lists:keysearch(fullsweep_after, 1, Gs), {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), - ?line {Ls, P, FA, HS}. - -% This testcase should probably be moved somewhere else -wilderness(doc) -> - ["Test that memory allocation command line options affecting the" - "wilderness of the heap are interpreted correct by the emulator "]; -wilderness(suite) -> - []; + {Ls, P, FA, HS}. + +%% Test erlang:packet_delim/3 with {line_delimiter,0} option. +decode_packet_delim(Config) when is_list(Config) -> + {ok,<<"abc",0>>,<<"efg",0>>} = + erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]), + {more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []). + +%% This testcase should probably be moved somewhere else + +%% Test that memory allocation command line options affecting the +%% wilderness of the heap are interpreted correct by the emulator. wilderness(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?default_timeout), - ?line OKParams = {512, 8}, - ?line Alloc = erlang:system_info(allocator), - ?line test_server:format("Test server allocator info:~n~p", [Alloc]), + OKParams = {512, 8}, + Alloc = erlang:system_info(allocator), + io:format("Test server allocator info:~n~p", [Alloc]), Result = case Alloc of {Allocator, _, _, _} when Allocator == glibc; Allocator == dlmalloc -> - ?line run_wilderness_test(OKParams, OKParams), - ?line {comment, - "Allocator used: " ++ atom_to_list(Allocator)}; + run_wilderness_test(OKParams, OKParams), + {comment, + "Allocator used: " ++ atom_to_list(Allocator)}; {OtherAllocator, _, _, _} -> - ?line {skipped, - "Only run when glibc is used. " - "Allocator used: " - ++ atom_to_list(OtherAllocator)} + {skipped, + "Only run when glibc is used. " + "Allocator used: " + ++ atom_to_list(OtherAllocator)} end, - ?line test_server:timetrap_cancel(Dog), Result. - + run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) -> Self = self(), Ref = make_ref(), SuiteDir = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = test_server:start_node(allocator_test, - slave, - [{args, - " -pa " - ++ SuiteDir - ++" +MYtt "++to_string(Set_tt) - ++" +MYtp "++to_string(Set_tp)}, - {linked, false}]), + {ok, Node} = test_server:start_node(allocator_test, + slave, + [{args, + " -pa " + ++ SuiteDir + ++" +MYtt "++to_string(Set_tt) + ++" +MYtp "++to_string(Set_tp)}, + {linked, false}]), spawn(Node, fun () -> Self ! {Ref, erlang:system_info(allocator)} end), @@ -561,15 +534,15 @@ run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) -> {Ref, {A, V, F, S}} -> Ett = Exp_tt*1024, Etp = Exp_tp*1024, - ?line test_server:format("Test allocator info:~n~p", - [{A, V, F, S}]), - ?line {value, {sys_alloc, SA_Opts}} + io:format("Test allocator info:~n~p", + [{A, V, F, S}]), + {value, {sys_alloc, SA_Opts}} = lists:keysearch(sys_alloc, 1, S), - ?line {value, {tt, Ett}} = lists:keysearch(tt, 1, SA_Opts), - ?line {value, {tp, Etp}} = lists:keysearch(tp, 1, SA_Opts) + {value, {tt, Ett}} = lists:keysearch(tt, 1, SA_Opts), + {value, {tp, Etp}} = lists:keysearch(tp, 1, SA_Opts) end, stop_node(Node). - + to_string(X) when is_integer(X) -> integer_to_list(X); to_string(X) when is_atom(X) -> @@ -595,12 +568,12 @@ get_nodenames(N, T, Acc) -> ++ integer_to_list(C)) | Acc]). start_node(TestCase) -> - ?line [Name] = get_nodenames(1, TestCase), - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]). + [Name] = get_nodenames(1, TestCase), + Pa = filename:dirname(code:which(?MODULE)), + test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]). stop_node(Node) -> - ?line true = test_server:stop_node(Node). + true = test_server:stop_node(Node). run_fun(Fun) -> Fun(). diff --git a/lib/kernel/test/ch.erl b/lib/kernel/test/ch.erl index ba8aa9f05a..c9f378e387 100644 --- a/lib/kernel/test/ch.erl +++ b/lib/kernel/test/ch.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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/kernel/test/ch_sup.erl b/lib/kernel/test/ch_sup.erl index a297b60200..1d7f17fc95 100644 --- a/lib/kernel/test/ch_sup.erl +++ b/lib/kernel/test/ch_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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/kernel/test/cleanup.erl b/lib/kernel/test/cleanup.erl index 7eb0a9e140..db738c167e 100644 --- a/lib/kernel/test/cleanup.erl +++ b/lib/kernel/test/cleanup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. 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,7 @@ -export([all/0,groups/0,init_per_group/2,end_per_group/2, cleanup/1]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). all() -> [cleanup]. @@ -36,15 +36,14 @@ end_per_group(_GroupName, Config) -> Config. -cleanup(suite) -> []; cleanup(_) -> - ?line Localhost = list_to_atom(net_adm:localhost()), - ?line net_adm:world_list([Localhost]), - ?line case nodes() of - [] -> - ok; - Nodes when is_list(Nodes) -> - Kill = fun(Node) -> spawn(Node, erlang, halt, []) end, - ?line lists:foreach(Kill, Nodes), - ?line test_server:fail({nodes_left, Nodes}) - end. + Localhost = list_to_atom(net_adm:localhost()), + net_adm:world_list([Localhost]), + case nodes() of + [] -> + ok; + Nodes when is_list(Nodes) -> + Kill = fun(Node) -> spawn(Node, erlang, halt, []) end, + lists:foreach(Kill, Nodes), + ct:fail({nodes_left, Nodes}) + end. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index ef5303defd..569753155f 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -19,7 +19,8 @@ %% -module(code_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("syntax_tools/include/merl.hrl"). -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). -export([set_path/1, get_path/1, add_path/1, add_paths/1, del_path/1, @@ -30,12 +31,17 @@ upgrade/1, sticky_dir/1, pa_pz_option/1, add_del_path/1, dir_disappeared/1, ext_mod_dep/1, clash/1, - load_cached/1, start_node_with_cache/1, add_and_rehash/1, - where_is_file_cached/1, where_is_file_no_cache/1, + where_is_file/1, purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, - on_load_embedded/1, on_load_errors/1, big_boot_embedded/1, - native_early_modules/1, get_mode/1]). + on_load_embedded/1, on_load_errors/1, on_load_update/1, + on_load_trace_on_load/1, + on_load_purge/1, on_load_self_call/1, on_load_pending/1, + on_load_deleted/1, + big_boot_embedded/1, + module_status/1, + native_early_modules/1, get_mode/1, + normalized_paths/1]). -export([init_per_testcase/2, end_per_testcase/2, init_per_suite/1, end_per_suite/1]). @@ -47,7 +53,9 @@ -export([compile_load/4]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,5}}]. all() -> [set_path, get_path, add_path, add_paths, del_path, @@ -56,15 +64,19 @@ all() -> load_binary, dir_req, object_code, set_path_file, upgrade, sticky_dir, pa_pz_option, add_del_path, dir_disappeared, - ext_mod_dep, clash, load_cached, start_node_with_cache, - add_and_rehash, where_is_file_no_cache, - where_is_file_cached, purge_stacktrace, mult_lib_roots, + ext_mod_dep, clash, where_is_file, + purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, on_load_binary, on_load_embedded, on_load_errors, - big_boot_embedded, native_early_modules, get_mode]. + {group, sequence}, + on_load_purge, on_load_self_call, on_load_pending, + on_load_deleted, + module_status, + big_boot_embedded, native_early_modules, get_mode, normalized_paths]. -groups() -> - []. +%% These need to run in order +groups() -> [{sequence, [sequence], [on_load_update, + on_load_trace_on_load]}]. init_per_group(_GroupName, Config) -> Config. @@ -86,6 +98,11 @@ init_per_suite(Config) -> end_per_suite(Config) -> Config. +-define(TESTMOD, test_dummy). +-define(TESTMODSTR, "test_dummy"). +-define(TESTMODSRC, ?TESTMODSTR ".erl"). +-define(TESTMODOBJ, ?TESTMODSTR ".beam"). + init_per_testcase(big_boot_embedded, Config) -> case catch crypto:start() of ok -> @@ -93,35 +110,49 @@ init_per_testcase(big_boot_embedded, Config) -> _Else -> {skip, "Needs crypto!"} end; +init_per_testcase(on_load_embedded, Config0) -> + LibRoot = code:lib_dir(), + LinkName = filename:join(LibRoot, "on_load_app-1.0"), + Config = [{link_name,LinkName}|Config0], + init_per_testcase(Config); init_per_testcase(_Func, Config) -> - Dog=?t:timetrap(?t:minutes(5)), - P=code:get_path(), - P=code:get_path(), - [{watchdog, Dog}, {code_path, P}|Config]. + init_per_testcase(Config). +init_per_testcase(Config) -> + P = code:get_path(), + [{code_path, P}|Config]. + + +end_per_testcase(module_status, Config) -> + code:purge(?TESTMOD), + code:delete(?TESTMOD), + code:purge(?TESTMOD), + file:delete(?TESTMODOBJ), + file:delete(?TESTMODSRC), + end_per_testcase(Config); end_per_testcase(TC, Config) when TC == mult_lib_roots; TC == big_boot_embedded -> {ok, HostName} = inet:gethostname(), NodeName = list_to_atom(atom_to_list(TC)++"@"++HostName), - ?t:stop_node(NodeName), + test_server:stop_node(NodeName), + end_per_testcase(Config); +end_per_testcase(on_load_embedded, Config) -> + LinkName = proplists:get_value(link_name, Config), + _ = del_link(LinkName), end_per_testcase(Config); end_per_testcase(_Func, Config) -> end_per_testcase(Config). end_per_testcase(Config) -> code:purge(code_b_test), - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog), - P=?config(code_path, Config), + P=proplists:get_value(code_path, Config), true=code:set_path(P), P=code:get_path(), ok. -set_path(suite) -> []; -set_path(doc) -> []; set_path(Config) when is_list(Config) -> P = code:get_path(), - NonExDir = filename:join(?config(priv_dir, Config), ?t:temp_name("hej")), + NonExDir = filename:join(proplists:get_value(priv_dir, Config), test_server:temp_name("hej")), {'EXIT',_} = (catch code:set_path({a})), {error, bad_directory} = (catch code:set_path([{a}])), {error, bad_directory} = code:set_path(NonExDir), @@ -135,19 +166,15 @@ set_path(Config) when is_list(Config) -> [LibDir] = code:get_path(), ok. -get_path(suite) -> []; -get_path(doc) -> []; get_path(Config) when is_list(Config) -> P = code:get_path(), - % test that all directories are strings (lists). + %% test that all directories are strings (lists). [] = lists:filter(fun (Dir) when is_list(Dir) -> false; (_) -> true end, P), ok. -add_path(suite) -> []; -add_path(doc) -> []; add_path(Config) when is_list(Config) -> P = code:get_path(), {'EXIT',_} = (catch code:add_path({})), @@ -168,8 +195,6 @@ add_path(Config) when is_list(Config) -> code:set_path(P), ok. -add_paths(suite) -> []; -add_paths(doc) -> []; add_paths(Config) when is_list(Config) -> P = code:get_path(), ok = code:add_paths([{}]), @@ -215,8 +240,6 @@ add_paths(Config) when is_list(Config) -> code:set_path(P), ok. -del_path(suite) -> []; -del_path(doc) -> []; del_path(Config) when is_list(Config) -> P = code:get_path(), try @@ -226,18 +249,18 @@ del_path(Config) when is_list(Config) -> end. del_path_1(P) -> - test_server:format("Initial code:get_path()=~p~n",[P]), + io:format("Initial code:get_path()=~p~n",[P]), {'EXIT',_} = (catch code:del_path(3)), false = code:del_path(my_dummy_name), false = code:del_path("/kdlk/my_dummy_dir"), Dir = filename:join([code:lib_dir(kernel),"ebin"]), - test_server:format("kernel dir: ~p~n",[Dir]), + io:format("kernel dir: ~p~n",[Dir]), true = code:del_path(kernel), NewP = code:get_path(), - test_server:format("Path after removing 'kernel':~p~n",[NewP]), + io:format("Path after removing 'kernel':~p~n",[NewP]), ReferenceP = lists:delete(Dir,P), - test_server:format("Reference path:~p~n",[ReferenceP]), + io:format("Reference path:~p~n",[ReferenceP]), NewP = ReferenceP, % check that dir is deleted code:set_path(P), @@ -251,10 +274,8 @@ del_path_1(P) -> NewP1 = lists:delete(Dir,P), % check that dir is deleted ok. -replace_path(suite) -> []; -replace_path(doc) -> []; replace_path(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), P = code:get_path(), {'EXIT',_} = (catch code:replace_path(3,"")), {error, bad_name} = code:replace_path(dummy_name,""), @@ -289,10 +310,9 @@ replace_path(Config) when is_list(Config) -> ok. -dir_disappeared(suite) -> []; -dir_disappeared(doc) -> ["OTP-3977"]; +%% OTP-3977. dir_disappeared(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Dir = filename:join(PrivDir, "temp"), ok = file:make_dir(Dir), true = code:add_path(Dir), @@ -300,8 +320,6 @@ dir_disappeared(Config) when is_list(Config) -> non_existing = code:which(bubbelskrammel), ok. -load_file(suite) -> []; -load_file(doc) -> []; load_file(Config) when is_list(Config) -> {error, nofile} = code:load_file(duuuumy_mod), {error, badfile} = code:load_file(code_a_test), @@ -316,21 +334,18 @@ load_file(Config) when is_list(Config) -> test_dir() -> filename:dirname(code:which(?MODULE)). -load_abs(suite) -> []; -load_abs(doc) -> []; load_abs(Config) when is_list(Config) -> TestDir = test_dir(), {error, nofile} = code:load_abs(TestDir ++ "/duuuumy_mod"), {error, badfile} = code:load_abs(TestDir ++ "/code_a_test"), {'EXIT', _} = (catch code:load_abs({})), + {error, nofile} = code:load_abs("Non-latin-имя-файла"), {module, code_b_test} = code:load_abs(TestDir ++ "/code_b_test"), code:stick_dir(TestDir), {error, sticky_directory} = code:load_abs(TestDir ++ "/code_b_test"), code:unstick_dir(TestDir), ok. -ensure_loaded(suite) -> []; -ensure_loaded(doc) -> []; ensure_loaded(Config) when is_list(Config) -> {module, lists} = code:ensure_loaded(lists), case init:get_argument(mode) of @@ -347,8 +362,6 @@ ensure_loaded(Config) when is_list(Config) -> ok end. -delete(suite) -> []; -delete(doc) -> []; delete(Config) when is_list(Config) -> OldFlag = process_flag(trap_exit, true), code:purge(code_b_test), @@ -365,8 +378,6 @@ delete(Config) when is_list(Config) -> process_flag(trap_exit, OldFlag), ok. -purge(suite) -> []; -purge(doc) -> []; purge(Config) when is_list(Config) -> OldFlag = process_flag(trap_exit, true), code:purge(code_b_test), @@ -382,8 +393,23 @@ purge(Config) when is_list(Config) -> purge_many_exits(Config) when is_list(Config) -> OldFlag = process_flag(trap_exit, true), + code:purge(code_b_test), {'EXIT',_} = (catch code:purge({})), + + CodePurgeF = fun(M, Exp) -> Exp = code:purge(M) end, + purge_many_exits_do(CodePurgeF), + + %% Let's repeat test for erlang:purge_module as it does the same thing + %% now in erts-8.0 (except for return value). + ErlangPurgeF = fun(M, _Exp) -> erlang:purge_module(M) end, + purge_many_exits_do(ErlangPurgeF), + + process_flag(trap_exit, OldFlag), + ok. + + +purge_many_exits_do(PurgeF) -> false = code:purge(code_b_test), TPids = lists:map(fun (_) -> {code_b_test:do_spawn(), @@ -394,7 +420,7 @@ purge_many_exits(Config) when is_list(Config) -> end)} end, lists:seq(1, 1000)), - % Give them time to start... + %% Give them time to start... receive after 1000 -> ok end, true = code:delete(code_b_test), lists:foreach(fun ({Pid1, Pid2}) -> @@ -402,7 +428,7 @@ purge_many_exits(Config) when is_list(Config) -> false = code_b_test:check_exit(Pid1), true = erlang:is_process_alive(Pid2) end, TPids), - true = code:purge(code_b_test), + PurgeF(code_b_test, true), lists:foreach(fun ({Pid1, Pid2}) -> false = erlang:is_process_alive(Pid1), true = code_b_test:check_exit(Pid1), @@ -411,13 +437,9 @@ purge_many_exits(Config) when is_list(Config) -> end, TPids), lists:foreach(fun ({_Pid1, Pid2}) -> receive {'EXIT', Pid2, _} -> ok end - end, TPids), - process_flag(trap_exit, OldFlag), - ok. + end, TPids). -soft_purge(suite) -> []; -soft_purge(doc) -> []; soft_purge(Config) when is_list(Config) -> OldFlag = process_flag(trap_exit, true), code:purge(code_b_test), @@ -434,8 +456,6 @@ soft_purge(Config) when is_list(Config) -> process_flag(trap_exit, OldFlag), ok. -is_loaded(suite) -> []; -is_loaded(doc) -> []; is_loaded(Config) when is_list(Config) -> code:purge(code_b_test), code:delete(code_b_test), @@ -449,10 +469,8 @@ is_loaded(Config) when is_list(Config) -> code:delete(code_b_test), ok. -all_loaded(suite) -> []; -all_loaded(doc) -> []; all_loaded(Config) when is_list(Config) -> - case ?t:is_cover() of + case test_server:is_cover() of true -> {skip,"Cover is running"}; false -> all_loaded_1() end. @@ -480,8 +498,6 @@ all_unique([]) -> ok; all_unique([_]) -> ok; all_unique([{X,_}|[{Y,_}|_]=T]) when X < Y -> all_unique(T). -load_binary(suite) -> []; -load_binary(doc) -> []; load_binary(Config) when is_list(Config) -> TestDir = test_dir(), File = TestDir ++ "/code_b_test" ++ code:objfile_extension(), @@ -497,23 +513,35 @@ load_binary(Config) when is_list(Config) -> code:delete(code_b_test), ok. -upgrade(Config) -> - DataDir = ?config(data_dir, Config), - %%T = [beam, hipe], - T = [beam], - - [upgrade_do(DataDir, Client, U1, U2, O1, O2) - || Client<-T, U1<-T, U2<-T, O1<-T, O2<-T], +upgrade(Config) -> + DataDir = proplists:get_value(data_dir, Config), + case erlang:system_info(hipe_architecture) of + undefined -> + upgrade_do(DataDir, beam, [beam]); + + _ -> + T = [beam, hipe], + [upgrade_do(DataDir, Client, T) || Client <- T], + + case hipe:llvm_support_available() of + false -> ok; + true -> + T2 = [beam, hipe_llvm], + [upgrade_do(DataDir, Client, T2) || Client <- T2] + end + end, ok. -upgrade_do(DataDir, Client, U1, U2, O1, O2) -> +upgrade_do(DataDir, Client, T) -> compile_load(upgrade_client, DataDir, undefined, Client), - upgrade_client:run(DataDir, U1, U2, O1, O2), + [upgrade_client:run(DataDir, U1, U2, O1, O2) + || U1<-T, U2<-T, O1<-T, O2<-T], ok. compile_load(Mod, Dir, Ver, CodeType) -> + %%erlang:display({"{{{{{{{{{{{{{{{{Loading",Mod,Ver,CodeType}), Version = case Ver of undefined -> io:format("Compiling '~p' as ~p\n", [Mod, CodeType]), @@ -525,20 +553,23 @@ compile_load(Mod, Dir, Ver, CodeType) -> end, Target = case CodeType of beam -> []; - hipe -> [native] + hipe -> [native]; + hipe_llvm -> [native,{hipe,[to_llvm]}] end, CompOpts = [binary, report] ++ Target ++ Version, Src = filename:join(Dir, atom_to_list(Mod) ++ ".erl"), - %io:format("compile:file(~p,~p)\n", [Src, CompOpts]), + T1 = erlang:now(), {ok,Mod,Code} = compile:file(Src, CompOpts), + T2 = erlang:now(), ObjFile = filename:basename(Src,".erl") ++ ".beam", {module,Mod} = code:load_binary(Mod, ObjFile, Code), - %IsNative = code:is_module_native(Mod), + T3 = erlang:now(), + io:format("Compile time ~p ms, Load time ~p ms\n", + [timer:now_diff(T2,T1) div 1000, timer:now_diff(T3,T2) div 1000]), + %%erlang:display({"}}}}}}}}}}}}}}}Loaded",Mod,Ver,CodeType}), ok. -dir_req(suite) -> []; -dir_req(doc) -> []; dir_req(Config) when is_list(Config) -> {ok,[[Root0]]} = init:get_argument(root), Root = filename:join([Root0]), % Normalised form. @@ -553,8 +584,6 @@ dir_req(Config) when is_list(Config) -> {error, bad_name} = code:priv_dir(duuumy), ok. -object_code(suite) -> []; -object_code(doc) -> []; object_code(Config) when is_list(Config) -> TestDir = test_dir(), P = code:get_path(), @@ -575,22 +604,20 @@ object_code(Config) when is_list(Config) -> P=code:get_path(), ok. -set_path_file(suite) -> []; -set_path_file(doc) -> ["Test that set_path does not accept ", - "files as pathnames (known previous bug)"]; +%% Test that set_path does not accept +%% files as pathnames (known previous bug) set_path_file(Config) when is_list(Config) -> - File=filename:join(?config(priv_dir, Config), "testfil"), + File=filename:join(proplists:get_value(priv_dir, Config), "testfil"), ok=file:write_file(File, list_to_binary("lite data")), {error, bad_directory}=code:set_path([File]). -sticky_dir(suite) -> []; -sticky_dir(doc) -> ["Test that a module with the same name as a module in ", - "a sticky directory cannot be loaded."]; +%% Test that a module with the same name as a module in +%% a sticky directory cannot be loaded. sticky_dir(Config) when is_list(Config) -> Pa = filename:dirname(code:which(?MODULE)), - {ok,Node} = ?t:start_node(sticky_dir, slave, [{args,"-pa "++Pa}]), + {ok,Node} = test_server:start_node(sticky_dir, slave, [{args,"-pa "++Pa}]), Mods = [code,lists,erlang,init], - OutDir = filename:join(?config(priv_dir, Config), sticky_dir), + OutDir = filename:join(proplists:get_value(priv_dir, Config), sticky_dir), _ = file:make_dir(OutDir), Ret = rpc:call(Node, erlang, apply, [fun sticky_compiler/2,[Mods,OutDir]]), @@ -599,9 +626,9 @@ sticky_dir(Config) when is_list(Config) -> ok; Other -> io:format("~p\n", [Other]), - ?t:fail() + ct:fail(failed) end, - ?t:stop_node(Node), + test_server:stop_node(Node), ok. sticky_compiler(Files, PrivDir) -> @@ -610,50 +637,55 @@ sticky_compiler(Files, PrivDir) -> [R || R <- Rets, R =/= ok]. do_sticky_compile(Mod, Dir) -> - %% Make sure that the module is loaded. A module being sticky - %% only prevents it from begin reloaded, not from being loaded - %% from the wrong place to begin with. - Mod = Mod:module_info(module), - File = filename:append(Dir, atom_to_list(Mod)), - Src = io_lib:format("-module(~s).\n" - "-export([test/1]).\n" - "test(me) -> fail.\n", [Mod]), - ok = file:write_file(File++".erl", Src), - case c:c(File, [{outdir,Dir}]) of - {ok,Module} -> - Module:test(me); - {error,sticky_directory} -> - ok + case code:is_sticky(Mod) of + true -> + %% Make sure that the module is loaded. A module being sticky + %% only prevents it from begin reloaded, not from being loaded + %% from the wrong place to begin with. + Mod = Mod:module_info(module), + File = filename:append(Dir, atom_to_list(Mod)), + Src = io_lib:format("-module(~s).\n" + "-export([test/1]).\n" + "test(me) -> fail.\n", [Mod]), + ok = file:write_file(File++".erl", Src), + case c:c(File, [{outdir,Dir}]) of + {ok,Module} -> + Module:test(me); + {error,sticky_directory} -> + ok + end; + false -> + %% For some reason the module is not sticky + %% could be that the .erlang file has + %% unstuck it? + {Mod, is_not_sticky} end. -pa_pz_option(suite) -> []; -pa_pz_option(doc) -> ["Test that the -pa and -pz options work as expected"]; +%% Test that the -pa and -pz options work as expected. pa_pz_option(Config) when is_list(Config) -> - DDir = ?config(data_dir,Config), + DDir = proplists:get_value(data_dir,Config), PaDir = filename:join(DDir,"pa"), PzDir = filename:join(DDir,"pz"), - {ok, Node}=?t:start_node(pa_pz1, slave, + {ok, Node}=test_server:start_node(pa_pz1, slave, [{args, "-pa " ++ PaDir ++ " -pz " ++ PzDir}]), Ret=rpc:call(Node, code, get_path, []), [PaDir|Paths] = Ret, [PzDir|_] = lists:reverse(Paths), - ?t:stop_node(Node), - {ok, Node2}=?t:start_node(pa_pz2, slave, + test_server:stop_node(Node), + {ok, Node2}=test_server:start_node(pa_pz2, slave, [{args, "-mode embedded " ++ "-pa " ++ PaDir ++ " -pz " ++ PzDir}]), Ret2=rpc:call(Node2, code, get_path, []), [PaDir|Paths2] = Ret2, [PzDir|_] = lists:reverse(Paths2), - ?t:stop_node(Node2). + test_server:stop_node(Node2). -add_del_path(suite) -> - []; -add_del_path(doc) -> ["add_path, del_path should not cause priv_dir(App) to fail"]; +%% add_path, del_path should not cause priv_dir(App) to fail. add_del_path(Config) when is_list(Config) -> - DDir = ?config(data_dir,Config), + DDir = proplists:get_value(data_dir,Config), Dir1 = filename:join(DDir,"dummy_app-1.0/ebin"), Dir2 = filename:join(DDir,"dummy_app-2.0/ebin"), code:add_patha(Dir1), @@ -667,43 +699,35 @@ add_del_path(Config) when is_list(Config) -> clash(Config) when is_list(Config) -> - DDir = ?config(data_dir,Config)++"clash/", + DDir = proplists:get_value(data_dir,Config)++"clash/", P = code:get_path(), - [TestServerPath|_] = [Path || Path <- code:get_path(), - re:run(Path,"test_server/?$",[unicode]) /= nomatch], %% test non-clashing entries - %% remove TestServerPath to prevent clash with test-server path - true = code:del_path(TestServerPath), true = code:add_path(DDir++"foobar-0.1/ebin"), true = code:add_path(DDir++"zork-0.8/ebin"), - test_server:capture_start(), + ct:capture_start(), ok = code:clash(), - test_server:capture_stop(), - [OKMsg|_] = test_server:capture_get(), + ct:capture_stop(), + [OKMsg|_] = ct:capture_get(), true = lists:prefix("** Found 0 name clashes", OKMsg), true = code:set_path(P), %% test clashing entries - %% remove TestServerPath to prevent clash with test-server path - true = code:del_path(TestServerPath), true = code:add_path(DDir++"foobar-0.1/ebin"), true = code:add_path(DDir++"foobar-0.1.ez/foobar-0.1/ebin"), - test_server:capture_start(), + ct:capture_start(), ok = code:clash(), - test_server:capture_stop(), - [ClashMsg|_] = test_server:capture_get(), + ct:capture_stop(), + [ClashMsg|_] = ct:capture_get(), {match, [" hides "]} = re:run(ClashMsg, "\\*\\* .*( hides ).*", [{capture,all_but_first,list}]), true = code:set_path(P), %% test "Bad path can't read" - %% remove TestServerPath to prevent clash with test-server path - Priv = ?config(priv_dir, Config), - true = code:del_path(TestServerPath), + Priv = proplists:get_value(priv_dir, Config), TmpEzFile = Priv++"foobar-0.tmp.ez", {ok, _} = file:copy(DDir++"foobar-0.1.ez", TmpEzFile), true = code:add_path(TmpEzFile++"/foobar-0.1/ebin"), @@ -715,20 +739,17 @@ clash(Config) when is_list(Config) -> _ -> ok = file:delete(TmpEzFile) end, - test_server:capture_start(), + ct:capture_start(), ok = code:clash(), - test_server:capture_stop(), - [BadPathMsg|_] = test_server:capture_get(), + ct:capture_stop(), + [BadPathMsg|_] = ct:capture_get(), true = lists:prefix("** Bad path can't read", BadPathMsg), true = code:set_path(P), file:delete(TmpEzFile++".moved"), %% Only effect on windows ok. -ext_mod_dep(suite) -> - []; -ext_mod_dep(doc) -> - ["Every module that the code_server uses should be preloaded, " - "this test case verifies that"]; +%% Every module that the code_server uses should be preloaded, +%% this test case verifies that. ext_mod_dep(Config) when is_list(Config) -> xref:start(s), xref:set_default(s, [{verbose,false},{warnings,false}, @@ -744,7 +765,7 @@ ext_mod_dep(Config) when is_list(Config) -> xref:stop(s), case Else of ok -> ok; - _ -> test_server:fail(Else) + _ -> ct:fail(Else) end end. @@ -768,6 +789,7 @@ analyse([], [This={M,F,A}|Path], Visited, ErrCnt0) -> OK = [erlang, os, prim_file, erl_prim_loader, init, ets, code_server, lists, lists_sort, unicode, binary, filename, gb_sets, gb_trees, hipe_unified_loader, hipe_bifs, + erts_code_purger, prim_zip, zlib], ErrCnt1 = case lists:member(M, OK) or erlang:is_builtin(M,F,A) of @@ -793,7 +815,7 @@ analyse2(MFA={_,_,_}, Path, Visited0) -> analyse(FL, [MFA|Path], my_usort([MFA|Visited0]), 0). %%%% We need to check these manually... -% fun's are ok as long as they are defined locally. +%% fun's are ok as long as they are defined locally. check_funs({'$M_EXPR','$F_EXPR',_}, [{unicode,characters_to_binary_int,3}, {unicode,characters_to_binary,3}, @@ -838,26 +860,13 @@ check_funs({'$M_EXPR','$F_EXPR',1}, {code_server,start_link,1}]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, [{lists,filter,2}, - {code_server,try_archive_subdirs,3}, - {code_server,all_archive_subdirs,1}, - {code_server,archive_subdirs,1}, - {code_server,insert_name,3}, - {code_server,replace_name,2}, - {code_server,update,2}, - {code_server,maybe_update,2}, - {code_server,do_add,4}, - {code_server,add_path,4}, - {code_server,handle_call,3}, - {code_server,loop,1}, - {code_server,system_continue,3}]) -> 0; + {code_server,try_archive_subdirs,3}|_]) -> 0; check_funs({'$M_EXPR','$F_EXPR',_}, [{erlang,apply,2}, {erlang,spawn_link,1}, {code_server,start_link,1}]) -> 0; check_funs({'$M_EXPR','$F_EXPR',_}, [{erlang,spawn_link,1},{code_server,start_link,1}]) -> 0; -check_funs({'$M_EXPR',module_info,1}, - [{hipe_unified_loader,patch_to_emu_step1,1} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',2}, [{hipe_unified_loader,write_words,3} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',2}, @@ -869,26 +878,30 @@ check_funs({'$M_EXPR','$F_EXPR',2}, {hipe_unified_loader,sort_and_write,5} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, [{lists,foreach,2}, - {hipe_unified_loader,patch_consts,3} | _]) -> 0; -check_funs({'$M_EXPR','$F_EXPR',1}, - [{lists,foreach,2}, - {hipe_unified_loader,mark_referred_from,1}, - {hipe_unified_loader,get_refs_from,2}| _]) -> 0; + {hipe_unified_loader,patch_consts,4} | _]) -> 0; check_funs({'$M_EXPR',warning_msg,2}, [{code_server,finish_on_load_report,2} | _]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',1}, + [{code_server,run,2}|_]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',2}, + [{code_server,handle_on_load,5}|_]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',2}, + [{code_server,handle_pending_on_load,4}|_]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',2}, + [{code_server,finish_on_load_2,3}|_]) -> 0; %% This is cheating! /raimo %% %% check_funs(This = {M,_,_}, Path) -> %% case catch atom_to_list(M) of %% [$h,$i,$p,$e | _] -> -%% test_server:format("hipe_module_ignored(~p, ~p)~n", [This, Path]), +%% io:format("hipe_module_ignored(~p, ~p)~n", [This, Path]), %% 0; %% _ -> -%% test_server:format("not_verified(~p, ~p)~n", [This, Path]), +%% io:format("not_verified(~p, ~p)~n", [This, Path]), %% 1 %% end; check_funs(This, Path) -> - test_server:format("not_verified(~p, ~p)~n", [This, Path]), + io:format("not_verified(~p, ~p)~n", [This, Path]), 1. my_usort(List) -> @@ -904,140 +917,7 @@ uniq([H|T],A) -> uniq(T,[H|A]). -load_cached(suite) -> - []; -load_cached(doc) -> - []; -load_cached(Config) when is_list(Config) -> - Priv = ?config(priv_dir, Config), - WD = filename:dirname(code:which(?MODULE)), - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-pa \"" ++ WD ++ "\""}, - {erl, [this]}]), - CCTabCreated = fun(Tab) -> - case ets:info(Tab, name) of - code_cache -> true; - _ -> false - end - end, - Tabs = rpc:call(Node, ets, all, []), - case rpc:call(Node, lists, any, [CCTabCreated,Tabs]) of - true -> - ?t:stop_node(Node), - ?t:fail("Code cache should not be active!"); - false -> - ok - end, - rpc:call(Node, code, del_path, [Priv]), - rpc:call(Node, code, add_pathz, [Priv]), - - FullModName = Priv ++ "/code_cache_test", - {ok,Dev} = file:open(FullModName ++ ".erl", [write]), - io:format(Dev, "-module(code_cache_test). -export([a/0]). a() -> ok.~n", []), - ok = file:close(Dev), - {ok,code_cache_test} = compile:file(FullModName, [{outdir,Priv}]), - - F = fun load_loop/2, - N = 1000, - {T0,T1} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]), - TNoCache = now_diff(T1, T0), - rpc:call(Node, code, rehash, []), - {T2,T3} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]), - TCache = now_diff(T3, T2), - AvgNoCache = TNoCache/N, - AvgCache = TCache/N, - io:format("Avg. load time (no_cache/cache): ~w/~w~n", [AvgNoCache,AvgCache]), - ?t:stop_node(Node), - if AvgNoCache =< AvgCache -> - ?t:fail("Cache not working properly."); - true -> - ok - end. - -load_loop(N, M) -> - load_loop(N, M, now()). -load_loop(0, _M, T0) -> - {T0,now()}; -load_loop(N, M, T0) -> - code:load_file(M), - code:delete(M), - code:purge(M), - load_loop(N-1, M, T0). - -now_diff({A2, B2, C2}, {A1, B1, C1}) -> - ((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1. - -start_node_with_cache(suite) -> - []; -start_node_with_cache(doc) -> - []; -start_node_with_cache(Config) when is_list(Config) -> - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-code_path_cache"}, - {erl, [this]}]), - Tabs = rpc:call(Node, ets, all, []), - io:format("Tabs: ~w~n", [Tabs]), - CCTabCreated = fun(Tab) -> - case rpc:call(Node, ets, info, [Tab,name]) of - code_cache -> true; - _ -> false - end - end, - true = lists:any(CCTabCreated, Tabs), - ?t:stop_node(Node), - ok. - -add_and_rehash(suite) -> - []; -add_and_rehash(doc) -> - []; -add_and_rehash(Config) when is_list(Config) -> - Priv = ?config(priv_dir, Config), - WD = filename:dirname(code:which(?MODULE)), - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-pa \"" ++ WD ++ "\""}, - {erl, [this]}]), - CCTabCreated = fun(Tab) -> - case ets:info(Tab, name) of - code_cache -> true; - _ -> false - end - end, - Tabs0 = rpc:call(Node, ets, all, []), - case rpc:call(Node, lists, any, [CCTabCreated,Tabs0]) of - true -> - ?t:stop_node(Node), - ?t:fail("Code cache should not be active!"); - false -> - ok - end, - ok = rpc:call(Node, code, rehash, []), % create cache - Tabs1 = rpc:call(Node, ets, all, []), - true = rpc:call(Node, lists, any, [CCTabCreated,Tabs1]), % cache table created - ok = rpc:call(Node, code, rehash, []), - OkDir = filename:join(Priv, ""), - BadDir = filename:join(Priv, "guggemuffsussiputt"), - CP = [OkDir | rpc:call(Node, code, get_path, [])], - true = rpc:call(Node, code, set_path, [CP]), - CP1 = [BadDir | CP], - {error,_} = rpc:call(Node, code, set_path, [CP1]), - true = rpc:call(Node, code, del_path, [OkDir]), - true = rpc:call(Node, code, add_path, [OkDir]), - true = rpc:call(Node, code, add_path, [OkDir]), - {error,_} = rpc:call(Node, code, add_path, [BadDir]), - ok = rpc:call(Node, code, rehash, []), - - ?t:stop_node(Node), - ok. - -where_is_file_no_cache(suite) -> - []; -where_is_file_no_cache(doc) -> - []; -where_is_file_no_cache(Config) when is_list(Config) -> +where_is_file(Config) when is_list(Config) -> {T,KernelBeamFile} = timer:tc(code, where_is_file, ["kernel.beam"]), io:format("Load time: ~w ms~n", [T]), KernelEbinDir = filename:dirname(KernelBeamFile), @@ -1046,39 +926,7 @@ where_is_file_no_cache(Config) when is_list(Config) -> non_existing = code:where_is_file("kernel"), % no such file ok. -where_is_file_cached(suite) -> - []; -where_is_file_cached(doc) -> - []; -where_is_file_cached(Config) when is_list(Config) -> - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-code_path_cache"}, - {erl, [this]}]), - Tabs = rpc:call(Node, ets, all, []), - io:format("Tabs: ~w~n", [Tabs]), - CCTabCreated = fun(Tab) -> - case rpc:call(Node, ets, info, [Tab,name]) of - code_cache -> true; - _ -> false - end - end, - true = lists:any(CCTabCreated, Tabs), - KernelBeamFile = rpc:call(Node, code, where_is_file, ["kernel.beam"]), - {T,KernelBeamFile} = rpc:call(Node, timer, tc, [code,where_is_file,["kernel.beam"]]), - io:format("Load time: ~w ms~n", [T]), - KernelEbinDir = rpc:call(Node, filename, dirname, [KernelBeamFile]), - AppFile = rpc:call(Node, filename, join, [KernelEbinDir,"kernel.app"]), - AppFile = rpc:call(Node, code, where_is_file, ["kernel.app"]), - non_existing = rpc:call(Node, code, where_is_file, ["kernel"]), % no such file - ?t:stop_node(Node), - ok. - - -purge_stacktrace(suite) -> - []; -purge_stacktrace(doc) -> - ["Test that stacktrace is deleted when purging a referred module"]; +%% Test that stacktrace is deleted when purging a referred module. purge_stacktrace(Config) when is_list(Config) -> code:purge(code_b_test), try code_b_test:call(fun(b) -> ok end, a) @@ -1119,7 +967,7 @@ purge_stacktrace(Config) when is_list(Config) -> ok. mult_lib_roots(Config) when is_list(Config) -> - DataDir = filename:join(?config(data_dir, Config), "mult_lib_roots"), + DataDir = filename:join(proplists:get_value(data_dir, Config), "mult_lib_roots"), mult_lib_compile(DataDir, "my_dummy_app-b/ebin/lists"), mult_lib_compile(DataDir, "my_dummy_app-c/ebin/code_SUITE_mult_root_module"), @@ -1129,12 +977,11 @@ mult_lib_roots(Config) when is_list(Config) -> filename:join(DataDir, "second_root"), {ok,Node} = - ?t:start_node(mult_lib_roots, slave, + test_server:start_node(mult_lib_roots, slave, [{args,"-env ERL_LIBS "++ErlLibs}]), - TSPath = filename:dirname(code:which(test_server)), Path0 = rpc:call(Node, code, get_path, []), - [TSPath,"."|Path1] = Path0, + ["."|Path1] = Path0, [Kernel|Path2] = Path1, [Stdlib|Path3] = Path2, mult_lib_verify_lib(Kernel, "kernel"), @@ -1178,16 +1025,19 @@ mult_lib_remove_prefix([$/|T], []) -> T. bad_erl_libs(Config) when is_list(Config) -> {ok,Node} = - ?t:start_node(mult_lib_roots, slave, - [{args,"-env ERL_LIBS "}]), - - ?t:stop_node(Node), + test_server:start_node(bad_erl_libs, slave, []), + Code = rpc:call(Node,code,get_path,[]), + test_server:stop_node(Node), {ok,Node2} = - ?t:start_node(mult_lib_roots, slave, - [{args,"-env ERL_LIBS /no/such/dir"}]), + test_server:start_node(bad_erl_libs, slave, + [{args,"-env ERL_LIBS /no/such/dir"}]), + Code2 = rpc:call(Node,code,get_path,[]), + test_server:stop_node(Node2), + + %% Test that code path is not affected by the faulty ERL_LIBS + Code = Code2, - ?t:stop_node(Node2), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1202,8 +1052,8 @@ code_archive2(Config) when is_list(Config) -> do_code_archive(Config, Root, StripVsn) when is_list(Config) -> %% Copy the orig files to priv_dir - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), App = code_archive_dict, VsnBase = atom_to_list(App) ++ "-1.0", Base = @@ -1236,9 +1086,15 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) -> {ok, _} = zip:create(Archive, [Base], [{compress, []}, {cwd, PrivDir}]), + %% Create a directory and a file outside of the archive. + OtherFile = filename:join([RootDir,VsnBase,"other","other.txt"]), + OtherContents = ?MODULE:module_info(md5), + filelib:ensure_dir(OtherFile), + ok = file:write_file(OtherFile, OtherContents), + %% Set up ERL_LIBS and start a slave node. {ok, Node} = - ?t:start_node(code_archive, slave, + test_server:start_node(code_archive, slave, [{args,"-env ERL_LIBS " ++ RootDir}]), CodePath = rpc:call(Node, code, get_path, []), AppEbin = filename:join([Archive, Base, "ebin"]), @@ -1250,13 +1106,25 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) -> %% Start the app ok = rpc:call(Node, application, start, [App]), + %% Get the lib dir for the app. + AppLibDir = rpc:call(Node, code, lib_dir, [App]), + io:format("AppLibDir: ~p\n", [AppLibDir]), + AppLibDir = filename:join(RootDir, VsnBase), + %% Access the app priv dir AppPrivDir = rpc:call(Node, code, priv_dir, [App]), AppPrivFile = filename:join([AppPrivDir, "code_archive.txt"]), io:format("AppPrivFile: ~p\n", [AppPrivFile]), - {ok, _Bin, _Path} = + {ok, _Bin, _} = rpc:call(Node, erl_prim_loader, get_file, [AppPrivFile]), + %% Read back the other text file. + OtherDirPath = rpc:call(Node, code, lib_dir, [App,other]), + OtherFilePath = filename:join(OtherDirPath, "other.txt"), + io:format("OtherFilePath: ~p\n", [OtherFilePath]), + {ok, OtherContents, _} = + rpc:call(Node, erl_prim_loader, get_file, [OtherFilePath]), + %% Use the app Tab = code_archive_tab, Key = foo, @@ -1269,7 +1137,7 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) -> error = rpc:call(Node, App, find, [Tab, Key]), ok = rpc:call(Node, App, erase, [Tab]), - ?t:stop_node(Node), + test_server:stop_node(Node), ok. compile_app(TopDir, AppName) -> @@ -1295,15 +1163,12 @@ compile_files([File | Files], SrcDir, OutDir) -> compile_files([], _, _) -> ok. -big_boot_embedded(suite) -> - []; -big_boot_embedded(doc) -> - ["Test that a boot file with (almost) all of OTP can be used to start an" - " embeddedd system."]; +%% Test that a boot file with (almost) all of OTP can be used to start an +%% embeddedd system. big_boot_embedded(Config) when is_list(Config) -> {BootArg,AppsInBoot} = create_big_boot(Config), {ok, Node} = - ?t:start_node(big_boot_embedded, slave, + test_server:start_node(big_boot_embedded, slave, [{args,"-boot "++BootArg++" -mode embedded"}]), RemoteNodeApps = [ {X,Y} || {X,_,Y} <- @@ -1314,7 +1179,7 @@ big_boot_embedded(Config) when is_list(Config) -> on_load(Config) when is_list(Config) -> Master = on_load_test_case_process, - Data = filename:join([?config(data_dir, Config),"on_load"]), + Data = filename:join([proplists:get_value(data_dir, Config),"on_load"]), ok = file:set_cwd(Data), up_to_date = make:all([{d,'MASTER',Master}]), @@ -1358,7 +1223,7 @@ on_load(Config) when is_list(Config) -> on_load_wait_for_all(Refs), receive Any -> - ?t:fail({unexpected,Any}) + ct:fail({unexpected,Any}) after 10 -> ok end. @@ -1382,22 +1247,17 @@ on_load_binary(_) -> register(Master, self()), %% Construct, compile and pretty-print. - Mod = on_load_binary, + Mod = ?FUNCTION_NAME, File = atom_to_list(Mod) ++ ".erl", - Forms = [{attribute,1,file,{File,1}}, - {attribute,1,module,Mod}, - {attribute,2,export,[{ok,0}]}, - {attribute,3,on_load,{init,0}}, - {function,5,init,0, - [{clause,5,[],[], - [{op,6,'!', - {atom,6,Master}, - {tuple,6,[{atom,6,Mod},{call,6,{atom,6,self},[]}]}}, - {'receive',7,[{clause,8,[{atom,8,go}],[],[{atom,8,ok}]}]}]}]}, - {function,11,ok,0,[{clause,11,[],[],[{atom,11,true}]}]}], - Forms1 = erl_parse:new_anno(Forms), - {ok,Mod,Bin} = compile:forms(Forms1, [report]), - [io:put_chars(erl_pp:form(F)) || F <- Forms1], + Tree = ?Q(["-module('@Mod@').\n", + "-export([ok/0]).\n", + "-on_load({init,0}).\n", + "init() ->\n", + " '@Master@' ! {on_load_binary,self()},\n", + " receive go -> ok end.\n", + "ok() -> true.\n"]), + {ok,Mod,Bin} = merl:compile(Tree), + merl:print(Tree), {Pid1,Ref1} = spawn_monitor(fun() -> code:load_binary(Mod, File, Bin), @@ -1426,17 +1286,19 @@ on_load_embedded(Config) when is_list(Config) -> end. on_load_embedded_1(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + LinkName = proplists:get_value(link_name, Config), %% Link the on_load_app application into the lib directory. - LibRoot = code:lib_dir(), - LinkName = filename:join(LibRoot, "on_load_app-1.0"), OnLoadApp = filename:join(DataDir, "on_load_app-1.0"), del_link(LinkName), io:format("LinkName :~p, OnLoadApp: ~p~n",[LinkName,OnLoadApp]), case file:make_symlink(OnLoadApp, LinkName) of {error,enotsup} -> throw({skip,"Support for symlinks required"}); + {error,eperm} -> + %% On Windows, we may not have permissions to create symlinks. + throw({skip,"Support for symlinks required"}); ok -> ok end, @@ -1461,8 +1323,7 @@ on_load_embedded_1(Config) -> ok = rpc:call(Node, on_load_embedded, status, []), %% Clean up. - stop_node(Node), - ok = del_link(LinkName). + stop_node(Node). del_link(LinkName) -> case file:delete(LinkName) of @@ -1481,7 +1342,7 @@ create_boot(Config, Options) -> filename:join(LatestDir, LatestName). create_script(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Name = PrivDir ++ "on_load_test", Apps = application_controller:which_applications(), {value,{_,_,KernelVer}} = lists:keysearch(kernel, 1, Apps), @@ -1508,33 +1369,45 @@ create_big_boot(Config) -> ok = file:set_cwd(OldDir), {filename:join(LatestDir, LatestName),Apps}. -% The following apps cannot be loaded -% hipe .app references (or can reference) files that have no -% corresponding beam file (if hipe is not enabled) +%% The following apps cannot be loaded. +%% hipe .app references (or can reference) files that have no +%% corresponding beam file (if hipe is not enabled). filter_app("hipe",_) -> false; -% Dialyzer and typer depends on hipe + +%% Dialyzer depends on hipe filter_app("dialyzer",_) -> false; -filter_app("typer",_) -> false; -% Orber requires explicit configuration + +%% Orber requires explicit configuration filter_app("orber",_) -> false; -% cos* depends on orber + +%% cos* depends on orber filter_app("cos"++_,_) -> false; -% ic has a mod instruction in the app file but no corresponding start function + +%% ic has a mod instruction in the app file but no corresponding start +%% function filter_app("ic",_) -> false; -% Netconf has some dependency that I really do not understand (maybe like orber) + +%% Netconf has some dependency that I really do not understand (maybe +%% like orber) filter_app("netconf",_) -> false; -% Safe has the same kind of error in the .app file as ic + +%% Safe has the same kind of error in the .app file as ic filter_app("safe",_) -> false; -% Comte cannot be started in the "usual" way + +%% Comte cannot be started in the "usual" way filter_app("comte",_) -> false; -% OS_mon does not find it's port program when running cerl + +%% OS_mon does not find its port program when running cerl filter_app("os_mon",true) -> false; -% erts is not a "real" app either =/ + +%% erts is not a "real" app either =/ filter_app("erts",_) -> false; -% Other apps should be OK. + +%% Other apps should be OK. filter_app(_,_) -> true. + create_big_script(Config,Local) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Name = filename:join(PrivDir,"full_script_test"), InitialApplications=application:loaded_applications(), %% Applications left loaded by the application suite, unload them! @@ -1568,7 +1441,7 @@ on_load_errors(Config) when is_list(Config) -> Master = on_load_error_test_case_process, register(Master, self()), - Data = filename:join([?config(data_dir, Config),"on_load_errors"]), + Data = filename:join([proplists:get_value(data_dir, Config),"on_load_errors"]), ok = file:set_cwd(Data), up_to_date = make:all([{d,'MASTER',Master}]), @@ -1594,11 +1467,22 @@ on_load_errors(Config) when is_list(Config) -> %% There should be no more messages. receive Unexpected -> - ?t:fail({unexpected,Unexpected}) + ct:fail({unexpected,Unexpected}) after 10 -> ok end, + %% Make sure that the code loading functions return the correct + %% error code. + Simple = simple_on_load_error, + SimpleList = atom_to_list(Simple), + {error,on_load_failure} = code:load_file(Simple), + {error,on_load_failure} = code:ensure_loaded(Simple), + {ok,SimpleCode} = file:read_file("simple_on_load_error.beam"), + {error,on_load_failure} = code:load_binary(Simple, "", SimpleCode), + {error,on_load_failure} = code:load_abs(SimpleList), + {error,on_load_failure} = code:load_abs(SimpleList, Simple), + ok. do_on_load_error(ReturnValue) -> @@ -1612,8 +1496,284 @@ do_on_load_error(ReturnValue) -> {undef,[{on_load_error,main,[],_}|_]} = Exit end. -native_early_modules(suite) -> []; -native_early_modules(doc) -> ["Test that the native code of early loaded modules is loaded"]; +on_load_update(Config) -> + {Mod,Code1} = on_load_update_code(1), + {module,Mod} = code:load_binary(Mod, "", Code1), + 42 = Mod:a(), + 100 = Mod:b(99), + 4 = erlang:trace_pattern({Mod,'_','_'}, true), + + {Mod,Code2} = on_load_update_code(2), + {error,on_load_failure} = code:load_binary(Mod, "", Code2), + 42 = Mod:a(), + 78 = Mod:b(77), + {'EXIT',{undef,_}} = (catch Mod:never()), + 4 = erlang:trace_pattern({Mod,'_','_'}, false), + + {Mod,Code3} = on_load_update_code(3), + {module,Mod} = code:load_binary(Mod, "", Code3), + 100 = Mod:c(), + {'EXIT',{undef,_}} = (catch Mod:a()), + {'EXIT',{undef,_}} = (catch Mod:b(10)), + {'EXIT',{undef,_}} = (catch Mod:never()), + + code:purge(Mod), + code:delete(Mod), + code:purge(Mod), + ok. + +on_load_update_code(Version) -> + Mod = ?FUNCTION_NAME, + Tree = on_load_update_code_1(Version, Mod), + io:format("Version ~p", [Version]), + {ok,Mod,Code} = merl:compile(Tree), + merl:print(Tree), + io:nl(), + {Mod,Code}. + +on_load_update_code_1(1, Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([a/0,b/1]).\n" + "-on_load(f/0).\n", + "f() -> ok.\n", + "a() -> 42.\n" + "b(I) -> I+1.\n"]); +on_load_update_code_1(2, Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([never/0]).\n" + "-on_load(f/0).\n", + "f() -> 42 = '@Mod@':a(), 1 = '@Mod@':b(0), fail.\n", + "never() -> never.\n"]); +on_load_update_code_1(3, Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([c/0]).\n" + "-on_load(f/0).\n", + "f() -> ok.\n", + "c() -> 100.\n"]). + +%% Test -on_load while trace feature 'on_load' is enabled (OTP-14612) +on_load_trace_on_load(Config) -> + Papa = self(), + Tracer = spawn_link(fun F() -> receive M -> Papa ! M end, F() end), + {tracer,[]} = erlang:trace_info(self(),tracer), + erlang:trace(self(), true, [call, {tracer, Tracer}]), + erlang:trace_pattern(on_load, true, []), + on_load_update(Config), + erlang:trace_pattern(on_load, false, []), + erlang:trace(self(), false, [call]), + + Ms = flush(), + [{trace, Papa, call, {on_load_update_code, a, []}}, + {trace, Papa, call, {on_load_update_code, b, [99]}}, + {trace, Papa, call, {on_load_update_code, c, []}}] = Ms, + + exit(Tracer, normal), + ok. + +flush() -> + receive M -> [M | flush()] + after 100 -> [] + end. + + +on_load_purge(_Config) -> + Mod = ?FUNCTION_NAME, + register(Mod, self()), + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "loop() -> loop().\n", + "f() ->\n", + "'@Mod@' ! {self(),spawn(fun loop/0)},\n", + "receive Ack -> Ack end.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + P = spawn(fun() -> + exit(code:load_binary(Mod, "", Code)) + end), + monitor(process, P), + receive + {Pid1,Pid2} -> + monitor(process, Pid2), + Pid1 ! ack_and_failure, + receive + {'DOWN',_,process,P,Exit1} -> + {error,on_load_failure} = Exit1 + end, + receive + {'DOWN',_,process,Pid2,Exit2} -> + io:format("~p\n", [Exit2]) + after 10000 -> + ct:fail(no_down_message) + end + end. + +on_load_self_call(_Config) -> + Mod = ?FUNCTION_NAME, + register(Mod, self()), + Tree = ?Q(["-module('@Mod@').\n", + "-export([ext/0]).\n", + "-on_load(f/0).\n", + "f() ->\n", + " '@Mod@' ! (catch '@Mod@':ext()),\n", + " ok.\n", + "ext() -> good_work.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + + {'EXIT',{undef,_}} = on_load_do_load(Mod, Code), + good_work = on_load_do_load(Mod, Code), + + ok. + +on_load_do_load(Mod, Code) -> + spawn(fun() -> + {module,Mod} = code:load_binary(Mod, "", Code) + end), + receive + Any -> Any + end. + +on_load_pending(_Config) -> + Mod = ?FUNCTION_NAME, + Tree1 = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() ->\n", + " register('@Mod@', self()),\n", + " receive _ -> ok end.\n"]), + merl:print(Tree1), + {ok,Mod,Code1} = merl:compile(Tree1), + + Tree2 = ?Q(["-module('@Mod@').\n", + "-export([t/0]).\n", + "t() -> ok.\n"]), + merl:print(Tree2), + {ok,Mod,Code2} = merl:compile(Tree2), + + Self = self(), + {_,Ref1} = + spawn_monitor(fun() -> + Self ! started1, + {module,Mod} = code:load_binary(Mod, "", Code1) + end), + receive started1 -> ok end, + timer:sleep(10), + {_,Ref2} = + spawn_monitor(fun() -> + Self ! started2, + {module,Mod} = code:load_binary(Mod, "", Code2), + ok = Mod:t() + end), + receive started2 -> ok end, + receive + Unexpected -> + ct:fail({unexpected,Unexpected}) + after 100 -> + ok + end, + Mod ! go, + receive + {'DOWN',Ref1,process,_,normal} -> ok + end, + receive + {'DOWN',Ref2,process,_,normal} -> ok + end, + ok = Mod:t(), + ok. + +on_load_deleted(_Config) -> + Mod = ?FUNCTION_NAME, + + R0 = fun() -> + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> ok.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + {module,Mod} = code:load_binary(Mod, "", Code) + end, + delete_before_reload(Mod, R0), + delete_before_reload(Mod, R0), + + R1 = fun() -> + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> fail.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + {error,on_load_failure} = code:load_binary(Mod, "", Code) + end, + delete_before_reload(Mod, R1), + delete_before_reload(Mod, R1), + + OtherMod = list_to_atom(lists:concat([Mod,"_42"])), + OtherTree = ?Q(["-module('@OtherMod@').\n"]), + merl:print(OtherTree), + {ok,OtherMod,OtherCode} = merl:compile(OtherTree), + + R2 = fun() -> + RegName = 'on_load__registered_name', + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() ->\n", + " register('@RegName@', self()),\n", + " receive _ -> ok end.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + spawn(fun() -> + {module,Mod} = code:load_binary(Mod, "", Code) + end), + receive after 1 -> ok end, + {module,OtherMod} = code:load_binary(OtherMod, "", + OtherCode), + RegName ! stop + end, + delete_before_reload(Mod, R2), + + ok. + +delete_before_reload(Mod, Reload) -> + false = check_old_code(Mod), + + Tree1 = ?Q(["-module('@Mod@').\n", + "-export([f/1]).\n", + "f(Parent) ->\n", + " register('@Mod@', self()),\n", + " Parent ! started,\n", + " receive _ -> ok end.\n"]), + merl:print(Tree1), + {ok,Mod,Code1} = merl:compile(Tree1), + + Self = self(), + spawn(fun() -> + {module,Mod} = code:load_binary(Mod, "", Code1), + Mod:f(Self) + end), + receive started -> ok end, + + true = code:delete(Mod), + true = check_old_code(Mod), + + Reload(), + + %% When loading the the module with the -on_load() function, + %% the reference to the old code would be lost. Make sure that + %% the old code is remembered and is still preventing the + %% purge. + false = code:soft_purge(Mod), + + %% Get rid of the old code. + Mod ! stop, + receive after 1 -> ok end, + true = code:soft_purge(Mod), + + %% Unload the version of the module with the -on_load() function. + true = code:delete(Mod), + true = code:soft_purge(Mod), + + ok. + + +%% Test that the native code of early loaded modules is loaded. native_early_modules(Config) when is_list(Config) -> case erlang:system_info(hipe_architecture) of undefined -> @@ -1641,11 +1801,205 @@ native_early_modules_1(Architecture) -> ok end. -get_mode(suite) -> []; -get_mode(doc) -> ["Test that the mode of the code server is properly retrieved"]; +%% Test that the mode of the code server is properly retrieved. get_mode(Config) when is_list(Config) -> interactive = code:get_mode(). +%% Make sure that the paths for all loaded modules have been normalized. +normalized_paths(_Config) -> + do_normalized_paths(erlang:loaded()). + +do_normalized_paths([M|Ms]) -> + case code:which(M) of + Special when is_atom(Special) -> + do_normalized_paths(Ms); + File when is_list(File) -> + File = filename:join([File]), + do_normalized_paths(Ms) + end; +do_normalized_paths([]) -> + ok. + +%% Test that module_status/1 behaves as expected +module_status(_Config) -> + case test_server:is_cover() of + true -> + module_status(); + false -> + %% Make sure that we terminate the cover server. + try + module_status() + after + cover:stop() + end + end. + +module_status() -> + %% basics + not_loaded = code:module_status(fubar), % nonexisting + {file, preloaded} = code:is_loaded(erlang), + loaded = code:module_status(erlang), % preloaded + loaded = code:module_status(?MODULE), % normal known loaded + + non_existing = code:which(?TESTMOD), % verify dummy name not in path + code:purge(?TESTMOD), % ensure no previous version in memory + code:delete(?TESTMOD), + code:purge(?TESTMOD), + + %% generated code is detected as such + {ok,?TESTMOD,Bin} = compile:forms(dummy_ast(), []), + {module,?TESTMOD} = code:load_binary(?TESTMOD,"",Bin), % no source file + ok = ?TESTMOD:f(), + "" = code:which(?TESTMOD), % verify empty string for source file + loaded = code:module_status(?TESTMOD), + + %% deleting generated code + true = code:delete(?TESTMOD), + non_existing = code:which(?TESTMOD), % verify still not in path + not_loaded = code:module_status(?TESTMOD), + + %% beam file exists but not loaded + make_source_file(<<"0">>), + compile_beam(0), + true = (non_existing =/= code:which(?TESTMOD)), % verify in path + not_loaded = code:module_status(?TESTMOD), + + %% loading code from disk makes it loaded + load_code(), + loaded = code:module_status(?TESTMOD), % loaded + + %% cover compiling a module + {ok,?TESTMOD} = cover:compile(?TESTMOD), + {file, cover_compiled} = code:is_loaded(?TESTMOD), % verify cover compiled + modified = code:module_status(?TESTMOD), % loaded cover code but file exists + remove_code(), + removed = code:module_status(?TESTMOD), % removed + compile_beam(0), + modified = code:module_status(?TESTMOD), % recreated + load_code(), + loaded = code:module_status(?TESTMOD), % loading removes cover status + code:purge(?TESTMOD), + true = code:delete(?TESTMOD), + not_loaded = code:module_status(?TESTMOD), % deleted + + %% recompilation ignores timestamps, only md5 matters + load_code(), + compile_beam(1100), + loaded = code:module_status(?TESTMOD), + + %% modifying module detects different md5 + make_source_file(<<"1">>), + compile_beam(0), + modified = code:module_status(?TESTMOD), + + %% loading the modified code from disk makes it loaded + load_code(), + loaded = code:module_status(?TESTMOD), + + %% removing and recreating a module with same md5 + remove_code(), + removed = code:module_status(?TESTMOD), + compile_beam(0), + loaded = code:module_status(?TESTMOD), + + case erlang:system_info(hipe_architecture) of + undefined -> + %% no native support + ok; + _ -> + %% native chunk is ignored if beam code is already loaded + load_code(), + loaded = code:module_status(?TESTMOD), + false = has_native(?TESTMOD), + compile_native(0), + BeamMD5 = erlang:get_module_info(?TESTMOD, md5), + {ok,{?TESTMOD,BeamMD5}} = beam_lib:md5(?TESTMODOBJ), % beam md5 unchanged + loaded = code:module_status(?TESTMOD), + + %% native code reported as loaded, though different md5 from beam + load_code(), + true = has_native(?TESTMOD), + NativeMD5 = erlang:get_module_info(?TESTMOD, md5), + true = (BeamMD5 =/= NativeMD5), + loaded = code:module_status(?TESTMOD), + + %% recompilation ignores timestamps, only md5 matters + compile_native(1100), % later timestamp + loaded = code:module_status(?TESTMOD), + + %% modifying native module detects different md5 + make_source_file(<<"2">>), + compile_native(0), + modified = code:module_status(?TESTMOD), + + %% loading the modified native code from disk makes it loaded + load_code(), + true = has_native(?TESTMOD), + NativeMD5_2 = erlang:get_module_info(?TESTMOD, md5), + true = (NativeMD5 =/= NativeMD5_2), % verify native md5 changed + {ok,{?TESTMOD,BeamMD5_2}} = beam_lib:md5(?TESTMODOBJ), + true = (BeamMD5_2 =/= NativeMD5_2), % verify md5 differs from beam + loaded = code:module_status(?TESTMOD), + + %% removing and recreating a native module with same md5 + remove_code(), + removed = code:module_status(?TESTMOD), + compile_native(0), + loaded = code:module_status(?TESTMOD), + + %% purging/deleting native module + code:purge(?TESTMOD), + true = code:delete(?TESTMOD), + not_loaded = code:module_status(?TESTMOD) + end, + ok. + +compile_beam(Sleep) -> + compile(Sleep, []). + +compile_native(Sleep) -> + compile(Sleep, [native]). + +compile(Sleep, Opts) -> + timer:sleep(Sleep), % increment compilation timestamp + {ok,?TESTMOD} = compile:file(?TESTMODSRC, Opts). + +load_code() -> + code:purge(?TESTMOD), + {module,?TESTMOD} = code:load_file(?TESTMOD). + +remove_code() -> + ok = file:delete(?TESTMODOBJ). + +has_native(Module) -> + case erlang:get_module_info(Module, native_addresses) of + [] -> false; + [_|_] -> true + end. + +make_source_file(Body) -> + ok = file:write_file(?TESTMODSRC, dummy_source(Body)). + +dummy_source(Body) -> + [<<"-module(" ?TESTMODSTR ").\n" + "-export([f/0]).\n" + "f() -> ">>, Body, <<".\n">>]. + +dummy_ast() -> + dummy_ast(?TESTMODSTR). + +dummy_ast(Mod) when is_atom(Mod) -> + dummy_ast(atom_to_list(Mod)); +dummy_ast(ModStr) -> + [scan_form("-module(" ++ ModStr ++ ")."), + scan_form("-export([f/0])."), + scan_form("f() -> ok.")]. + +scan_form(String) -> + {ok,Ts,_} = erl_scan:string(String), + {ok,F} = erl_parse:parse_form(Ts), + F. + %%----------------------------------------------------------------- %% error_logger handler. %% (Copied from stdlib/test/proc_lib_SUITE.erl.) @@ -1672,7 +2026,7 @@ terminate(_Reason, State) -> %%% start_node(Name, Param) -> - ?t:start_node(Name, slave, [{args, Param}]). + test_server:start_node(Name, slave, [{args, Param}]). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). diff --git a/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict.erl b/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict.erl index 9fb5a31358..1fcf05a0a1 100644 --- a/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict.erl +++ b/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_app.erl b/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_app.erl index 8012ddafb4..d164db9794 100644 --- a/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_app.erl +++ b/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_app.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_sup.erl b/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_sup.erl index 8c7b49644a..e659202e08 100644 --- a/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_sup.erl +++ b/lib/kernel/test/code_SUITE_data/code_archive_dict-1.0/src/code_archive_dict_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-b/ebin/lists.erl b/lib/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-b/ebin/lists.erl index 07a4ffc8b6..6accd00191 100644 --- a/lib/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-b/ebin/lists.erl +++ b/lib/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-b/ebin/lists.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-c/ebin/code_SUITE_mult_root_module.erl b/lib/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-c/ebin/code_SUITE_mult_root_module.erl index 15ff5d4896..f45e5b2dba 100644 --- a/lib/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-c/ebin/code_SUITE_mult_root_module.erl +++ b/lib/kernel/test/code_SUITE_data/mult_lib_roots/first_root/my_dummy_app-c/ebin/code_SUITE_mult_root_module.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl b/lib/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl new file mode 100644 index 0000000000..603c282257 --- /dev/null +++ b/lib/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl @@ -0,0 +1,5 @@ +-module(simple_on_load_error). +-on_load(on_load/0). + +on_load() -> + nope. diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl index bb655e01d3..1c3c2def53 100644 --- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl +++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl @@ -9,6 +9,8 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> %% Load version 1 of upgradee code_SUITE:compile_load(upgradee, Dir, 1, Upgradee1), + Tracer = start_tracing(), + ?line 1 = upgradee:exp1(), ?line 1 = upgradee:exp1exp2(), ?line 1 = upgradee:exp1loc2(), @@ -56,6 +58,15 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + Env1 = "Env1", + put(loc1_fun, upgradee:get_local_fun(Env1)), + ?line {1,Env1} = (get(loc1_fun))(), + + put(exp1exp2_fun, upgradee:get_exp1exp2_fun()), + ?line 1 = (get(exp1exp2_fun))(), + + ok = check_tracing(Tracer, 13), + %% %% Load version 1 of other %% @@ -78,6 +89,8 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ok = check_tracing(Tracer, 5), + %% %% Load version 2 of upgradee %% @@ -130,6 +143,15 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line {1,Env1} = (get(loc1_fun))(), + Env2 = "Env2", + put(loc2_fun, upgradee:get_local_fun(Env2)), + ?line {2,Env2} = (get(loc2_fun))(), + + ?line 2 = (get(exp1exp2_fun))(), + + ok = check_tracing(Tracer, 10), + %% %% Load version 2 of other %% @@ -182,17 +204,26 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line {1,Env1} = (get(loc1_fun))(), + ?line {2,Env2} = (get(loc2_fun))(), + ?line 2 = (get(exp1exp2_fun))(), + + ok = check_tracing(Tracer, 10), %% %% Upgrade proxy to version 2 %% P ! upgrade_order, - %% - io:format("Delete version 2 of 'upgradee'\n",[]), + io:format("Purge version 1 of 'upgradee'\n",[]), %% + put(loc1_fun,undefined), code:purge(upgradee), + + %% + io:format("Delete version 2 of 'upgradee'\n",[]), + %% code:delete(upgradee), ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()), @@ -239,17 +270,24 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + ?line {'EXIT',{undef,_}} = (catch (get(exp1exp2_fun))()), + ok = check_tracing(Tracer, 14), + unlink(P), exit(P, die_please), io:format("Purge 'upgradee'\n",[]), + put(loc2_fun,undefined), code:purge(upgradee), io:format("Delete and purge 'other'\n",[]), code:purge(other), code:delete(other), code:purge(other), + + stop_tracing(Tracer), ok. proxy_call(Pid, CallType, Func) -> @@ -257,3 +295,55 @@ proxy_call(Pid, CallType, Func) -> receive {Pid, call_result, Func, Ret} -> Ret end. + + +start_tracing() -> + Self = self(), + {Tracer,_} = spawn_opt(fun() -> tracer_loop(Self) end, [link,monitor]), + ?line 1 = erlang:trace_pattern({error_handler,undefined_function,3}, + true, [global]), + ?line 1 = erlang:trace(Self, true, [call,{tracer,Tracer}]), + Tracer. + + +tracer_loop(Receiver) -> + receive + die_please -> + ok; + {do_trace_delivered, Tracee} -> + _ = erlang:trace_delivered(Tracee), + tracer_loop(Receiver); + + Msg -> + Receiver ! Msg, + tracer_loop(Receiver) + end. + +check_tracing(Tracer, Expected) -> + Tracer ! {do_trace_delivered, self()}, + case check_tracing_loop(0,[]) of + {Expected,_} -> + ok; + {Got, MsgList} -> + io:format("Expected ~p trace msg, got ~p:\n~p\n", + [Expected, Got, lists:reverse(MsgList)]), + "Trace msg mismatch" + end. + +check_tracing_loop(N, MsgList) -> + Self = self(), + receive + {trace, _Pid, call, {_M, _F, _Args}} = Msg -> + check_tracing_loop(N+1, [Msg | MsgList]); + {trace_delivered, Self, _} -> + {N, MsgList} + end. + + +stop_tracing(Tracer) -> + erlang:trace_pattern({error_handler,undefined_function,3}, false, [global]), + erlang:trace(self(), false, [call]), + Tracer ! die_please, + receive + {'DOWN', _, process, Tracer, _} -> ok + end. diff --git a/lib/kernel/test/code_SUITE_data/upgradee.erl b/lib/kernel/test/code_SUITE_data/upgradee.erl index 62b1d95e30..8ca660c19c 100644 --- a/lib/kernel/test/code_SUITE_data/upgradee.erl +++ b/lib/kernel/test/code_SUITE_data/upgradee.erl @@ -8,6 +8,9 @@ -export([exp1/0]). % only exported in v1 -export([exp1loc2/0]). % exported in v1, local in v2 -export([exp1exp2/0]). % exported in v1 and v2 +-export([get_local_fun/1]). +-export([get_exp1exp2_fun/0]). +-export([exp1exp2_fun/0]). exp1() -> ?VERSION. loc1() -> ?VERSION. @@ -20,6 +23,9 @@ loc1() -> ?VERSION. -export([exp2/0]). -export([loc1exp2/0]). -export([exp1exp2/0]). +-export([get_local_fun/1]). +-export([get_exp1exp2_fun/0]). +-export([exp1exp2_fun/0]). exp2() -> ?VERSION. loc2() -> ?VERSION. @@ -31,6 +37,12 @@ exp1loc2() -> ?VERSION. loc1exp2() -> ?VERSION. loc1loc2() -> ?VERSION. +get_local_fun(Env) -> fun() -> {?VERSION,Env} end. +get_exp1exp2_fun() -> fun ?MODULE:exp1exp2_fun/0. + +exp1exp2_fun() -> + ?VERSION. + dispatch_loop() -> receive upgrade_order -> diff --git a/lib/kernel/test/code_a_test.erl b/lib/kernel/test/code_a_test.erl index fa33c6f57a..bb5d814f04 100644 --- a/lib/kernel/test/code_a_test.erl +++ b/lib/kernel/test/code_a_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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/kernel/test/code_b_test.erl b/lib/kernel/test/code_b_test.erl index 559698dd8e..9c362eb0d0 100644 --- a/lib/kernel/test/code_b_test.erl +++ b/lib/kernel/test/code_b_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 9988347581..12e2521939 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-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. @@ -19,7 +19,7 @@ %% -module(disk_log_SUITE). -%-define(debug, true). +%%-define(debug, true). -ifdef(debug). -define(format(S, A), io:format(S, A)). @@ -29,10 +29,10 @@ -define(config(X,Y), foo). -define(t,test_server). -else. --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(format(S, A), ok). --define(privdir(Conf), ?config(priv_dir, Conf)). --define(datadir(Conf), ?config(data_dir, Conf)). +-define(privdir(Conf), proplists:get_value(priv_dir, Conf)). +-define(datadir(Conf), proplists:get_value(data_dir, Conf)). -endif. -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -102,8 +102,6 @@ -export([client/4]). --define(default_timeout, ?t:minutes(1)). - %% error_logger -export([init/1, handle_event/2, handle_call/2, handle_info/2, @@ -139,7 +137,9 @@ change_size_after, default_size]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [{group, halt_int}, {group, wrap_int}, @@ -194,264 +194,234 @@ end_per_group(_GroupName, Config) -> -init_per_testcase(Case, Config) -> - case should_skip(Case,Config) of - true -> - CS = check_nfs(Config), - {skipped, lists:flatten - (io_lib:format - ("The test does not work " - "with current NFS cache size (~w)," - " to get this test to run, " - "~s the NFS cache size~n", - [CS, case CS of - 0 -> - "enlarge"; - _ -> - "zero" - end]))}; - _ -> - Dog=?t:timetrap(?t:minutes(2)), - [{watchdog, Dog}|Config] - end. +init_per_testcase(_Case, Config) -> + Config. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -halt_int_inf(suite) -> []; -halt_int_inf(doc) -> ["Test simple halt disk log, size infinity"]; +%% Test simple halt disk log, size infinity. halt_int_inf(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line ok = disk_log:start(), + ok = disk_log:start(), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, - {file, File}]), - ?line simple_log(a), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, + {file, File}]), + simple_log(a), + ok = disk_log:close(a), + ok = file:delete(File). -halt_int_sz_1(suite) -> []; -halt_int_sz_1(doc) -> ["Test simple halt disk log, size defined"]; +%% Test simple halt disk log, size defined. halt_int_sz_1(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000}, - {format,internal}, - {file, File}]), - ?line simple_log(a), - ?line ok = disk_log:truncate(a), - ?line [] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000}, + {format,internal}, + {file, File}]), + simple_log(a), + ok = disk_log:truncate(a), + [] = get_all_terms(a), T1 = mk_bytes(10000), T2 = mk_bytes(5000), - ?line ok = disk_log:log(a, T1), - ?line case get_all_terms(a) of - [T1] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, [T1]}) - end, - ?line ok = disk_log:log(a, T2), - ?line {error, {full, a}} = disk_log:log(a, T1), - ?line ok = disk_log:alog(a, T1), - ?line case get_all_terms(a) of - [T1, T2] -> - ok; - E2 -> - test_server_fail({bad_terms, E2, [T1, T2]}) - end, - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + ok = disk_log:log(a, T1), + case get_all_terms(a) of + [T1] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, [T1]}) + end, + ok = disk_log:log(a, T2), + {error, {full, a}} = disk_log:log(a, T1), + ok = disk_log:alog(a, T1), + case get_all_terms(a) of + [T1, T2] -> + ok; + E2 -> + test_server_fail({bad_terms, E2, [T1, T2]}) + end, + ok = disk_log:close(a), + ok = file:delete(File). -halt_int_sz_2(suite) -> []; -halt_int_sz_2(doc) -> ["Test simple halt disk log, size ~8192"]; +%% Test simple halt disk log, size ~8192. halt_int_sz_2(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File1 = filename:join(Dir, "a.LOG"), File2 = filename:join(Dir, "b.LOG"), File3 = filename:join(Dir, "c.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191}, - {format,internal}, - {file, File1}]), - ?line {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192}, - {format,internal}, - {file, File2}]), - ?line {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193}, - {format,internal}, - {file, File3}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191}, + {format,internal}, + {file, File1}]), + {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192}, + {format,internal}, + {file, File2}]), + {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193}, + {format,internal}, + {file, File3}]), T1 = mk_bytes(8191-16), % 16 is size of header + magics for 1 item T2 = mk_bytes(8192-16), T3 = mk_bytes(8193-16), - ?line ok = disk_log:log(a, T1), - ?line ok = disk_log:log(b, T2), - ?line ok = disk_log:log(c, T3), - ?line case get_all_terms(a) of - [T1] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, [T1]}) - end, - ?line case get_all_terms(b) of - [T2] -> - ok; - E2 -> - test_server_fail({bad_terms, E2, [T2]}) - end, - ?line case get_all_terms(c) of - [T3] -> - ok; - E3 -> - test_server_fail({bad_terms, E3, [T3]}) - end, - ?line ok = disk_log:truncate(a), - ?line ok = disk_log:truncate(b), - ?line {error, {full, a}} = disk_log:log(a, T2), - ?line {error, {full, b}} = disk_log:log(b, T3), - ?line [] = get_all_terms(a), - ?line [] = get_all_terms(b), - ?line ok = disk_log:close(a), - ?line ok = disk_log:close(b), - ?line ok = disk_log:close(c), - ?line ok = file:delete(File1), - ?line ok = file:delete(File2), - ?line ok = file:delete(File3), + ok = disk_log:log(a, T1), + ok = disk_log:log(b, T2), + ok = disk_log:log(c, T3), + case get_all_terms(a) of + [T1] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, [T1]}) + end, + case get_all_terms(b) of + [T2] -> + ok; + E2 -> + test_server_fail({bad_terms, E2, [T2]}) + end, + case get_all_terms(c) of + [T3] -> + ok; + E3 -> + test_server_fail({bad_terms, E3, [T3]}) + end, + ok = disk_log:truncate(a), + ok = disk_log:truncate(b), + {error, {full, a}} = disk_log:log(a, T2), + {error, {full, b}} = disk_log:log(b, T3), + [] = get_all_terms(a), + [] = get_all_terms(b), + ok = disk_log:close(a), + ok = disk_log:close(b), + ok = disk_log:close(c), + ok = file:delete(File1), + ok = file:delete(File2), + ok = file:delete(File3), ok. -halt_int_ro(suite) -> []; -halt_int_ro(doc) -> ["Test simple halt disk log, read only, internal"]; +%% Test simple halt disk log, read only, internal. halt_int_ro(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}]), simple_log(a), - ?line ok = disk_log:close(a), + ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}, - {mode,read_only}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}, + {mode,read_only}]), T1 = "not allowed to write", - ?line {error, {read_only_mode, a}} = disk_log:log(a, T1), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + {error, {read_only_mode, a}} = disk_log:log(a, T1), + ok = disk_log:close(a), + ok = file:delete(File). -halt_ext_ro(suite) -> []; -halt_ext_ro(doc) -> ["Test simple halt disk log, read only, external"]; +%% Test simple halt disk log, read only, external. halt_ext_ro(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,external}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,external}, {file, File}]), xsimple_log(File, a), - ?line ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,external}, {file, File}, - {mode,read_only}]), + ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,external}, {file, File}, + {mode,read_only}]), T1 = "not allowed to write", - ?line {error, {read_only_mode, a}} = disk_log:blog(a, T1), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + {error, {read_only_mode, a}} = disk_log:blog(a, T1), + ok = disk_log:close(a), + ok = file:delete(File). -wrap_int_ro(suite) -> []; -wrap_int_ro(doc) -> ["Test simple wrap disk log, read only, internal"]; +%% Test simple wrap disk log, read only, internal. wrap_int_ro(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,internal}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,internal}, {file, File}]), simple_log(a), - ?line ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,internal}, {file, File}, {mode,read_only}]), + ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,internal}, {file, File}, {mode,read_only}]), T1 = "not allowed to write", - ?line {error, {read_only_mode, a}} = disk_log:log(a, T1), - ?line ok = disk_log:close(a), - ?line del(File, 4). + {error, {read_only_mode, a}} = disk_log:log(a, T1), + ok = disk_log:close(a), + del(File, 4). -wrap_ext_ro(suite) -> []; -wrap_ext_ro(doc) -> ["Test simple wrap disk log, read only, external"]; +%% Test simple wrap disk log, read only, external. wrap_ext_ro(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,external}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,external}, {file, File}]), x2simple_log(File ++ ".1", a), - ?line ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,external}, {file, File}, - {mode,read_only}]), + ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,external}, {file, File}, + {mode,read_only}]), T1 = "not allowed to write", - ?line {error, {read_only_mode, a}} = disk_log:blog(a, T1), - ?line {error, {read_only_mode, a}} = disk_log:inc_wrap_file(a), - ?line ok = disk_log:close(a), + {error, {read_only_mode, a}} = disk_log:blog(a, T1), + {error, {read_only_mode, a}} = disk_log:inc_wrap_file(a), + ok = disk_log:close(a), del(File, 4). -halt_trunc(suite) -> []; -halt_trunc(doc) -> ["Test truncation of halt disk log"]; +%% Test truncation of halt disk log. halt_trunc(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}]), simple_log(a), - ?line ok = disk_log:close(a), - ?line {error,{badarg,repair_read_only}} = + ok = disk_log:close(a), + {error,{badarg,repair_read_only}} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, {repair, truncate}, {format,internal}, {file, File}, {mode,read_only}]), - ?line ok = file:delete(File). + ok = file:delete(File). -halt_misc(suite) -> []; -halt_misc(doc) -> ["Test truncation of halt disk log"]; +%% Test truncation of halt disk log. halt_misc(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}]), simple_log(a), - ?line ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}, - {mode,read_only}]), + ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}, + {mode,read_only}]), T1 = "not allowed to write", - ?line {error, {read_only_mode, a}} = disk_log:log(a, T1), - ?line {error, {read_only_mode, a}} = disk_log:sync(a), - ?line {error, {read_only_mode, a}} = disk_log:reopen(a, "b.LOG"), - ?line {error, {read_only_mode, a}} = + {error, {read_only_mode, a}} = disk_log:log(a, T1), + {error, {read_only_mode, a}} = disk_log:sync(a), + {error, {read_only_mode, a}} = disk_log:reopen(a, "b.LOG"), + {error, {read_only_mode, a}} = disk_log:change_header(a, {head,header}), - ?line {error, {read_only_mode, a}} = + {error, {read_only_mode, a}} = disk_log:change_size(a, infinity), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + ok = disk_log:close(a), + ok = file:delete(File). -halt_ro_alog(suite) -> []; -halt_ro_alog(doc) -> ["Test truncation of halt disk log, read only"]; +%% Test truncation of halt disk log, read only. halt_ro_alog(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}]), simple_log(a), - ?line ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {notify,true}, {format,internal}, - {file, File}, {mode,read_only}]), + ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {notify,true}, {format,internal}, + {file, File}, {mode,read_only}]), T1 = "not allowed to write", - ?line ok = disk_log:alog(a, T1), - ?line ok = halt_ro_alog_wait_notify(a, T1), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + ok = disk_log:alog(a, T1), + ok = halt_ro_alog_wait_notify(a, T1), + ok = disk_log:close(a), + ok = file:delete(File). halt_ro_alog_wait_notify(Log, T) -> Term = term_to_binary(T), receive - {disk_log, _, Log,{read_only, Term}} -> + {disk_log, _, Log,{read_only, [Term]}} -> ok; Other -> Other @@ -459,28 +429,27 @@ halt_ro_alog_wait_notify(Log, T) -> failed end. -halt_ro_balog(suite) -> []; -halt_ro_balog(doc) -> ["Test truncation of halt disk log, read only"]; +%% Test truncation of halt disk log, read only. halt_ro_balog(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal}, {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal}, {file, File}]), simple_log(a), - ?line ok = disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {notify,true}, {format,external}, - {file, File}, {mode,read_only}]), + ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {notify,true}, {format,external}, + {file, File}, {mode,read_only}]), T1 = "not allowed to write", - ?line ok = disk_log:balog(a, T1), - ?line ok = halt_ro_balog_wait_notify(a, T1), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + ok = disk_log:balog(a, T1), + ok = halt_ro_balog_wait_notify(a, T1), + ok = disk_log:close(a), + ok = file:delete(File). halt_ro_balog_wait_notify(Log, T) -> Term = list_to_binary(T), receive - {disk_log, _, Log,{read_only, Term}} -> + {disk_log, _, Log,{read_only, [Term]}} -> ok; Other -> Other @@ -488,127 +457,123 @@ halt_ro_balog_wait_notify(Log, T) -> failed end. -halt_ro_crash(suite) -> []; -halt_ro_crash(doc) -> ["Test truncation of halt disk log, read only, repair"]; +%% Test truncation of halt disk log, read only, repair. halt_ro_crash(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line file:delete(File), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,internal},{file, File}]), + file:delete(File), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,internal},{file, File}]), simple_log(a), - ?line ok = disk_log:close(a), + ok = disk_log:close(a), crash(File, 10), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {notify,true}, {format,internal}, - {file, File}, {mode,read_only}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {notify,true}, {format,internal}, + {file, File}, {mode,read_only}]), - ?line Error1 = {error, {read_only_mode, a}} = disk_log:truncate(a), - ?line "The disk log" ++ _ = format_error(Error1), + Error1 = {error, {read_only_mode, a}} = disk_log:truncate(a), + "The disk log" ++ _ = format_error(Error1), %% crash/1 sets the length of the first item to something big (2.5 kb). %% In R6B, binary_to_term accepts garbage at the end of the binary, %% which means that the first item is recognized! %% This is how it was before R6B: - %% ?line {C1,T1,15} = disk_log:chunk(a,start), - %% ?line {C2,T2} = disk_log:chunk(a,C1), + %% {C1,T1,15} = disk_log:chunk(a,start), + %% {C2,T2} = disk_log:chunk(a,C1), {C1,_OneItem,7478} = disk_log:chunk(a,start), {C2, [], 7} = disk_log:chunk(a,C1), - ?line eof = disk_log:chunk(a,C2), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + eof = disk_log:chunk(a,C2), + ok = disk_log:close(a), + ok = file:delete(File). -wrap_int_1(suite) -> []; -wrap_int_1(doc) -> ["Test wrap disk log, internal"]; +%% Test wrap disk log, internal. wrap_int_1(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,internal}, - {file, File}]), - ?line [_] = + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,internal}, + {file, File}]), + [_] = lists:filter(fun(P) -> disk_log:pid2name(P) =/= undefined end, erlang:processes()), simple_log(a), - ?line ok = disk_log:close(a), + ok = disk_log:close(a), del(File, 4), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,internal}, - {file, File}]), - ?line [] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,internal}, + {file, File}]), + [] = get_all_terms(a), T1 = mk_bytes(10000), % file 2 T2 = mk_bytes(5000), % file 3 T3 = mk_bytes(4000), % file 4 T4 = mk_bytes(2000), % file 4 T5 = mk_bytes(5000), % file 1 T6 = mk_bytes(5000), % file 2 - ?line ok = disk_log:log(a, T1), - ?line ok = disk_log:log(a, T2), - ?line ok = disk_log:log(a, T3), - ?line ok = disk_log:log_terms(a, [T4, T5, T6]), - ?line case get_all_terms(a) of - [T2,T3,T4,T5,T6] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, [T2,T3,T4,T5,T6]}) - end, - ?line ok = disk_log:close(a), + ok = disk_log:log(a, T1), + ok = disk_log:log(a, T2), + ok = disk_log:log(a, T3), + ok = disk_log:log_terms(a, [T4, T5, T6]), + case get_all_terms(a) of + [T2,T3,T4,T5,T6] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, [T2,T3,T4,T5,T6]}) + end, + ok = disk_log:close(a), del(File, 4). -wrap_int_2(suite) -> []; -wrap_int_2(doc) -> ["Test wrap disk log, internal"]; +%% Test wrap disk log, internal. wrap_int_2(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File1 = filename:join(Dir, "a.LOG"), File2 = filename:join(Dir, "b.LOG"), File3 = filename:join(Dir, "c.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}}, - {format,internal}, - {file, File1}]), - ?line {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}}, - {format,internal}, - {file, File2}]), - ?line {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}}, - {format,internal}, - {file, File3}]), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}}, + {format,internal}, + {file, File1}]), + {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}}, + {format,internal}, + {file, File2}]), + {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}}, + {format,internal}, + {file, File3}]), T1 = mk_bytes(8191-16), % 16 is size of header + magics for 1 item T2 = mk_bytes(8192-16), T3 = mk_bytes(8193-16), - ?line ok = disk_log:log(a, T1), - ?line ok = disk_log:log(b, T2), - ?line ok = disk_log:log(c, T3), - ?line case get_all_terms(a) of - [T1] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, [T1]}) - end, - ?line case get_all_terms(b) of - [T2] -> - ok; - E2 -> - test_server_fail({bad_terms, E2, [T2]}) - end, - ?line case get_all_terms(c) of - [T3] -> - ok; - E3 -> - test_server_fail({bad_terms, E3, [T3]}) - end, - ?line ok = disk_log:close(a), - ?line ok = disk_log:close(b), - ?line ok = disk_log:close(c), + ok = disk_log:log(a, T1), + ok = disk_log:log(b, T2), + ok = disk_log:log(c, T3), + case get_all_terms(a) of + [T1] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, [T1]}) + end, + case get_all_terms(b) of + [T2] -> + ok; + E2 -> + test_server_fail({bad_terms, E2, [T2]}) + end, + case get_all_terms(c) of + [T3] -> + ok; + E3 -> + test_server_fail({bad_terms, E3, [T3]}) + end, + ok = disk_log:close(a), + ok = disk_log:close(b), + ok = disk_log:close(c), del(File1, 3), del(File2, 3), del(File3, 3). -inc_wrap_file(suite) -> []; -inc_wrap_file(doc) -> ["Test disk log, force a change to next file"]; +%% Test disk log, force a change to next file. inc_wrap_file(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File1 = filename:join(Dir, "a.LOG"), @@ -616,262 +581,257 @@ inc_wrap_file(Conf) when is_list(Conf) -> File3 = filename:join(Dir, "c.LOG"), %% Test that halt logs gets an error message - ?line {ok, a} = disk_log:open([{name, a}, {type, halt}, - {format, internal}, - {file, File1}]), - ?line ok = disk_log:log(a, "message one"), - ?line {error, {halt_log, a}} = disk_log:inc_wrap_file(a), + {ok, a} = disk_log:open([{name, a}, {type, halt}, + {format, internal}, + {file, File1}]), + ok = disk_log:log(a, "message one"), + {error, {halt_log, a}} = disk_log:inc_wrap_file(a), %% test an internally formatted wrap log file - ?line {ok, b} = disk_log:open([{name, b}, {type, wrap}, {size, {100,3}}, - {format, internal}, {head, 'thisisahead'}, - {file, File2}]), - ?line ok = disk_log:log(b, "message one"), - ?line ok = disk_log:inc_wrap_file(b), - ?line ok = disk_log:log(b, "message two"), - ?line ok = disk_log:inc_wrap_file(b), - ?line ok = disk_log:log(b, "message three"), - ?line ok = disk_log:inc_wrap_file(b), - ?line ok = disk_log:log(b, "message four"), - ?line T1 = get_all_terms(b), - ?line ['thisisahead', "message two", - 'thisisahead', "message three", - 'thisisahead', "message four"] = T1, + {ok, b} = disk_log:open([{name, b}, {type, wrap}, {size, {100,3}}, + {format, internal}, {head, 'thisisahead'}, + {file, File2}]), + ok = disk_log:log(b, "message one"), + ok = disk_log:inc_wrap_file(b), + ok = disk_log:log(b, "message two"), + ok = disk_log:inc_wrap_file(b), + ok = disk_log:log(b, "message three"), + ok = disk_log:inc_wrap_file(b), + ok = disk_log:log(b, "message four"), + T1 = get_all_terms(b), + ['thisisahead', "message two", + 'thisisahead', "message three", + 'thisisahead', "message four"] = T1, %% test an externally formatted wrap log file - ?line {ok, c} = disk_log:open([{name, c}, {type, wrap}, {size, {100,3}}, - {format,external}, {head,"this is a head "}, - {file, File3}]), - ?line ok = disk_log:blog(c, "message one"), - ?line ok = disk_log:inc_wrap_file(c), - ?line ok = disk_log:blog(c, "message two"), - ?line ok = disk_log:inc_wrap_file(c), - ?line ok = disk_log:blog(c, "message three"), - ?line ok = disk_log:inc_wrap_file(c), - ?line ok = disk_log:blog(c, "message four"), - ?line ok = disk_log:sync(c), - ?line {ok, Fd31} = file:open(File3 ++ ".1", [read]), - ?line {ok,"this is a head message four"} = file:read(Fd31, 200), - ?line {ok, Fd32} = file:open(File3 ++ ".2", [read]), - ?line {ok,"this is a head message two"} = file:read(Fd32, 200), - ?line {ok, Fd33} = file:open(File3 ++ ".3", [read]), - ?line {ok,"this is a head message three"} = file:read(Fd33, 200), - ?line ok = file:close(Fd31), - ?line ok = file:close(Fd32), - ?line ok = file:close(Fd33), - - ?line ok = disk_log:close(a), - ?line ok = disk_log:close(b), - ?line ok = disk_log:close(c), - ?line ok = file:delete(File1), + {ok, c} = disk_log:open([{name, c}, {type, wrap}, {size, {100,3}}, + {format,external}, {head,"this is a head "}, + {file, File3}]), + ok = disk_log:blog(c, "message one"), + ok = disk_log:inc_wrap_file(c), + ok = disk_log:blog(c, "message two"), + ok = disk_log:inc_wrap_file(c), + ok = disk_log:blog(c, "message three"), + ok = disk_log:inc_wrap_file(c), + ok = disk_log:blog(c, "message four"), + ok = disk_log:sync(c), + {ok, Fd31} = file:open(File3 ++ ".1", [read]), + {ok,"this is a head message four"} = file:read(Fd31, 200), + {ok, Fd32} = file:open(File3 ++ ".2", [read]), + {ok,"this is a head message two"} = file:read(Fd32, 200), + {ok, Fd33} = file:open(File3 ++ ".3", [read]), + {ok,"this is a head message three"} = file:read(Fd33, 200), + ok = file:close(Fd31), + ok = file:close(Fd32), + ok = file:close(Fd33), + + ok = disk_log:close(a), + ok = disk_log:close(b), + ok = disk_log:close(c), + ok = file:delete(File1), del(File2, 3), del(File3, 3). -halt_ext_inf(suite) -> []; -halt_ext_inf(doc) -> ["Test halt disk log, external, infinity"]; +%% Test halt disk log, external, infinity. halt_ext_inf(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, - {format,external}, - {file, File}]), - ?line xsimple_log(File, a), - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity}, + {format,external}, + {file, File}]), + xsimple_log(File, a), + ok = disk_log:close(a), + ok = file:delete(File). -halt_ext_sz_1(suite) -> []; -halt_ext_sz_1(doc) -> ["Test halt disk log, external, size defined"]; +%% Test halt disk log, external, size defined. halt_ext_sz_1(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000}, - {format,external}, - {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000}, + {format,external}, + {file, File}]), xsimple_log(File, a), - ?line ok = disk_log:truncate(a), - ?line [] = get_list(File, a), + ok = disk_log:truncate(a), + [] = get_list(File, a), {B1, T1} = x_mk_bytes(10000), {B2, T2} = x_mk_bytes(5000), {B3, T3} = x_mk_bytes(1000), - ?line ok = disk_log:blog(a, B1), - ?line case get_list(File, a) of - T1 -> - ok; - E1 -> - test_server_fail({bad_terms, E1, T1}) - end, - ?line ok = disk_log:blog(a, B2), - ?line {error, {full, a}} = disk_log:blog_terms(a, [B3,B3,B1]), - ?line ok = disk_log:balog(a, B1), - ?line Tmp = T1 ++ T2 ++ T3 ++ T3, - ?line case get_list(File, a) of - Tmp -> - ok; - E2 -> - test_server_fail({bad_terms, E2, Tmp}) - end, - ?line ok = disk_log:close(a), - ?line ok = file:delete(File). + ok = disk_log:blog(a, B1), + case get_list(File, a) of + T1 -> + ok; + E1 -> + test_server_fail({bad_terms, E1, T1}) + end, + ok = disk_log:blog(a, B2), + {error, {full, a}} = disk_log:blog_terms(a, [B3,B3,B1]), + ok = disk_log:balog(a, B1), + Tmp = T1 ++ T2 ++ T3 ++ T3, + case get_list(File, a) of + Tmp -> + ok; + E2 -> + test_server_fail({bad_terms, E2, Tmp}) + end, + ok = disk_log:close(a), + ok = file:delete(File). -halt_ext_sz_2(suite) -> []; -halt_ext_sz_2(doc) -> ["Test halt disk log, external, size defined"]; +%% Test halt disk log, external, size defined. halt_ext_sz_2(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File1 = filename:join(Dir, "a.LOG"), File2 = filename:join(Dir, "b.LOG"), File3 = filename:join(Dir, "c.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191}, - {format,external}, - {file, File1}]), - ?line {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192}, - {format,external}, - {file, File2}]), - ?line {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193}, - {format,external}, - {file, File3}]), + {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191}, + {format,external}, + {file, File1}]), + {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192}, + {format,external}, + {file, File2}]), + {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193}, + {format,external}, + {file, File3}]), {B1, T1} = x_mk_bytes(8191), {B2, T2} = x_mk_bytes(8192), {B3, T3} = x_mk_bytes(8193), - ?line ok = disk_log:blog(a, B1), - ?line ok = disk_log:blog(b, B2), - ?line ok = disk_log:blog(c, B3), - ?line case get_list(File1, a) of - T1 -> - ok; - E1 -> - test_server_fail({bad_terms, E1, T1}) - end, - ?line case get_list(File2, b) of - T2 -> - ok; - E2 -> - test_server_fail({bad_terms, E2, T2}) - end, - ?line case get_list(File3, c) of - T3 -> - ok; - E3 -> - test_server_fail({bad_terms, E3, T3}) - end, - ?line ok = disk_log:truncate(a), - ?line ok = disk_log:truncate(b), - ?line {error, {full, a}} = disk_log:blog(a, B2), - ?line Error1 = {error, {full, b}} = disk_log:blog(b, B3), - ?line "The halt log" ++ _ = format_error(Error1), - ?line true = info(b, full, false), - ?line [] = get_list(File1, a), - ?line [] = get_list(File2, b), - ?line ok = disk_log:close(a), - ?line ok = disk_log:close(b), - ?line ok = disk_log:close(c), - ?line ok = file:delete(File1), - ?line ok = file:delete(File2), - ?line ok = file:delete(File3), + ok = disk_log:blog(a, B1), + ok = disk_log:blog(b, B2), + ok = disk_log:blog(c, B3), + case get_list(File1, a) of + T1 -> + ok; + E1 -> + test_server_fail({bad_terms, E1, T1}) + end, + case get_list(File2, b) of + T2 -> + ok; + E2 -> + test_server_fail({bad_terms, E2, T2}) + end, + case get_list(File3, c) of + T3 -> + ok; + E3 -> + test_server_fail({bad_terms, E3, T3}) + end, + ok = disk_log:truncate(a), + ok = disk_log:truncate(b), + {error, {full, a}} = disk_log:blog(a, B2), + Error1 = {error, {full, b}} = disk_log:blog(b, B3), + "The halt log" ++ _ = format_error(Error1), + true = info(b, full, false), + [] = get_list(File1, a), + [] = get_list(File2, b), + ok = disk_log:close(a), + ok = disk_log:close(b), + ok = disk_log:close(c), + ok = file:delete(File1), + ok = file:delete(File2), + ok = file:delete(File3), ok. -wrap_ext_1(suite) -> []; -wrap_ext_1(doc) -> ["Test wrap disk log, external, size defined"]; +%% Test wrap disk log, external, size defined. wrap_ext_1(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,external}, - {file, File}]), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,external}, + {file, File}]), x2simple_log(File ++ ".1", a), - ?line ok = disk_log:close(a), -% del(File, 4), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, - {format,external}, - {file, File}]), + ok = disk_log:close(a), + %% del(File, 4), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}}, + {format,external}, + {file, File}]), {B1, _T1} = x_mk_bytes(10000), % file 2 {B2, T2} = x_mk_bytes(5000), % file 3 {B3, T3} = x_mk_bytes(4000), % file 4 {B4, T4} = x_mk_bytes(2000), % file 4 {B5, T5} = x_mk_bytes(5000), % file 1 {B6, T6} = x_mk_bytes(5000), % file 2 - ?line ok = disk_log:blog(a, B1), - ?line ok = disk_log:blog(a, B2), - ?line ok = disk_log:blog(a, B3), - ?line ok = disk_log:blog_terms(a, [B4, B5, B6]), - ?line case get_list(File ++ ".3", a) of - T2 -> - ok; - E2 -> - test_server_fail({bad_terms, E2, T2}) - end, - ?line T34 = T3 ++ T4, - ?line case get_list(File ++ ".4", a) of - T34 -> - ok; - E34 -> - test_server_fail({bad_terms, E34, T34}) - end, - ?line case get_list(File ++ ".1", a) of - T5 -> - ok; - E5 -> - test_server_fail({bad_terms, E5, T5}) - end, - ?line case get_list(File ++ ".2", a) of - T6 -> - ok; - E6 -> - test_server_fail({bad_terms, E6, T6}) - end, - ?line ok = disk_log:close(a), + ok = disk_log:blog(a, B1), + ok = disk_log:blog(a, B2), + ok = disk_log:blog(a, B3), + ok = disk_log:blog_terms(a, [B4, B5, B6]), + case get_list(File ++ ".3", a) of + T2 -> + ok; + E2 -> + test_server_fail({bad_terms, E2, T2}) + end, + T34 = T3 ++ T4, + case get_list(File ++ ".4", a) of + T34 -> + ok; + E34 -> + test_server_fail({bad_terms, E34, T34}) + end, + case get_list(File ++ ".1", a) of + T5 -> + ok; + E5 -> + test_server_fail({bad_terms, E5, T5}) + end, + case get_list(File ++ ".2", a) of + T6 -> + ok; + E6 -> + test_server_fail({bad_terms, E6, T6}) + end, + ok = disk_log:close(a), del(File, 4). -wrap_ext_2(suite) -> []; -wrap_ext_2(doc) -> ["Test wrap disk log, external, size defined"]; +%% Test wrap disk log, external, size defined. wrap_ext_2(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File1 = filename:join(Dir, "a.LOG"), File2 = filename:join(Dir, "b.LOG"), File3 = filename:join(Dir, "c.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}}, - {format,external}, - {file, File1}]), - ?line {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}}, - {format,external}, - {file, File2}]), - ?line {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}}, - {format,external}, - {file, File3}]), + {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}}, + {format,external}, + {file, File1}]), + {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}}, + {format,external}, + {file, File2}]), + {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}}, + {format,external}, + {file, File3}]), {B1, T1} = x_mk_bytes(8191), {B2, T2} = x_mk_bytes(8192), {B3, T3} = x_mk_bytes(8193), - ?line ok = disk_log:blog(a, B1), - ?line ok = disk_log:blog(b, B2), - ?line ok = disk_log:blog(c, B3), - ?line case get_list(File1 ++ ".1", a) of - T1 -> - ok; - E1 -> - test_server_fail({bad_terms, E1, T1}) - end, - ?line case get_list(File2 ++ ".1", b) of - T2 -> - ok; - E2 -> - test_server_fail({bad_terms, E2, T2}) - end, - ?line case get_list(File3 ++ ".1", c) of - T3 -> - ok; - E3 -> - test_server_fail({bad_terms, E3, T3}) - end, - ?line ok = disk_log:close(a), - ?line ok = disk_log:close(b), - ?line ok = disk_log:close(c), - ?line del(File1, 3), - ?line del(File2, 3), - ?line del(File3, 3), + ok = disk_log:blog(a, B1), + ok = disk_log:blog(b, B2), + ok = disk_log:blog(c, B3), + case get_list(File1 ++ ".1", a) of + T1 -> + ok; + E1 -> + test_server_fail({bad_terms, E1, T1}) + end, + case get_list(File2 ++ ".1", b) of + T2 -> + ok; + E2 -> + test_server_fail({bad_terms, E2, T2}) + end, + case get_list(File3 ++ ".1", c) of + T3 -> + ok; + E3 -> + test_server_fail({bad_terms, E3, T3}) + end, + ok = disk_log:close(a), + ok = disk_log:close(b), + ok = disk_log:close(c), + del(File1, 3), + del(File2, 3), + del(File3, 3), ok. simple_log(Log) -> @@ -879,61 +839,61 @@ simple_log(Log) -> T2 = hopp, T3 = {tjena, 12}, T4 = mk_bytes(10000), - ?line ok = disk_log:log(Log, T1), - ?line ok = disk_log:log_terms(Log, [T2, T3]), - ?line case get_all_terms(Log) of - [T1, T2, T3] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, [T1, T2, T3]}) - end, - ?line ok = disk_log:log(a, T4), - ?line case get_all_terms(Log) of - [T1, T2, T3, T4] -> - ok; - E2 -> - test_server_fail({bad_terms, E2, [T1, T2, T3, T4]}) - end. + ok = disk_log:log(Log, T1), + ok = disk_log:log_terms(Log, [T2, T3]), + case get_all_terms(Log) of + [T1, T2, T3] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, [T1, T2, T3]}) + end, + ok = disk_log:log(a, T4), + case get_all_terms(Log) of + [T1, T2, T3, T4] -> + ok; + E2 -> + test_server_fail({bad_terms, E2, [T1, T2, T3, T4]}) + end. xsimple_log(File, Log) -> T1 = "hej", T2 = list_to_binary("hopp"), T3 = list_to_binary(["sena", list_to_binary("sejer")]), T4 = list_to_binary(By = mk_bytes(10000)), - ?line ok = disk_log:blog(Log, T1), - ?line ok = disk_log:blog_terms(Log, [T2, T3]), - ?line X = "hejhoppsenasejer", - ?line X2 = get_list(File, Log), - ?line case X2 of - X -> ok; - Z1 -> test_server_fail({bad_terms, Z1, X2}) - end, - ?line ok = disk_log:blog(Log, T4), - ?line Tmp = get_list(File, Log), - ?line case X ++ By of - Tmp -> ok; - Z2 -> test_server_fail({bad_terms, Z2, X ++ By}) - end. + ok = disk_log:blog(Log, T1), + ok = disk_log:blog_terms(Log, [T2, T3]), + X = "hejhoppsenasejer", + X2 = get_list(File, Log), + case X2 of + X -> ok; + Z1 -> test_server_fail({bad_terms, Z1, X2}) + end, + ok = disk_log:blog(Log, T4), + Tmp = get_list(File, Log), + case X ++ By of + Tmp -> ok; + Z2 -> test_server_fail({bad_terms, Z2, X ++ By}) + end. x2simple_log(File, Log) -> T1 = "hej", T2 = list_to_binary("hopp"), T3 = list_to_binary(["sena", list_to_binary("sejer")]), T4 = list_to_binary(By = mk_bytes(1000)), - ?line ok = disk_log:blog(Log, T1), - ?line ok = disk_log:blog_terms(Log, [T2, T3]), - ?line X = "hejhoppsenasejer", - ?line X2 = get_list(File, Log), - ?line case X2 of - X -> ok; - Z1 -> test_server_fail({bad_terms, Z1, X2}) - end, - ?line ok = disk_log:blog(Log, T4), - ?line Tmp = get_list(File, Log), - ?line case X ++ By of - Tmp -> ok; - Z2 -> test_server_fail({bad_terms, Z2, X ++ By}) - end. + ok = disk_log:blog(Log, T1), + ok = disk_log:blog_terms(Log, [T2, T3]), + X = "hejhoppsenasejer", + X2 = get_list(File, Log), + case X2 of + X -> ok; + Z1 -> test_server_fail({bad_terms, Z1, X2}) + end, + ok = disk_log:blog(Log, T4), + Tmp = get_list(File, Log), + case X ++ By of + Tmp -> ok; + Z2 -> test_server_fail({bad_terms, Z2, X ++ By}) + end. x_mk_bytes(N) -> X = lists:duplicate(N, $a), @@ -947,7 +907,7 @@ mk_bytes(N) when N > 4 -> end. get_list(File, Log) -> - ?t:format(0, "File ~p~n",[File]), + ct:pal(?HI_VERBOSITY, "File ~p~n", [File]), ok = disk_log:sync(Log), {ok, B} = file:read_file(File), binary_to_list(B). @@ -955,7 +915,7 @@ get_list(File, Log) -> get_all_terms(Log, File, Type) -> {ok, _Log} = disk_log:open([{name,Log}, {type,Type}, {size,infinity}, - {format,internal}, {file, File}, + {format,internal}, {file, File}, {mode, read_only}]), Ts = get_all_terms(Log), ok = disk_log:close(Log), @@ -976,14 +936,14 @@ get_all_terms1(Log, Cont, Res) -> get_all_terms_and_bad(Log, File, Type) -> {ok, _Log} = disk_log:open([{name,Log}, {type,Type}, {size,infinity}, - {format,internal}, {file, File}, + {format,internal}, {file, File}, {mode, read_only}]), Ts = get_all_terms_and_bad(Log), ok = disk_log:close(Log), Ts. get_all_terms_and_bad(Log) -> - ?line read_only = info(Log, mode, foo), + read_only = info(Log, mode, foo), get_all_terms_and_bad1(Log, start, [], 0). %% @@ -999,7 +959,7 @@ get_all_terms_and_bad1(Log, Cont, Res, Bad0) -> get_all_binary_terms_and_bad(Log, File, Type) -> {ok, _Log} = disk_log:open([{name,Log}, {type,Type}, {size,infinity}, - {format,internal}, {file, File}, + {format,internal}, {file, File}, {mode, read_only}]), Ts = get_all_binary_terms_and_bad(Log), ok = disk_log:close(Log), @@ -1037,7 +997,7 @@ xx() -> {format,internal}, {file, File}]), W = xwr(a, 400), disk_log:close(a), -% file:delete(File), + %% file:delete(File), W. %% old: 6150 @@ -1186,73 +1146,72 @@ end_times({T1,W1}) -> {T2-T1, W2-W1}. -head_func(suite) -> []; -head_func(doc) -> ["Test head parameter"]; +%% Test head parameter. head_func(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), ets:new(xxx, [named_table, set, public]), ets:insert(xxx, {wrapc, 0}), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,4}}, - {head_func, {?MODULE, hf, []}}]), - ?line B = mk_bytes(60), - ?line disk_log:log(a, B), - ?line disk_log:alog(a, B), - ?line disk_log:alog(a, B), - ?line disk_log:log(a, B), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,4}}, + {head_func, {?MODULE, hf, []}}]), + B = mk_bytes(60), + disk_log:log(a, B), + disk_log:alog(a, B), + disk_log:alog(a, B), + disk_log:log(a, B), H = [1,2,3], - ?line [{wrapc, 4}] = ets:lookup(xxx, wrapc), + [{wrapc, 4}] = ets:lookup(xxx, wrapc), ets:delete(xxx), - ?line case get_all_terms(a) of - [H,B,H,B,H,B,H,B] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, - [H,B,H,B,H,B,H,B]}) - end, - ?line 8 = no_written_items(a), + case get_all_terms(a) of + [H,B,H,B,H,B,H,B] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, + [H,B,H,B,H,B,H,B]}) + end, + 8 = no_written_items(a), disk_log:close(a), del(File, 4), - % invalid header function - ?line {error, {invalid_header, {_, {term}}}} = + %% invalid header function + {error, {invalid_header, {_, {term}}}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, external}, {head_func, {?MODULE, head_fun, [{term}]}}]), file:delete(File), - ?line {error, {invalid_header, _}} = + {error, {invalid_header, _}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, external}, {head_func, {?MODULE, head_fun, [{ok,{term}}]}}]), file:delete(File), - ?line {ok,n} = + {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, external}, {head_func, {?MODULE, head_fun, [{ok,<<"head">>}]}}]), - ?line ok = disk_log:close(n), - ?line {ok,<<"head">>} = file:read_file(File), + ok = disk_log:close(n), + {ok,<<"head">>} = file:read_file(File), file:delete(File), - ?line {ok,n} = + {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, external}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), - ?line ok = disk_log:close(n), - ?line {ok,<<"head">>} = file:read_file(File), + ok = disk_log:close(n), + {ok,<<"head">>} = file:read_file(File), file:delete(File), - ?line Error1 = {error, {badarg, _}} = + Error1 = {error, {badarg, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {head_func, {tjo,hej,san}},{size, {100, 4}}]), - ?line "The argument " ++ _ = format_error(Error1), - - ?line Error2 = {error, {invalid_header, _}} = + "The argument " ++ _ = format_error(Error1), + + Error2 = {error, {invalid_header, _}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {head_func, {tjo,hej,[san]}}]), - ?line "The disk log header" ++ _ = format_error(Error2), + "The disk log header" ++ _ = format_error(Error2), file:delete(File). @@ -1263,194 +1222,186 @@ hf() -> ets:update_counter(xxx, wrapc, 1), {ok, [1,2,3]}. -plain_head(suite) -> []; -plain_head(doc) -> ["Test head parameter"]; +%% Test head parameter. plain_head(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), H = [1,2,3], - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,4}}, {head, H}]), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,4}}, {head, H}]), %% This one is not "counted". - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,4}}, {head, H}]), - ?line B = mk_bytes(60), - ?line disk_log:log(a, B), - ?line disk_log:alog(a, B), - ?line disk_log:alog(a, B), - ?line disk_log:log(a, B), - ?line case get_all_terms(a) of - [H,B,H,B,H,B,H,B] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, - [H,B,H,B,H,B,H,B]}) - end, - ?line 8 = no_written_items(a), - ?line ok = disk_log:close(a), - ?line {error, no_such_log} = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,4}}, {head, H}]), + B = mk_bytes(60), + disk_log:log(a, B), + disk_log:alog(a, B), + disk_log:alog(a, B), + disk_log:log(a, B), + case get_all_terms(a) of + [H,B,H,B,H,B,H,B] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, + [H,B,H,B,H,B,H,B]}) + end, + 8 = no_written_items(a), + ok = disk_log:close(a), + {error, no_such_log} = disk_log:close(a), del(File, 4). -one_header(suite) -> []; -one_header(doc) -> ["Test that a header is just printed once in a log file"]; +%% Test that a header is just printed once in a log file. one_header(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), H = [1,2,3], - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,4}}, {head, H}]), - ?line B = mk_bytes(60), - ?line ok = disk_log:log(a, B), - ?line ok = disk_log:alog(a, B), - ?line ok = disk_log:alog(a, B), - ?line ok = disk_log:log(a, B), - ?line case get_all_terms(a) of - [H,B,H,B,H,B,H,B] -> - ok; - E1 -> - test_server_fail({bad_terms, E1, - [H,B,H,B,H,B,H,B]}) - end, - ?line 8 = no_written_items(a), - ?line ok = disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,4}}, {head, H}]), + B = mk_bytes(60), + ok = disk_log:log(a, B), + ok = disk_log:alog(a, B), + ok = disk_log:alog(a, B), + ok = disk_log:log(a, B), + case get_all_terms(a) of + [H,B,H,B,H,B,H,B] -> + ok; + E1 -> + test_server_fail({bad_terms, E1, + [H,B,H,B,H,B,H,B]}) + end, + 8 = no_written_items(a), + ok = disk_log:close(a), del(File, 4), Fileb = filename:join(Dir, "b.LOG"), - ?line {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]), - ?line ok = disk_log:close(b), - ?line {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]), - ?line ok = disk_log:log(b, "first log"), - ?line ok = disk_log:alog(b, "second log"), - ?line ok = disk_log:close(b), - ?line {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]), - ?line ok = disk_log:alog(b, "3rd log"), - ?line ok = disk_log:log(b, "4th log"), - ?line case get_all_terms(b) of - [H, "first log", "second log", "3rd log", "4th log"] -> - ok; - E2 -> - test_server_fail({bad_terms, E2, - [H, "first log", "second log", - "3rd log", "4th log"]}) - end, - ?line 2 = no_written_items(b), - ?line ok = disk_log:close(b), - ?line ok = file:delete(Fileb), + {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]), + ok = disk_log:close(b), + {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]), + ok = disk_log:log(b, "first log"), + ok = disk_log:alog(b, "second log"), + ok = disk_log:close(b), + {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]), + ok = disk_log:alog(b, "3rd log"), + ok = disk_log:log(b, "4th log"), + case get_all_terms(b) of + [H, "first log", "second log", "3rd log", "4th log"] -> + ok; + E2 -> + test_server_fail({bad_terms, E2, + [H, "first log", "second log", + "3rd log", "4th log"]}) + end, + 2 = no_written_items(b), + ok = disk_log:close(b), + ok = file:delete(Fileb), Filec = filename:join(Dir, "c.LOG"), H2 = "this is a header ", - ?line {ok, c} = disk_log:open([{name,c}, {format, external}, - {file, Filec}, {head, H2}]), - ?line ok = disk_log:close(c), - ?line {ok, c} = disk_log:open([{name,c}, {format, external}, - {file, Filec}, {head, H2}]), - ?line ok = disk_log:blog(c, "first log"), - ?line ok = disk_log:balog(c, "second log"), - ?line ok = disk_log:close(c), - ?line {ok, c} = disk_log:open([{name,c}, {format, external}, - {file, Filec}, {head, H2}]), - ?line ok = disk_log:balog(c, "3rd log"), - ?line ok = disk_log:blog(c, "4th log"), - ?line ok = disk_log:sync(c), - ?line {ok, Fdc} = file:open(Filec, [read]), - ?line {ok,"this is a header first logsecond log3rd log4th log"} = + {ok, c} = disk_log:open([{name,c}, {format, external}, + {file, Filec}, {head, H2}]), + ok = disk_log:close(c), + {ok, c} = disk_log:open([{name,c}, {format, external}, + {file, Filec}, {head, H2}]), + ok = disk_log:blog(c, "first log"), + ok = disk_log:balog(c, "second log"), + ok = disk_log:close(c), + {ok, c} = disk_log:open([{name,c}, {format, external}, + {file, Filec}, {head, H2}]), + ok = disk_log:balog(c, "3rd log"), + ok = disk_log:blog(c, "4th log"), + ok = disk_log:sync(c), + {ok, Fdc} = file:open(Filec, [read]), + {ok,"this is a header first logsecond log3rd log4th log"} = file:read(Fdc, 200), - ?line ok = file:close(Fdc), - ?line 2 = no_written_items(c), - ?line disk_log:close(c), - ?line ok = file:delete(Filec), + ok = file:close(Fdc), + 2 = no_written_items(c), + disk_log:close(c), + ok = file:delete(Filec), ok. -wrap_notif(suite) -> []; -wrap_notif(doc) -> ["Test notify parameter, wrap"]; +%% Test notify parameter, wrap. wrap_notif(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,4}}, {notify, true}]), - ?line B = mk_bytes(60), - ?line disk_log:log(a, B), - ?line disk_log:alog(a, B), - ?line disk_log:alog(a, B), - ?line disk_log:log(a, B), - ?line disk_log:log(a, B), - ?line rec(3, {disk_log, node(), a, {wrap, 0}}), - ?line rec(1, {disk_log, node(), a, {wrap, 1}}), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,4}}, {notify, true}]), + B = mk_bytes(60), + disk_log:log(a, B), + disk_log:alog(a, B), + disk_log:alog(a, B), + disk_log:log(a, B), + disk_log:log(a, B), + rec(3, {disk_log, node(), a, {wrap, 0}}), + rec(1, {disk_log, node(), a, {wrap, 1}}), disk_log:close(a), del(File, 4). -full_notif(suite) -> []; -full_notif(doc) -> ["Test notify parameter, wrap, filled file"]; +%% Test notify parameter, wrap, filled file. full_notif(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), file:delete(File), - ?line {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt}, - {size, 100}, {notify, true}]), - ?line B = mk_bytes(60), - ?line disk_log:log(a, B), - ?line disk_log:alog(a, B), - ?line rec(1, {disk_log, node(), a, full}), + {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt}, + {size, 100}, {notify, true}]), + B = mk_bytes(60), + disk_log:log(a, B), + disk_log:alog(a, B), + rec(1, {disk_log, node(), a, full}), disk_log:close(a), file:delete(File). -trunc_notif(suite) -> []; -trunc_notif(doc) -> ["Test notify parameter, wrap, truncated file"]; +%% Test notify parameter, wrap, truncated file. trunc_notif(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), File2 = filename:join(Dir, "a.DUMP"), - ?line {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt}, - {size, 100}, {notify, true}]), - ?line B = mk_bytes(60), - ?line disk_log:log(a, B), - ?line disk_log:truncate(a), - ?line rec(1, {disk_log, node(), a, {truncated, 1}}), - ?line disk_log:log(a, B), - ?line ok = disk_log:reopen(a, File2), - ?line rec(1, {disk_log, node(), a, {truncated, 1}}), + {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt}, + {size, 100}, {notify, true}]), + B = mk_bytes(60), + disk_log:log(a, B), + disk_log:truncate(a), + rec(1, {disk_log, node(), a, {truncated, 1}}), + disk_log:log(a, B), + ok = disk_log:reopen(a, File2), + rec(1, {disk_log, node(), a, {truncated, 1}}), disk_log:close(a), file:delete(File), file:delete(File2). -blocked_notif(suite) -> []; -blocked_notif(doc) -> - ["Test notify parameters 'format_external' and 'blocked_log"]; +%% Test notify parameters 'format_external' and 'blocked_log. blocked_notif(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "n.LOG"), No = 4, - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}, {notify, true}, - {format, external}]), - ?line B = mk_bytes(60), - ?line Error1 = {error,{format_external,n}} = disk_log:log(n, B), - ?line "The requested operation" ++ _ = format_error(Error1), - ?line ok = disk_log:blog(n, B), - ?line ok = disk_log:alog(n, B), - ?line rec(1, {disk_log, node(), n, {format_external, term_to_binary(B)}}), - ?line ok = disk_log:alog_terms(n, [B,B,B,B]), - ?line rec(1, {disk_log, node(), n, {format_external, - lists:map(fun term_to_binary/1, [B,B,B,B])}}), - ?line ok = disk_log:block(n, false), - ?line ok = disk_log:alog(n, B), - ?line rec(1, {disk_log, node(), n, {blocked_log, term_to_binary(B)}}), - ?line ok = disk_log:balog(n, B), - ?line rec(1, {disk_log, node(), n, {blocked_log, list_to_binary(B)}}), - ?line ok = disk_log:balog_terms(n, [B,B,B,B]), - ?line disk_log:close(n), - ?line rec(1, {disk_log, node(), n, {blocked_log, - lists:map(fun list_to_binary/1, [B,B,B,B])}}), - ?line del(File, No). - - -new_idx_vsn(suite) -> []; -new_idx_vsn(doc) -> ["Test the new version of the .idx file"]; + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}, {notify, true}, + {format, external}]), + B = mk_bytes(60), + Error1 = {error,{format_external,n}} = disk_log:log(n, B), + "The requested operation" ++ _ = format_error(Error1), + ok = disk_log:blog(n, B), + ok = disk_log:alog(n, B), + rec(1, {disk_log, node(), n, {format_external, [term_to_binary(B)]}}), + ok = disk_log:alog_terms(n, [B,B,B,B]), + rec(1, {disk_log, node(), n, {format_external, + lists:map(fun term_to_binary/1, [B,B,B,B])}}), + ok = disk_log:block(n, false), + ok = disk_log:alog(n, B), + rec(1, {disk_log, node(), n, {blocked_log, [term_to_binary(B)]}}), + ok = disk_log:balog(n, B), + rec(1, {disk_log, node(), n, {blocked_log, [list_to_binary(B)]}}), + ok = disk_log:balog_terms(n, [B,B,B,B]), + disk_log:close(n), + rec(1, {disk_log, node(), n, {blocked_log, + lists:map(fun list_to_binary/1, [B,B,B,B])}}), + del(File, No). + + +%% Test the new version of the .idx file. new_idx_vsn(Conf) when is_list(Conf) -> DataDir = ?datadir(Conf), PrivDir = ?privdir(Conf), @@ -1459,201 +1410,197 @@ new_idx_vsn(Conf) when is_list(Conf) -> Kurt2 = filename:join(PrivDir, "kurt2.LOG"), %% Test that a wrap log file can have more than 255 files - ?line {ok, new_vsn} = disk_log:open([{file, File}, {name, new_vsn}, - {type, wrap}, {size, {40, 270}}]), - ?line ok = log(new_vsn, 280), - ?line {ok, Bin} = file:read_file(add_ext(File, "idx")), - ?line <<0,0:32,2,10:32,1:64,1:64,_/binary>> = Bin, - ?line disk_log:close(new_vsn), - ?line del(File, 270), + {ok, new_vsn} = disk_log:open([{file, File}, {name, new_vsn}, + {type, wrap}, {size, {40, 270}}]), + ok = log(new_vsn, 280), + {ok, Bin} = file:read_file(add_ext(File, "idx")), + <<0,0:32,2,10:32,1:64,1:64,_/binary>> = Bin, + disk_log:close(new_vsn), + del(File, 270), %% convert a very old version (0) of wrap log file to the new format (2) copy_wrap_log("kurt.LOG", 4, DataDir, PrivDir), - ?line {repaired, kurt, {recovered, 1}, {badbytes, 0}} = + {repaired, kurt, {recovered, 1}, {badbytes, 0}} = disk_log:open([{file, Kurt}, {name, kurt}, {type, wrap}, {size, {40, 4}}]), - ?line ok = disk_log:log(kurt, "this is a logged message number X"), - ?line ok = disk_log:log(kurt, "this is a logged message number Y"), - ?line {ok, BinK} = file:read_file(add_ext(Kurt, "idx")), - ?line <<0,0:32,2,2:32,1:64,1:64,1:64,1:64>> = BinK, - ?line {{40,4}, 2} = disk_log_1:read_size_file_version(Kurt), + ok = disk_log:log(kurt, "this is a logged message number X"), + ok = disk_log:log(kurt, "this is a logged message number Y"), + {ok, BinK} = file:read_file(add_ext(Kurt, "idx")), + <<0,0:32,2,2:32,1:64,1:64,1:64,1:64>> = BinK, + {{40,4}, 2} = disk_log_1:read_size_file_version(Kurt), disk_log:close(kurt), - ?line del(Kurt, 4), + del(Kurt, 4), %% keep the old format (1) copy_wrap_log("kurt2.LOG", 4, DataDir, PrivDir), - ?line {repaired, kurt2, {recovered, 1}, {badbytes, 0}} = + {repaired, kurt2, {recovered, 1}, {badbytes, 0}} = disk_log:open([{file, Kurt2}, {name, kurt2}, {type, wrap}, {size, {40, 4}}]), - ?line ok = disk_log:log(kurt2, "this is a logged message number X"), - ?line ok = disk_log:log(kurt2, "this is a logged message number Y"), - ?line {ok, BinK2} = file:read_file(add_ext(Kurt2, "idx")), - ?line <<0,2:32,1:32,1:32,1:32,1:32>> = BinK2, - ?line {{40,4}, 1} = disk_log_1:read_size_file_version(Kurt2), + ok = disk_log:log(kurt2, "this is a logged message number X"), + ok = disk_log:log(kurt2, "this is a logged message number Y"), + {ok, BinK2} = file:read_file(add_ext(Kurt2, "idx")), + <<0,2:32,1:32,1:32,1:32,1:32>> = BinK2, + {{40,4}, 1} = disk_log_1:read_size_file_version(Kurt2), disk_log:close(kurt2), - ?line del(Kurt2, 4), + del(Kurt2, 4), ok. -reopen(suite) -> []; -reopen(doc) -> - ["Test reopen/1 on halt and wrap logs."]; +%% Test reopen/1 on halt and wrap logs. reopen(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line NewFile = filename:join(Dir, "nn.LOG"), - ?line B = mk_bytes(60), - - ?line file:delete(File), % cleanup - ?line file:delete(NewFile), % cleanup - ?line Q = qlen(), + File = filename:join(Dir, "n.LOG"), + NewFile = filename:join(Dir, "nn.LOG"), + B = mk_bytes(60), + + file:delete(File), % cleanup + file:delete(NewFile), % cleanup + Q = qlen(), %% External halt log. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {notify, true}, {head, "header"}, - {size, infinity},{format, external}]), - ?line ok = disk_log:blog(n, B), - ?line ok = disk_log:breopen(n, NewFile, "head"), - ?line rec(1, {disk_log, node(), n, {truncated, 2}}), - ?line ok = disk_log:blog(n, B), - ?line ok = disk_log:blog(n, B), - ?line ok = disk_log:breopen(n, NewFile, "head"), - ?line rec(1, {disk_log, node(), n, {truncated, 3}}), - ?line ok = disk_log:close(n), - ?line {ok,BinaryFile} = file:read_file(File), - ?line "head" = binary_to_list(BinaryFile), - ?line file:delete(File), - ?line file:delete(NewFile), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {notify, true}, {head, "header"}, + {size, infinity},{format, external}]), + ok = disk_log:blog(n, B), + ok = disk_log:breopen(n, NewFile, "head"), + rec(1, {disk_log, node(), n, {truncated, 2}}), + ok = disk_log:blog(n, B), + ok = disk_log:blog(n, B), + ok = disk_log:breopen(n, NewFile, "head"), + rec(1, {disk_log, node(), n, {truncated, 3}}), + ok = disk_log:close(n), + {ok,BinaryFile} = file:read_file(File), + "head" = binary_to_list(BinaryFile), + file:delete(File), + file:delete(NewFile), %% Internal halt log. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {notify, true}, {head, header}, - {size, infinity}]), - ?line ok = disk_log:log(n, B), - ?line Error1 = {error, {same_file_name, n}} = disk_log:reopen(n, File), - ?line "Current and new" ++ _ = format_error(Error1), - ?line ok = disk_log:reopen(n, NewFile), - ?line rec(1, {disk_log, node(), n, {truncated, 2}}), - ?line ok = disk_log:log(n, B), - ?line ok = disk_log:log(n, B), - ?line ok = disk_log:reopen(n, NewFile), - ?line rec(1, {disk_log, node(), n, {truncated, 3}}), - ?line ok = disk_log:close(n), - ?line [header, _B, _B] = get_all_terms(nn, NewFile, halt), - ?line file:delete(File), - ?line file:delete(NewFile), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {notify, true}, {head, header}, + {size, infinity}]), + ok = disk_log:log(n, B), + Error1 = {error, {same_file_name, n}} = disk_log:reopen(n, File), + "Current and new" ++ _ = format_error(Error1), + ok = disk_log:reopen(n, NewFile), + rec(1, {disk_log, node(), n, {truncated, 2}}), + ok = disk_log:log(n, B), + ok = disk_log:log(n, B), + ok = disk_log:reopen(n, NewFile), + rec(1, {disk_log, node(), n, {truncated, 3}}), + ok = disk_log:close(n), + [header, _B, _B] = get_all_terms(nn, NewFile, halt), + file:delete(File), + file:delete(NewFile), %% Internal wrap log. - ?line No = 4, - ?line del(File, No), % cleanup - ?line del(NewFile, No), % cleanup - - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, - {head, header}, {size, {100, No}}]), - ?line ok = disk_log:log(n, B), - ?line ok = disk_log:log_terms(n, [B,B,B]), + No = 4, + del(File, No), % cleanup + del(NewFile, No), % cleanup + + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, + {head, header}, {size, {100, No}}]), + ok = disk_log:log(n, B), + ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. - ?line rec(3, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line ok = disk_log:reopen(n, NewFile, new_header), - ?line rec(1, {disk_log, node(), n, {truncated, 8}}), - ?line ok = disk_log:log_terms(n, [B,B]), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:close(n), - ?line [header, _, header, _, header, _, header, _] = + rec(3, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + ok = disk_log:reopen(n, NewFile, new_header), + rec(1, {disk_log, node(), n, {truncated, 8}}), + ok = disk_log:log_terms(n, [B,B]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:close(n), + [header, _, header, _, header, _, header, _] = get_all_terms(nn, NewFile, wrap), - ?line [new_header, _, header, _, header, _] = get_all_terms(n, File, wrap), + [new_header, _, header, _, header, _] = get_all_terms(n, File, wrap), - ?line del(NewFile, No), - ?line file:delete(File ++ ".2"), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, - {head, header}, {size, {100, No}}]), + del(NewFile, No), + file:delete(File ++ ".2"), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, + {head, header}, {size, {100, No}}]), %% One file is missing... - ?line ok = disk_log:reopen(n, NewFile), - ?line rec(1, {disk_log, node(), n, {truncated, 6}}), - ?line ok = disk_log:close(n), + ok = disk_log:reopen(n, NewFile), + rec(1, {disk_log, node(), n, {truncated, 6}}), + ok = disk_log:close(n), - ?line del(File, No), - ?line del(NewFile, No), - ?line Q = qlen(), + del(File, No), + del(NewFile, No), + Q = qlen(), ok. -block_blocked(suite) -> []; -block_blocked(doc) -> - ["Test block/1 on external and internal logs."]; +%% Test block/1 on external and internal logs. block_blocked(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line B = mk_bytes(60), + B = mk_bytes(60), Halt = join(Dir, "halt.LOG"), - % External logs. - ?line file:delete(Halt), % cleanup - ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, - {format, external}, {file, Halt}]), - ?line ok = disk_log:sync(halt), - ?line ok = disk_log:block(halt, false), - ?line Error1 = {error, {blocked_log, halt}} = disk_log:block(halt), - ?line "The blocked disk" ++ _ = format_error(Error1), - ?line {error, {blocked_log, halt}} = disk_log:sync(halt), - ?line {error, {blocked_log, halt}} = disk_log:truncate(halt), - ?line {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity), - ?line {error, {blocked_log, halt}} = + %% External logs. + file:delete(Halt), % cleanup + {ok, halt} = disk_log:open([{name, halt}, {type, halt}, + {format, external}, {file, Halt}]), + ok = disk_log:sync(halt), + ok = disk_log:block(halt, false), + Error1 = {error, {blocked_log, halt}} = disk_log:block(halt), + "The blocked disk" ++ _ = format_error(Error1), + {error, {blocked_log, halt}} = disk_log:sync(halt), + {error, {blocked_log, halt}} = disk_log:truncate(halt), + {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity), + {error, {blocked_log, halt}} = disk_log:change_notify(halt, self(), false), - ?line {error, {blocked_log, halt}} = + {error, {blocked_log, halt}} = disk_log:change_header(halt, {head, header}), - ?line {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"), - ?line ok = disk_log:close(halt), - - ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, - {format, external}]), - ?line ok = disk_log:sync(halt), - ?line ok = disk_log:block(halt, true), - ?line {error, {blocked_log, halt}} = disk_log:blog(halt, B), - ?line {error, {blocked_log, halt}} = disk_log:blog(halt, B), - ?line {error, {blocked_log, halt}} = disk_log:block(halt), - ?line {error, {blocked_log, halt}} = disk_log:sync(halt), - ?line {error, {blocked_log, halt}} = disk_log:truncate(halt), - ?line {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity), - ?line {error, {blocked_log, halt}} = + {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"), + ok = disk_log:close(halt), + + {ok, halt} = disk_log:open([{name, halt}, {type, halt}, + {format, external}]), + ok = disk_log:sync(halt), + ok = disk_log:block(halt, true), + {error, {blocked_log, halt}} = disk_log:blog(halt, B), + {error, {blocked_log, halt}} = disk_log:blog(halt, B), + {error, {blocked_log, halt}} = disk_log:block(halt), + {error, {blocked_log, halt}} = disk_log:sync(halt), + {error, {blocked_log, halt}} = disk_log:truncate(halt), + {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity), + {error, {blocked_log, halt}} = disk_log:change_notify(halt, self(), false), - ?line {error, {blocked_log, halt}} = + {error, {blocked_log, halt}} = disk_log:change_header(halt, {head, header}), - ?line {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"), - - ?line ok = disk_log:unblock(halt), - ?line ok = disk_log:close(halt), - ?line file:delete(Halt), - - % Internal logs. - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup - ?line {ok, halt} = disk_log:open([{name, halt}, {file, File}, {type, wrap}, - {size, {100, No}}]), - ?line ok = disk_log:block(halt, true), - ?line eof = disk_log:chunk(halt, start), - ?line Error2 = {error, end_of_log} = disk_log:chunk_step(halt, start, 1), - ?line "An attempt" ++ _ = format_error(Error2), - ?line {error, {blocked_log, halt}} = disk_log:log(halt, B), - ?line {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt), - ?line ok = disk_log:unblock(halt), - ?line ok = disk_log:block(halt, false), - ?line {error, {blocked_log, halt}} = disk_log:log(halt, B), - ?line {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt), - ?line Parent = self(), - ?line Pid = + {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"), + + ok = disk_log:unblock(halt), + ok = disk_log:close(halt), + file:delete(Halt), + + %% Internal logs. + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup + {ok, halt} = disk_log:open([{name, halt}, {file, File}, {type, wrap}, + {size, {100, No}}]), + ok = disk_log:block(halt, true), + eof = disk_log:chunk(halt, start), + Error2 = {error, end_of_log} = disk_log:chunk_step(halt, start, 1), + "An attempt" ++ _ = format_error(Error2), + {error, {blocked_log, halt}} = disk_log:log(halt, B), + {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt), + ok = disk_log:unblock(halt), + ok = disk_log:block(halt, false), + {error, {blocked_log, halt}} = disk_log:log(halt, B), + {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt), + Parent = self(), + Pid = spawn_link(fun() -> {error, {blocked_log, halt}} = disk_log:chunk(halt, start), @@ -1661,109 +1608,107 @@ block_blocked(Conf) when is_list(Conf) -> disk_log:chunk_step(halt, start, 1), Parent ! {self(), stopped} end), - ?line receive {Pid,stopped} -> ok end, - ?line ok = disk_log:close(halt), - ?line del(File, No). + receive {Pid,stopped} -> ok end, + ok = disk_log:close(halt), + del(File, No). -block_queue(suite) -> []; -block_queue(doc) -> - ["Run commands from the queue by unblocking."]; +%% Run commands from the queue by unblocking. block_queue(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line Q = qlen(), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup - ?line B = mk_bytes(60), - - ?line Pid = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid, {open, File}), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {blog, B}), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line 1 = no_written_items(n), - ?line Error1 = {error,{not_blocked,n}} = disk_log:unblock(n), - ?line "The disk log" ++ _ = format_error(Error1), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {balog, "one string"}), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line 2 = no_written_items(n), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, sync), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, truncate), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line 0 = no_items(n), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {block, false}), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line {error, {blocked_log, _}} = disk_log:blog(n, B), - ?line ok = sync_do(Pid, unblock), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {change_notify, Pid, true}), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line [{_, true}] = owners(n), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {change_notify, Pid, false}), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line [{_, false}] = owners(n), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {change_header, {head, header}}), - ?line ok = disk_log:unblock(n), - ?line {error, {badarg, head}} = get_reply(), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {change_size, 17}), - ?line ok = disk_log:unblock(n), - ?line {error, {badarg, size}} = get_reply(), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, inc_wrap_file), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - - ?line ok = sync_do(Pid, close), - ?line del(File, No), - - ?line _Pid2 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid, {int_open, File}), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {chunk, start}), - ?line ok = disk_log:unblock(n), - ?line eof = get_reply(), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {chunk_step, start, 100}), - ?line ok = disk_log:unblock(n), - ?line {ok, _Cont} = get_reply(), - - ?line ok = disk_log:block(n, true), - ?line async_do(Pid, {log,a_term}), - ?line ok = disk_log:unblock(n), - ?line ok = get_reply(), - ?line 1 = no_written_items(n), - - ?line ok = sync_do(Pid, close), - ?line sync_do(Pid, terminate), - ?line del(File, No), + Q = qlen(), + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup + B = mk_bytes(60), + + Pid = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid, {open, File}), + + ok = disk_log:block(n, true), + async_do(Pid, {blog, B}), + ok = disk_log:unblock(n), + ok = get_reply(), + 1 = no_written_items(n), + Error1 = {error,{not_blocked,n}} = disk_log:unblock(n), + "The disk log" ++ _ = format_error(Error1), + + ok = disk_log:block(n, true), + async_do(Pid, {balog, "one string"}), + ok = disk_log:unblock(n), + ok = get_reply(), + 2 = no_written_items(n), + + ok = disk_log:block(n, true), + async_do(Pid, sync), + ok = disk_log:unblock(n), + ok = get_reply(), + + ok = disk_log:block(n, true), + async_do(Pid, truncate), + ok = disk_log:unblock(n), + ok = get_reply(), + 0 = no_items(n), + + ok = disk_log:block(n, true), + async_do(Pid, {block, false}), + ok = disk_log:unblock(n), + ok = get_reply(), + {error, {blocked_log, _}} = disk_log:blog(n, B), + ok = sync_do(Pid, unblock), + + ok = disk_log:block(n, true), + async_do(Pid, {change_notify, Pid, true}), + ok = disk_log:unblock(n), + ok = get_reply(), + [{_, true}] = owners(n), + + ok = disk_log:block(n, true), + async_do(Pid, {change_notify, Pid, false}), + ok = disk_log:unblock(n), + ok = get_reply(), + [{_, false}] = owners(n), + + ok = disk_log:block(n, true), + async_do(Pid, {change_header, {head, header}}), + ok = disk_log:unblock(n), + {error, {badarg, head}} = get_reply(), + + ok = disk_log:block(n, true), + async_do(Pid, {change_size, 17}), + ok = disk_log:unblock(n), + {error, {badarg, size}} = get_reply(), + + ok = disk_log:block(n, true), + async_do(Pid, inc_wrap_file), + ok = disk_log:unblock(n), + ok = get_reply(), + + ok = sync_do(Pid, close), + del(File, No), + + _Pid2 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid, {int_open, File}), + + ok = disk_log:block(n, true), + async_do(Pid, {chunk, start}), + ok = disk_log:unblock(n), + eof = get_reply(), + + ok = disk_log:block(n, true), + async_do(Pid, {chunk_step, start, 100}), + ok = disk_log:unblock(n), + {ok, _Cont} = get_reply(), + + ok = disk_log:block(n, true), + async_do(Pid, {log,a_term}), + ok = disk_log:unblock(n), + ok = get_reply(), + 1 = no_written_items(n), + + ok = sync_do(Pid, close), + sync_do(Pid, terminate), + del(File, No), %% Test of the queue. Three processes involved here. Pid1's block %% request is queued. Pid2's log requests are put in the queue. @@ -1771,171 +1716,165 @@ block_queue(Conf) when is_list(Conf) -> %% Pid2's log requests are executed when Pid1 unblocks. %% (This example should show that the pair 'queue' and 'messages' %% in State does the trick - one does not need a "real" queue.) - ?line P0 = pps(), + P0 = pps(), Name = n, - ?line Pid1 = spawn_link(?MODULE, lserv, [Name]), - ?line {ok, Name} = sync_do(Pid1, {int_open, File, {1000,2}}), - ?line Pid2 = spawn_link(?MODULE, lserv, [Name]), - ?line {ok, Name} = sync_do(Pid2, {int_open, File, {1000,2}}), - ?line ok = disk_log:block(Name), - ?line async_do(Pid1, {alog,{1,a}}), - ?line ok = get_reply(), - ?line async_do(Pid1, {alog,{2,b}}), - ?line ok = get_reply(), - ?line async_do(Pid1, {alog,{3,c}}), - ?line ok = get_reply(), - ?line async_do(Pid1, {alog,{4,d}}), - ?line ok = get_reply(), - ?line async_do(Pid1, block), - ?line async_do(Pid2, {alog,{5,e}}), - ?line ok = get_reply(), - ?line async_do(Pid2, {alog,{6,f}}), - ?line ok = get_reply(), - ?line ok = disk_log:unblock(Name), - ?line ok = get_reply(), - ?line async_do(Pid2, {alog,{7,g}}), - ?line ok = get_reply(), - ?line async_do(Pid2, {alog,{8,h}}), - ?line ok = get_reply(), - ?line async_do(Pid1, unblock), - ?line ok = get_reply(), - ?line ok = sync_do(Pid1, close), - ?line ok = sync_do(Pid2, close), - ?line sync_do(Pid1, terminate), - ?line sync_do(Pid2, terminate), + Pid1 = spawn_link(?MODULE, lserv, [Name]), + {ok, Name} = sync_do(Pid1, {int_open, File, {1000,2}}), + Pid2 = spawn_link(?MODULE, lserv, [Name]), + {ok, Name} = sync_do(Pid2, {int_open, File, {1000,2}}), + ok = disk_log:block(Name), + async_do(Pid1, {alog,{1,a}}), + ok = get_reply(), + async_do(Pid1, {alog,{2,b}}), + ok = get_reply(), + async_do(Pid1, {alog,{3,c}}), + ok = get_reply(), + async_do(Pid1, {alog,{4,d}}), + ok = get_reply(), + async_do(Pid1, block), + async_do(Pid2, {alog,{5,e}}), + ok = get_reply(), + async_do(Pid2, {alog,{6,f}}), + ok = get_reply(), + ok = disk_log:unblock(Name), + ok = get_reply(), + async_do(Pid2, {alog,{7,g}}), + ok = get_reply(), + async_do(Pid2, {alog,{8,h}}), + ok = get_reply(), + async_do(Pid1, unblock), + ok = get_reply(), + ok = sync_do(Pid1, close), + ok = sync_do(Pid2, close), + sync_do(Pid1, terminate), + sync_do(Pid2, terminate), Terms = get_all_terms(Name, File, wrap), - ?line true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms, + true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms, del(File, 2), - ?line Q = qlen(), - ?line true = (P0 == pps()), + Q = qlen(), + true = (P0 == pps()), ok. -block_queue2(suite) -> []; -block_queue2(doc) -> - ["OTP-4880. Blocked processes did not get disk_log_stopped message."]; +%% OTP-4880. Blocked processes did not get disk_log_stopped message. block_queue2(Conf) when is_list(Conf) -> - ?line Q = qlen(), - ?line P0 = pps(), + Q = qlen(), + P0 = pps(), Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, + File = filename:join(Dir, "n.LOG"), + No = 4, %% log requests are queued, and processed when the log is closed - ?line Pid = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid, {open, File}), - ?line ok = sync_do(Pid, block), + Pid = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid, {open, File}), + ok = sync_do(Pid, block), %% Asynchronous stuff is ignored. - ?line ok = disk_log:balog_terms(n, [<<"foo">>,<<"bar">>]), - ?line ok = disk_log:balog_terms(n, [<<"more">>,<<"terms">>]), + ok = disk_log:balog_terms(n, [<<"foo">>,<<"bar">>]), + ok = disk_log:balog_terms(n, [<<"more">>,<<"terms">>]), Parent = self(), - ?line Fun = + Fun = fun() -> {error,no_such_log} = disk_log:sync(n), receive {disk_log, _, {error, disk_log_stopped}} -> ok end, Parent ! disk_log_stopped_ok end, - ?line spawn(Fun), - ?line ok = sync_do(Pid, close), - ?line receive disk_log_stopped_ok -> ok end, - ?line sync_do(Pid, terminate), - ?line {ok,<<>>} = file:read_file(File ++ ".1"), - ?line del(File, No), - ?line Q = qlen(), - ?line true = (P0 == pps()), + spawn(Fun), + ok = sync_do(Pid, close), + receive disk_log_stopped_ok -> ok end, + sync_do(Pid, terminate), + {ok,<<>>} = file:read_file(File ++ ".1"), + del(File, No), + Q = qlen(), + true = (P0 == pps()), ok. -unblock(suite) -> []; -unblock(doc) -> - ["Test unblock/1."]; +%% Test unblock/1. unblock(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "n.LOG"), No = 1, - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}, {notify, true}, - {format, external}]), - ?line ok = disk_log:block(n), - ?line spawn_link(?MODULE, try_unblock, [n]), - ?line timer:sleep(100), - ?line disk_log:close(n), - ?line del(File, No). + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}, {notify, true}, + {format, external}]), + ok = disk_log:block(n), + spawn_link(?MODULE, try_unblock, [n]), + timer:sleep(100), + disk_log:close(n), + del(File, No). try_unblock(Log) -> - ?line Error = {error, {not_blocked_by_pid, n}} = disk_log:unblock(Log), - ?line "The disk log" ++ _ = format_error(Error). + Error = {error, {not_blocked_by_pid, n}} = disk_log:unblock(Log), + "The disk log" ++ _ = format_error(Error). -open_overwrite(suite) -> []; -open_overwrite(doc) -> - ["Test open/1 when old files exist."]; +%% Test open/1 when old files exist. open_overwrite(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup - % read write - ?line First = "n.LOG.1", - ?line make_file(Dir, First, 8), + %% read write + First = "n.LOG.1", + make_file(Dir, First, 8), - ?line Error1 = {error, {not_a_log_file, _}} = + Error1 = {error, {not_a_log_file, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {100, No}}]), - ?line "The file" ++ _ = format_error(Error1), - ?line del(File, No), + "The file" ++ _ = format_error(Error1), + del(File, No), - ?line make_file(Dir, First, 4), + make_file(Dir, First, 4), - ?line {error, {not_a_log_file, _}} = + {error, {not_a_log_file, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {100, No}}]), - ?line del(File, No), + del(File, No), - ?line make_file(Dir, First, 0), + make_file(Dir, First, 0), - ?line {error, {not_a_log_file, _}} = + {error, {not_a_log_file, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {100, No}}]), - % read only - ?line make_file(Dir, First, 6), + %% read only + make_file(Dir, First, 6), - ?line {error, {not_a_log_file, _}} = + {error, {not_a_log_file, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap},{mode, read_only}, {format, internal}, {size, {100, No}}]), - ?line del(File, No), + del(File, No), - ?line make_file(Dir, First, 0), + make_file(Dir, First, 0), - ?line {error, {not_a_log_file, _}} = + {error, {not_a_log_file, _}} = disk_log:open([{name, n}, {file, File},{type, wrap}, {mode, read_only}, {format, internal}, {size, {100, No}}]), - ?line del(File, No), - - ?line {error, _} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {mode, read_only}, - {format, internal},{size, {100, No}}]), + del(File, No), + + {error, _} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {mode, read_only}, + {format, internal},{size, {100, No}}]), file:delete(File), - ?line {ok,n} = disk_log:open([{name,n},{file,File}, - {mode,read_write},{type,halt}]), - ?line ok = disk_log:close(n), - ?line ok = unwritable(File), - ?line {error, {file_error, File, _}} = - disk_log:open([{name,n},{file,File},{mode,read_write},{type,halt}]), - ?line ok = writable(File), + {ok,n} = disk_log:open([{name,n},{file,File}, + {mode,read_write},{type,halt}]), + ok = disk_log:close(n), + ok = unwritable(File), + {error, {file_error, File, _}} = + disk_log:open([{name,n},{file,File},{mode,read_write},{type,halt}]), + ok = writable(File), file:delete(File), - ?line {ok,n} = disk_log:open([{name,n},{file,File},{format,external}, - {mode,read_write},{type,halt}]), - ?line ok = disk_log:close(n), - ?line ok = unwritable(File), - ?line {error, {file_error, File, _}} = + {ok,n} = disk_log:open([{name,n},{file,File},{format,external}, + {mode,read_write},{type,halt}]), + ok = disk_log:close(n), + ok = unwritable(File), + {error, {file_error, File, _}} = disk_log:open([{name,n},{file,File},{format,external}, {mode,read_write},{type,halt}]), - ?line ok = writable(File), + ok = writable(File), file:delete(File), ok. @@ -1953,424 +1892,412 @@ make_file(Dir, File, N) -> end, ok = file:close(F). -open_size(suite) -> []; -open_size(doc) -> - ["Test open/1 option size."]; +%% Test open/1 option size. open_size(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), + Dir = ?privdir(Conf), + File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line file:delete(File), - ?line del(File, No), % cleanup + No = 4, + file:delete(File), + del(File, No), % cleanup %% missing size option - ?line {error, {badarg, size}} = + {error, {badarg, size}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal},{size, {100, No}}]), - ?line B = mk_bytes(60), - ?line ok = disk_log:log_terms(n, [B, B, B, B]), - ?line ok = disk_log:sync(n), - ?line ok = disk_log:block(n), + B = mk_bytes(60), + ok = disk_log:log_terms(n, [B, B, B, B]), + ok = disk_log:sync(n), + ok = disk_log:block(n), %% size option does not match existing size file, read_only - ?line Error1 = {error, {size_mismatch, _, _}} = + Error1 = {error, {size_mismatch, _, _}} = disk_log:open([{name, nn}, {file, File}, {type, wrap}, {mode, read_only}, {format, internal}, {size, {100, No + 1}}]), - ?line "The given size" ++ _ = format_error(Error1), - ?line {ok, nn} = disk_log:open([{name, nn}, {file, File}, {type, wrap}, + "The given size" ++ _ = format_error(Error1), + {ok, nn} = disk_log:open([{name, nn}, {file, File}, {type, wrap}, {mode, read_only}, {format, internal},{size, {100, No}}]), - ?line [_, _, _, _] = get_all_terms1(nn, start, []), - ?line disk_log:close(nn), + [_, _, _, _] = get_all_terms1(nn, start, []), + disk_log:close(nn), - ?line ok = disk_log:unblock(n), - ?line ok = disk_log:close(n), + ok = disk_log:unblock(n), + ok = disk_log:close(n), %% size option does not match existing size file, read_write - ?line {error, {size_mismatch, _, _}} = + {error, {size_mismatch, _, _}} = disk_log:open([{name, nn}, {file, File}, {type, wrap}, {format, internal}, {size, {100, No + 1}}]), %% size option does not match existing size file, truncating - ?line {ok, nn} = + {ok, nn} = disk_log:open([{name, nn}, {file, File}, {type, wrap}, {repair, truncate}, {format, internal}, {size, {100, No + 1}}]), - ?line ok = disk_log:close(nn), + ok = disk_log:close(nn), - ?line del(File, No), + del(File, No), ok. -open_truncate(suite) -> []; -open_truncate(doc) -> - ["Test open/1 with {repair, truncate}."]; +%% Test open/1 with {repair, truncate}. open_truncate(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup - - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal},{size, {100, No}}]), - ?line B = mk_bytes(60), - ?line ok = disk_log:log_terms(n, [B, B, B, B]), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {repair,truncate}, - {format, internal},{size, {100, No}}]), - ?line ok = disk_log:close(n), - ?line [] = get_all_terms(n, File, wrap), - ?line del(File, No), + Dir = ?privdir(Conf), + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup + + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal},{size, {100, No}}]), + B = mk_bytes(60), + ok = disk_log:log_terms(n, [B, B, B, B]), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {repair,truncate}, + {format, internal},{size, {100, No}}]), + ok = disk_log:close(n), + [] = get_all_terms(n, File, wrap), + del(File, No), ok. - -open_error(suite) -> []; -open_error(doc) -> - ["Try some invalid open/1 options."]; + +%% Try some invalid open/1 options. open_error(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), + Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup - ?line {error, {badarg, name}} = disk_log:open([{file, File}]), - ?line {error, {badarg, file}} = disk_log:open([{name,{foo,bar}}]), - ?line {error, {badarg, [{foo,bar}]}} = disk_log:open([{foo,bar}]), + {error, {badarg, name}} = disk_log:open([{file, File}]), + {error, {badarg, file}} = disk_log:open([{name,{foo,bar}}]), + {error, {badarg, [{foo,bar}]}} = disk_log:open([{foo,bar}]), %% external logs, read_only. - ?line {error, {file_error, _, enoent}} = + {error, {file_error, _, enoent}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}, {format, external}, {mode, read_only}]), - ?line Error5 = {error, {file_error, _, enoent}} = + Error5 = {error, {file_error, _, enoent}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {size, 100}, {format, external}, {mode, read_only}]), - ?line true = lists:prefix("\"" ++ File, format_error(Error5)), + true = lists:prefix("\"" ++ File, format_error(Error5)), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, external},{size, {100, No}}]), %% Already owner, ignored. - ?line {ok, n} = + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, external}, {size, {100, No}}]), - ?line Error2 = {error, {name_already_open, n}} = + Error2 = {error, {name_already_open, n}} = disk_log:open([{name, n}, {file, another_file}, {type, wrap}, {format, external}, {size, {100, No}}]), - ?line "The disk log" ++ _ = format_error(Error2), - ?line Error1 = {error, {arg_mismatch, notify, false, true}} = + "The disk log" ++ _ = format_error(Error2), + Error1 = {error, {arg_mismatch, notify, false, true}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, external}, {size, {100, No}}, {notify, true}]), - ?line "The value" ++ _ = format_error(Error1), - ?line Error3 = {error, {open_read_write, n}} = + "The value" ++ _ = format_error(Error1), + Error3 = {error, {open_read_write, n}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {mode, read_only}, {format, external}, {size, {100, No}}]), - ?line "The disk log" ++ _ = format_error(Error3), - ?line {error, {badarg, size}} = + "The disk log" ++ _ = format_error(Error3), + {error, {badarg, size}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, external}, {size, {100, No}}]), - ?line {error, {arg_mismatch, type, wrap, halt}} = + {error, {arg_mismatch, type, wrap, halt}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, external}]), - ?line {error, {arg_mismatch, format, external, internal}} = + {error, {arg_mismatch, format, external, internal}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {100, No}}]), - ?line {error, {arg_mismatch, repair, true, false}} = + {error, {arg_mismatch, repair, true, false}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, external}, {repair, false}]), - ?line {error, {size_mismatch, {100,4}, {1000,4}}} = + {error, {size_mismatch, {100,4}, {1000,4}}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, external}, {size, {1000, No}}]), - ?line {error, {arg_mismatch, head, none, _}} = + {error, {arg_mismatch, head, none, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {head, "header"}, {format, external}, {size, {100, No}}]), - ?line {error, {badarg, size}} = + {error, {badarg, size}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, external}, {size, 100}]), - ?line ok = disk_log:close(n), + ok = disk_log:close(n), - ?line {ok, n} = + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {mode, read_only}, {format, external}, {size, {100, No}}]), - ?line Error4 = {error, {open_read_only, n}} = + Error4 = {error, {open_read_only, n}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {mode, read_write}, {format, external}, {size, {100, No}}]), - ?line "The disk log" ++ _ = format_error(Error4), - ?line ok = disk_log:close(n), + "The disk log" ++ _ = format_error(Error4), + ok = disk_log:close(n), - ?line del(File, No). + del(File, No). -close_race(suite) -> []; -close_race(doc) -> - ["Do something quickly after close/1"]; +%% Do something quickly after close/1. close_race(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 1, - ?line del(File, No), % cleanup - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}, {notify, true}, - {format, internal}]), - ?line ok = disk_log:close(n), - ?line Error1 = {error, no_such_log} = disk_log:close(n), - ?line "There is no disk" ++ _ = format_error(Error1), - - % Pid1 blocks, Pid2 closes without being suspended. - ?line Pid1 = spawn_link(?MODULE, lserv, [n]), - ?line Pid2 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid1, {open, File}), - ?line {ok, n} = sync_do(Pid2, {open, File}), - ?line ok = sync_do(Pid1, block), - ?line [{_, false}, {_, false}] = sync_do(Pid1, owners), - ?line ok = sync_do(Pid2, close), - ?line [{_, false}] = sync_do(Pid1, owners), - ?line ok = sync_do(Pid1, close), - ?line sync_do(Pid1, terminate), - ?line sync_do(Pid2, terminate), - ?line {error, no_such_log} = disk_log:info(n), - - % Pid3 blocks, Pid3 closes. Pid4 should still be ablo to use log. - ?line Pid3 = spawn_link(?MODULE, lserv, [n]), - ?line Pid4 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid3, {open, File}), - ?line {ok, n} = sync_do(Pid4, {open, File}), - ?line ok = sync_do(Pid3, block), - ?line ok = sync_do(Pid3, close), - ?line [{_Pid4, false}] = sync_do(Pid4, owners), - ?line sync_do(Pid3, terminate), - ?line sync_do(Pid4, terminate), - ?line {error, no_such_log} = disk_log:info(n), - - % Pid5 blocks, Pid5 terminates. Pid6 should still be ablo to use log. - ?line Pid5 = spawn_link(?MODULE, lserv, [n]), - ?line Pid6 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid5, {open, File}), - ?line {ok, n} = sync_do(Pid6, {open, File}), - ?line ok = sync_do(Pid5, block), - ?line sync_do(Pid5, terminate), - ?line [{_Pid6, false}] = sync_do(Pid6, owners), - ?line sync_do(Pid6, terminate), - ?line {error, no_such_log} = disk_log:info(n), - ?line del(File, No), % cleanup + File = filename:join(Dir, "n.LOG"), + No = 1, + del(File, No), % cleanup + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}, {notify, true}, + {format, internal}]), + ok = disk_log:close(n), + Error1 = {error, no_such_log} = disk_log:close(n), + "There is no disk" ++ _ = format_error(Error1), + + %% Pid1 blocks, Pid2 closes without being suspended. + Pid1 = spawn_link(?MODULE, lserv, [n]), + Pid2 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid1, {open, File}), + {ok, n} = sync_do(Pid2, {open, File}), + ok = sync_do(Pid1, block), + [{_, false}, {_, false}] = sync_do(Pid1, owners), + ok = sync_do(Pid2, close), + [{_, false}] = sync_do(Pid1, owners), + ok = sync_do(Pid1, close), + sync_do(Pid1, terminate), + sync_do(Pid2, terminate), + {error, no_such_log} = disk_log:info(n), + + %% Pid3 blocks, Pid3 closes. Pid4 should still be ablo to use log. + Pid3 = spawn_link(?MODULE, lserv, [n]), + Pid4 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid3, {open, File}), + {ok, n} = sync_do(Pid4, {open, File}), + ok = sync_do(Pid3, block), + ok = sync_do(Pid3, close), + [{_Pid4, false}] = sync_do(Pid4, owners), + sync_do(Pid3, terminate), + sync_do(Pid4, terminate), + {error, no_such_log} = disk_log:info(n), + + %% Pid5 blocks, Pid5 terminates. Pid6 should still be ablo to use log. + Pid5 = spawn_link(?MODULE, lserv, [n]), + Pid6 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid5, {open, File}), + {ok, n} = sync_do(Pid6, {open, File}), + ok = sync_do(Pid5, block), + sync_do(Pid5, terminate), + [{_Pid6, false}] = sync_do(Pid6, owners), + sync_do(Pid6, terminate), + {error, no_such_log} = disk_log:info(n), + del(File, No), % cleanup ok. -close_block(suite) -> []; -close_block(doc) -> - ["Block, unblock, close, terminate."]; +%% Block, unblock, close, terminate. close_block(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), + File = filename:join(Dir, "n.LOG"), No = 1, del(File, No), % cleanup P0 = pps(), %% One of two owners terminates. - ?line Pid1 = spawn_link(?MODULE, lserv, [n]), - ?line Pid2 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid1, {open, File}), - ?line {ok, n} = sync_do(Pid2, {open, File}), - ?line [_, _] = sync_do(Pid1, owners), - ?line [_, _] = sync_do(Pid2, owners), - ?line 0 = sync_do(Pid1, users), - ?line 0 = sync_do(Pid2, users), - ?line sync_do(Pid1, terminate), - ?line [_] = sync_do(Pid2, owners), - ?line 0 = sync_do(Pid2, users), - ?line sync_do(Pid2, terminate), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), + Pid1 = spawn_link(?MODULE, lserv, [n]), + Pid2 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid1, {open, File}), + {ok, n} = sync_do(Pid2, {open, File}), + [_, _] = sync_do(Pid1, owners), + [_, _] = sync_do(Pid2, owners), + 0 = sync_do(Pid1, users), + 0 = sync_do(Pid2, users), + sync_do(Pid1, terminate), + [_] = sync_do(Pid2, owners), + 0 = sync_do(Pid2, users), + sync_do(Pid2, terminate), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), %% Users terminate (no link...). - ?line Pid3 = spawn_link(?MODULE, lserv, [n]), - ?line Pid4 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid3, {open, File, none}), - ?line {ok, n} = sync_do(Pid4, {open, File, none}), - ?line [] = sync_do(Pid3, owners), - ?line [] = sync_do(Pid4, owners), - ?line 2 = sync_do(Pid3, users), - ?line 2 = sync_do(Pid4, users), - ?line sync_do(Pid3, terminate), - ?line [] = sync_do(Pid4, owners), - ?line 2 = sync_do(Pid4, users), - ?line sync_do(Pid4, terminate), - ?line disk_log:close(n), - ?line disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), - - % Blocking owner terminates. - ?line Pid5 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {linkto, none},{size, {100,No}}, - {format, external}]), - ?line {ok, n} = sync_do(Pid5, {open, File}), - ?line ok = sync_do(Pid5, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line sync_do(Pid5, terminate), - ?line ok = status(n), - ?line [] = owners(n), - ?line 1 = users(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), - - % Blocking user terminates. - ?line Pid6 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}, {format, external}]), - ?line {ok, n} = sync_do(Pid6, {open, File, none}), - ?line ok = sync_do(Pid6, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line sync_do(Pid6, terminate), % very silently... - ?line ok = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line ok = disk_log:close(n), - ?line [] = owners(n), - ?line 1 = users(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), - - % Blocking owner terminates. - ?line Pid7 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {linkto, none}, - {size, {100,No}}, {format, external}]), - ?line {ok, n} = sync_do(Pid7, {open, File}), - ?line ok = sync_do(Pid7, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line sync_do(Pid7, terminate), - ?line ok = status(n), - ?line [] = owners(n), - ?line 1 = users(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), + Pid3 = spawn_link(?MODULE, lserv, [n]), + Pid4 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid3, {open, File, none}), + {ok, n} = sync_do(Pid4, {open, File, none}), + [] = sync_do(Pid3, owners), + [] = sync_do(Pid4, owners), + 2 = sync_do(Pid3, users), + 2 = sync_do(Pid4, users), + sync_do(Pid3, terminate), + [] = sync_do(Pid4, owners), + 2 = sync_do(Pid4, users), + sync_do(Pid4, terminate), + disk_log:close(n), + disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), + + %% Blocking owner terminates. + Pid5 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {linkto, none},{size, {100,No}}, + {format, external}]), + {ok, n} = sync_do(Pid5, {open, File}), + ok = sync_do(Pid5, block), + {blocked, true} = status(n), + [_] = owners(n), + sync_do(Pid5, terminate), + ok = status(n), + [] = owners(n), + 1 = users(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), + + %% Blocking user terminates. + Pid6 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}, {format, external}]), + {ok, n} = sync_do(Pid6, {open, File, none}), + ok = sync_do(Pid6, block), + {blocked, true} = status(n), + [_] = owners(n), + 1 = users(n), + sync_do(Pid6, terminate), % very silently... + ok = status(n), + [_] = owners(n), + 1 = users(n), + ok = disk_log:close(n), + [] = owners(n), + 1 = users(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), + + %% Blocking owner terminates. + Pid7 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {linkto, none}, + {size, {100,No}}, {format, external}]), + {ok, n} = sync_do(Pid7, {open, File}), + ok = sync_do(Pid7, block), + {blocked, true} = status(n), + [_] = owners(n), + 1 = users(n), + sync_do(Pid7, terminate), + ok = status(n), + [] = owners(n), + 1 = users(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), %% Two owners, the blocking one terminates. - ?line Pid8 = spawn_link(?MODULE, lserv, [n]), - ?line Pid9 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = sync_do(Pid8, {open, File}), - ?line {ok, n} = sync_do(Pid9, {open, File}), - ?line ok = sync_do(Pid8, block), - ?line {blocked, true} = status(n), - ?line sync_do(Pid8, terminate), - ?line ok = status(n), - ?line [_] = sync_do(Pid9, owners), - ?line 0 = sync_do(Pid9, users), - ?line sync_do(Pid9, terminate), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), - - % Blocking user closes. - ?line Pid10 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}, {format, external}]), - ?line {ok, n} = sync_do(Pid10, {open, File, none}), - ?line ok = sync_do(Pid10, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line ok = sync_do(Pid10, close), - ?line ok = status(n), - ?line [_] = owners(n), - ?line 0 = users(n), - ?line ok = disk_log:close(n), - ?line sync_do(Pid10, terminate), - ?line {error, no_such_log} = disk_log:info(n), - ?line true = (P0 == pps()), - - % Blocking user unblocks and closes. - ?line Pid11 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}, {format, external}]), - ?line {ok, n} = sync_do(Pid11, {open, File, none}), - ?line ok = sync_do(Pid11, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line ok = sync_do(Pid11, unblock), - ?line ok = sync_do(Pid11, close), - ?line ok = status(n), - ?line [_] = owners(n), - ?line 0 = users(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line sync_do(Pid11, terminate), - ?line true = (P0 == pps()), - - % Blocking owner closes. - ?line Pid12 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {linkto, none}, - {size, {100,No}}, {format, external}]), - ?line {ok, n} = sync_do(Pid12, {open, File}), - ?line ok = sync_do(Pid12, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line ok = sync_do(Pid12, close), - ?line ok = status(n), - ?line [] = owners(n), - ?line 1 = users(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line sync_do(Pid12, terminate), - ?line true = (P0 == pps()), - - % Blocking owner unblocks and closes. - ?line Pid13 = spawn_link(?MODULE, lserv, [n]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {linkto, none}, - {size, {100,No}}, {format, external}]), - ?line {ok, n} = sync_do(Pid13, {open, File}), - ?line ok = sync_do(Pid13, block), - ?line {blocked, true} = status(n), - ?line [_] = owners(n), - ?line 1 = users(n), - ?line ok = sync_do(Pid13, unblock), - ?line ok = sync_do(Pid13, close), - ?line ok = status(n), - ?line [] = owners(n), - ?line 1 = users(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line sync_do(Pid13, terminate), - ?line true = (P0 == pps()), + Pid8 = spawn_link(?MODULE, lserv, [n]), + Pid9 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = sync_do(Pid8, {open, File}), + {ok, n} = sync_do(Pid9, {open, File}), + ok = sync_do(Pid8, block), + {blocked, true} = status(n), + sync_do(Pid8, terminate), + ok = status(n), + [_] = sync_do(Pid9, owners), + 0 = sync_do(Pid9, users), + sync_do(Pid9, terminate), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), + + %% Blocking user closes. + Pid10 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}, {format, external}]), + {ok, n} = sync_do(Pid10, {open, File, none}), + ok = sync_do(Pid10, block), + {blocked, true} = status(n), + [_] = owners(n), + 1 = users(n), + ok = sync_do(Pid10, close), + ok = status(n), + [_] = owners(n), + 0 = users(n), + ok = disk_log:close(n), + sync_do(Pid10, terminate), + {error, no_such_log} = disk_log:info(n), + true = (P0 == pps()), + + %% Blocking user unblocks and closes. + Pid11 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}, {format, external}]), + {ok, n} = sync_do(Pid11, {open, File, none}), + ok = sync_do(Pid11, block), + {blocked, true} = status(n), + [_] = owners(n), + 1 = users(n), + ok = sync_do(Pid11, unblock), + ok = sync_do(Pid11, close), + ok = status(n), + [_] = owners(n), + 0 = users(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + sync_do(Pid11, terminate), + true = (P0 == pps()), + + %% Blocking owner closes. + Pid12 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {linkto, none}, + {size, {100,No}}, {format, external}]), + {ok, n} = sync_do(Pid12, {open, File}), + ok = sync_do(Pid12, block), + {blocked, true} = status(n), + [_] = owners(n), + 1 = users(n), + ok = sync_do(Pid12, close), + ok = status(n), + [] = owners(n), + 1 = users(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + sync_do(Pid12, terminate), + true = (P0 == pps()), + + %% Blocking owner unblocks and closes. + Pid13 = spawn_link(?MODULE, lserv, [n]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {linkto, none}, + {size, {100,No}}, {format, external}]), + {ok, n} = sync_do(Pid13, {open, File}), + ok = sync_do(Pid13, block), + {blocked, true} = status(n), + [_] = owners(n), + 1 = users(n), + ok = sync_do(Pid13, unblock), + ok = sync_do(Pid13, close), + ok = status(n), + [] = owners(n), + 1 = users(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + sync_do(Pid13, terminate), + true = (P0 == pps()), del(File, No), % cleanup ok. -close_deadlock(suite) -> []; -close_deadlock(doc) -> - ["OTP-4745. Deadlock with just an ordinary log could happen."]; +%% OTP-4745. Deadlock with just an ordinary log could happen. close_deadlock(Conf) when is_list(Conf) -> - ?line true = is_alive(), + true = is_alive(), - ?line PrivDir = ?privdir(Conf), + PrivDir = ?privdir(Conf), - ?line F1 = filename:join(PrivDir, "a.LOG"), - ?line file:delete(F1), + F1 = filename:join(PrivDir, "a.LOG"), + file:delete(F1), Self = self(), %% One process opens the log at the same time as another process @@ -2378,11 +2305,11 @@ close_deadlock(Conf) when is_list(Conf) -> Name = a, Fun = fun() -> open_close(Self, Name, F1) end, P = spawn(Fun), - ?line receive {P, Name} -> ok end, - ?line {ok, L} = disk_log:open([{name,Name},{file,F1}]), - ?line ok = disk_log:close(L), - ?line receive {P, done} -> ok end, - ?line file:delete(F1), + receive {P, Name} -> ok end, + {ok, L} = disk_log:open([{name,Name},{file,F1}]), + ok = disk_log:close(L), + receive {P, done} -> ok end, + file:delete(F1), %% One process opens the log at the same time as another process %% closes the log due to file error while truncating. @@ -2390,38 +2317,38 @@ close_deadlock(Conf) when is_list(Conf) -> %% "work". When it works, as it seems to do right now :), the %% disk_log_server gets {error, no_such_log}, receives the EXIT %% message caused by truncate, and tries to open the log again. - ?line No = 4, - ?line LDir = F1 ++ ".2", - ?line file:del_dir(LDir), - ?line del(F1, No), - ?line ok = file:make_dir(LDir), + No = 4, + LDir = F1 ++ ".2", + file:del_dir(LDir), + del(F1, No), + ok = file:make_dir(LDir), Fun2 = fun() -> open_truncate(Self, Name, F1, No) end, P2 = spawn(Fun2), - ?line receive {P2, Name} -> ok end, - ?line {ok, L} = disk_log:open([{name, Name}, {file, F1}, {type, wrap}, - {format, external}]), + receive {P2, Name} -> ok end, + {ok, L} = disk_log:open([{name, Name}, {file, F1}, {type, wrap}, + {format, external}]), %% Note: truncate causes the disk log process to terminate. One %% cannot say if open above happened before, after, or during the %% termination. The link to the owner is removed before termination. - ?line case disk_log:close(L) of - ok -> ok; - {error,no_such_log} -> - ok - end, - ?line receive {P2, done} -> ok end, - ?line del(F1, No), - ?line file:del_dir(LDir), + case disk_log:close(L) of + ok -> ok; + {error,no_such_log} -> + ok + end, + receive {P2, done} -> ok end, + del(F1, No), + file:del_dir(LDir), %% To the same thing, this time using distributed logs. %% (Does not seem to work very well, unfortunately.) FunD = fun() -> open_close_dist(Self, Name, F1) end, PD = spawn(FunD), receive {PD, Name} -> ok end, - ?line {[_], []} = disk_log:open([{name,Name},{file,F1}, - {distributed,[node()]}]), - ?line ok = disk_log:close(L), + {[_], []} = disk_log:open([{name,Name},{file,F1}, + {distributed,[node()]}]), + ok = disk_log:close(L), receive {PD, done} -> ok end, - ?line file:delete(F1), + file:delete(F1), ok. @@ -2467,7 +2394,7 @@ sync_do(Pid, Req) -> end. lserv(Log) -> - ?line receive + receive {From, {open, File}} -> From ! disk_log:open([{name, Log}, {file, File}, {type, wrap}, {size, {100,1}}, {format, external}]); @@ -2534,664 +2461,662 @@ lserv(Log) -> lserv(Log). -error_repair(suite) -> []; -error_repair(doc) -> - ["Error while repairing."]; +%% Error while repairing. error_repair(Conf) when is_list(Conf) -> - % not all error situations are covered by this test + %% not all error situations are covered by this test DataDir = ?datadir(Conf), PrivDir = ?privdir(Conf), - ?line File = filename:join(PrivDir, "n.LOG"), - ?line No = 4, - ?line file:delete(File), - ?line del(File, No), % cleanup + File = filename:join(PrivDir, "n.LOG"), + No = 4, + file:delete(File), + del(File, No), % cleanup - % kurt.LOG is not closed and has four logged items, one is recovered - ?line copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir), - ?line {repaired,n,{recovered,1},{badbytes,0}} = + %% kurt.LOG is not closed and has four logged items, one is recovered + copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir), + {repaired,n,{recovered,1},{badbytes,0}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,No}}]), - ?line 1 = cur_cnt(n), - ?line 53 = curb(n), - ?line 4 = no_items(n), - ?line ok = disk_log:close(n), - - % temporary repair file cannot be created - ?line copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir), - ?line Dir = File ++ ".4" ++ ".TMP", - ?line ok = file:make_dir(Dir), - ?line P0 = pps(), - ?line {error, {file_error, _, _}} = + 1 = cur_cnt(n), + 53 = curb(n), + 4 = no_items(n), + ok = disk_log:close(n), + + %% temporary repair file cannot be created + copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir), + Dir = File ++ ".4" ++ ".TMP", + ok = file:make_dir(Dir), + P0 = pps(), + {error, {file_error, _, _}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,4}}]), - ?line true = (P0 == pps()), - ?line del(File, No), - ?line ok = file:del_dir(Dir), + true = (P0 == pps()), + del(File, No), + ok = file:del_dir(Dir), + error_logger:add_report_handler(?MODULE, self()), %% repair a file - ?line P1 = pps(), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {40,No}}]), - ?line ok = disk_log:log_terms(n, [{this,is}]), % first file full - ?line ok = disk_log:log_terms(n, [{some,terms}]), % second file full - ?line ok = disk_log:close(n), - ?line BadFile = add_ext(File, 2), % current file - ?line set_opened(BadFile), - ?line crash(BadFile, 28), % the binary is now invalid - ?line {repaired,n,{recovered,0},{badbytes,26}} = - disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {40,No}}]), - ?line ok = disk_log:close(n), - ?line true = (P1 == pps()), - ?line del(File, No), + P1 = pps(), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {40,No}}]), + ok = disk_log:log_terms(n, [{this,is}]), % first file full + ok = disk_log:log_terms(n, [{some,terms}]), % second file full + ok = disk_log:close(n), + BadFile = add_ext(File, 2), % current file + set_opened(BadFile), + crash(BadFile, 28), % the binary is now invalid + {repaired,n,{recovered,0},{badbytes,26}} = + disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {40,No}}]), + ok = disk_log:close(n), + true = (P1 == pps()), + del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% yet another repair - ?line P2 = pps(), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {4000,No}}]), - ?line ok = disk_log:log_terms(n, [{this,is},{some,terms}]), - ?line ok = disk_log:close(n), - ?line BadFile2 = add_ext(File, 1), % current file - ?line set_opened(BadFile2), - ?line crash(BadFile2, 51), % the second binary is now invalid - ?line {repaired,n,{recovered,1},{badbytes,26}} = + P2 = pps(), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {4000,No}}]), + ok = disk_log:log_terms(n, [{this,is},{some,terms}]), + ok = disk_log:close(n), + BadFile2 = add_ext(File, 1), % current file + set_opened(BadFile2), + crash(BadFile2, 51), % the second binary is now invalid + {repaired,n,{recovered,1},{badbytes,26}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {4000,No}}]), - ?line ok = disk_log:close(n), - ?line true = (P2 == pps()), - ?line del(File, No), + ok = disk_log:close(n), + true = (P2 == pps()), + del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% Repair, large term - ?line Big = term_to_binary(lists:duplicate(66000,$a)), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {40,No}}]), - ?line ok = disk_log:log_terms(n, [Big]), - ?line ok = disk_log:close(n), - ?line set_opened(add_ext(File, 1)), - ?line {repaired,n,{recovered,1},{badbytes,0}} = + Big = term_to_binary(lists:duplicate(66000,$a)), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {40,No}}]), + ok = disk_log:log_terms(n, [Big]), + ok = disk_log:close(n), + set_opened(add_ext(File, 1)), + {repaired,n,{recovered,1},{badbytes,0}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {40,No}}]), - ?line {_, [Got]} = disk_log:chunk(n, start), - ?line ok = disk_log:close(n), - ?line Got = Big, - ?line del(File, No), + {_, [Got]} = disk_log:chunk(n, start), + ok = disk_log:close(n), + Got = Big, + del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% A term a little smaller than a chunk, then big terms. - ?line BigSmall = mk_bytes(1024*64-8-12), - ?line file:delete(File), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line ok = disk_log:log_terms(n, [BigSmall, Big, Big]), - ?line ok = disk_log:close(n), - ?line set_opened(File), - ?line FileSize = file_size(File), - ?line crash(File, FileSize-byte_size(Big)-4), - ?line Error1 = {error, {need_repair, _}} = + BigSmall = mk_bytes(1024*64-8-12), + file:delete(File), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + ok = disk_log:log_terms(n, [BigSmall, Big, Big]), + ok = disk_log:close(n), + set_opened(File), + FileSize = file_size(File), + crash(File, FileSize-byte_size(Big)-4), + Error1 = {error, {need_repair, _}} = disk_log:open([{name, n}, {file, File}, {repair, false}, {type, halt}, {format, internal}]), - ?line "The disk log" ++ _ = format_error(Error1), - ?line {repaired,n,{recovered,2},{badbytes,132013}} = + "The disk log" ++ _ = format_error(Error1), + {repaired,n,{recovered,2},{badbytes,132013}} = disk_log:open([{name, n}, {file, File}, {repair, true}, {type, halt}, {format, internal}]), - ?line ok = disk_log:close(n), - ?line file:delete(File), + ok = disk_log:close(n), + file:delete(File), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% The header is recovered. - ?line {ok,n} = + {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), - ?line ok = disk_log:log_terms(n, [list,'of',terms]), - ?line ["head",list,'of',terms] = get_all_terms(n), - ?line ok = disk_log:close(n), - ?line set_opened(File), - ?line crash(File, 30), - ?line {repaired,n,{recovered,3},{badbytes,16}} = + ok = disk_log:log_terms(n, [list,'of',terms]), + ["head",list,'of',terms] = get_all_terms(n), + ok = disk_log:close(n), + set_opened(File), + crash(File, 30), + {repaired,n,{recovered,3},{badbytes,16}} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal},{repair,true}, + {format, internal},{repair,true}, {quiet, true}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), - ?line ["head",'of',terms] = get_all_terms(n), - ?line ok = disk_log:close(n), - + ["head",'of',terms] = get_all_terms(n), + ok = disk_log:close(n), + error_logger:delete_report_handler(?MODULE), file:delete(File), + {messages, []} = process_info(self(), messages), ok. - + set_opened(File) -> {ok, Fd} = file:open(File, [raw, binary, read, write]), ok = file:write(Fd, [?LOGMAGIC, ?OPENED]), ok = file:close(Fd). -error_log(suite) -> []; -error_log(doc) -> - ["Error while repairing."]; +%% Error while repairing. error_log(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), - - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line file:delete(File), - ?line del(File, No), % cleanup - ?line LDir = File ++ ".2", - - ?line Q = qlen(), - % dummy just to get all processes "above" disk_log going - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external},{size, {100, No}}]), - ?line ok = disk_log:close(n), - ?line del(File, No), - - % inc_wrap_file fails, the external log is not terminated - ?line P0 = pps(), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external},{size, {100, No}}]), - ?line ok = file:make_dir(LDir), - ?line {error, {file_error, _, _}} = disk_log:inc_wrap_file(n), - ?line timer:sleep(500), - ?line ok = disk_log:close(n), - ?line del(File, No), - - % inc_wrap_file fails, the internal log is not terminated, ./File.2/ exists - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal},{size, {100, No}}]), - ?line {error, {file_error, _, _}} = disk_log:inc_wrap_file(n), - ?line ok = disk_log:close(n), - ?line del(File, No), - - % truncate fails, the log is terminated, ./File.2/ exists - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external},{size, {100, No}}]), - ?line {error, {file_error, _, _}} = disk_log:truncate(n), - ?line true = (P0 == pps()), - ?line del(File, No), + Dir = ?privdir(Conf), + + File = filename:join(Dir, "n.LOG"), + No = 4, + file:delete(File), + del(File, No), % cleanup + LDir = File ++ ".2", + + Q = qlen(), + %% dummy just to get all processes "above" disk_log going + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external},{size, {100, No}}]), + ok = disk_log:close(n), + del(File, No), + + %% inc_wrap_file fails, the external log is not terminated + P0 = pps(), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external},{size, {100, No}}]), + ok = file:make_dir(LDir), + {error, {file_error, _, _}} = disk_log:inc_wrap_file(n), + timer:sleep(500), + ok = disk_log:close(n), + del(File, No), + + %% inc_wrap_file fails, the internal log is not terminated, ./File.2/ exists + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal},{size, {100, No}}]), + {error, {file_error, _, _}} = disk_log:inc_wrap_file(n), + ok = disk_log:close(n), + del(File, No), + + %% truncate fails, the log is terminated, ./File.2/ exists + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external},{size, {100, No}}]), + {error, {file_error, _, _}} = disk_log:truncate(n), + true = (P0 == pps()), + del(File, No), %% OTP-4880. - % reopen (rename) fails, the log is terminated, ./File.2/ exists - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, external},{size, 100000}]), - ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir), - ?line true = (P0 == pps()), - ?line file:delete(File), + %% reopen (rename) fails, the log is terminated, ./File.2/ exists + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, external},{size, 100000}]), + {error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir), + true = (P0 == pps()), + file:delete(File), - ?line B = mk_bytes(60), + B = mk_bytes(60), %% OTP-4880. reopen a wrap log, rename fails - ?line File2 = filename:join(Dir, "n.LOG2"), - ?line {ok, n} = disk_log:open([{name, n}, {file, File2}, {type, wrap}, - {format, external},{size, {100, No}}]), - ?line ok = disk_log:blog_terms(n, [B,B,B]), - ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, File), - ?line {error, no_such_log} = disk_log:close(n), - ?line del(File2, No), - ?line del(File, No), - - % log, external wrap log, ./File.2/ exists - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external},{size, {100, No}}]), - ?line {error, {file_error, _, _}} = disk_log:blog_terms(n, [B,B,B]), - ?line ok = disk_log:close(n), - ?line del(File, No), - - % log, internal wrap log, ./File.2/ exists - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal},{size, {100, No}}]), - ?line {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]), - ?line ok = disk_log:close(n), - ?line del(File, No), - - ?line ok = file:del_dir(LDir), - - % can't remove file when changing size - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal},{size, {100, No}}]), - ?line ok = disk_log:log_terms(n, [B,B,B,B]), - ?line ok = disk_log:change_size(n, {100, No-2}), - ?line Three = File ++ ".3", - ?line ok = file:delete(Three), - ?line ok = file:make_dir(Three), - ?line {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]), - ?line timer:sleep(500), - ?line ok = disk_log:close(n), - ?line ok = file:del_dir(Three), - ?line del(File, No), - ?line Q = qlen(), + File2 = filename:join(Dir, "n.LOG2"), + {ok, n} = disk_log:open([{name, n}, {file, File2}, {type, wrap}, + {format, external},{size, {100, No}}]), + ok = disk_log:blog_terms(n, [B,B,B]), + {error, {file_error, _, eisdir}} = disk_log:reopen(n, File), + {error, no_such_log} = disk_log:close(n), + del(File2, No), + del(File, No), + + %% log, external wrap log, ./File.2/ exists + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external},{size, {100, No}}]), + {error, {file_error, _, _}} = disk_log:blog_terms(n, [B,B,B]), + ok = disk_log:close(n), + del(File, No), + + %% log, internal wrap log, ./File.2/ exists + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal},{size, {100, No}}]), + {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]), + ok = disk_log:close(n), + del(File, No), + + ok = file:del_dir(LDir), + + %% can't remove file when changing size + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal},{size, {100, No}}]), + ok = disk_log:log_terms(n, [B,B,B,B]), + ok = disk_log:change_size(n, {100, No-2}), + Three = File ++ ".3", + ok = file:delete(Three), + ok = file:make_dir(Three), + {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]), + timer:sleep(500), + ok = disk_log:close(n), + ok = file:del_dir(Three), + del(File, No), + Q = qlen(), ok. - -chunk(suite) -> []; -chunk(doc) -> - ["Test chunk and chunk_step."]; + +%% Test chunk and chunk_step. chunk(Conf) when is_list(Conf) -> %% See also halt_ro_crash/1 above. Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), + File = filename:join(Dir, "n.LOG"), No = 4, - ?line B = mk_bytes(60), - ?line BB = mk_bytes(64000), % 64 kB chunks - ?line del(File, No),% cleanup + B = mk_bytes(60), + BB = mk_bytes(64000), % 64 kB chunks + del(File, No),% cleanup %% Make sure chunk_step skips the rest of the binary. %% OTP-3716. This was a bug... - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {50,No}}]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {50,No}}]), %% 1, 2 and 3 on file one, 4 on file two. - ?line ok = disk_log:log_terms(n, [1,2,3,4]), - ?line {I1, [1]} = disk_log:chunk(n, start, 1), - ?line [{node,Node}] = disk_log:chunk_info(I1), - ?line Node = node(), - ?line Error1 = {error, {no_continuation, foobar}} = + ok = disk_log:log_terms(n, [1,2,3,4]), + {I1, [1]} = disk_log:chunk(n, start, 1), + [{node,Node}] = disk_log:chunk_info(I1), + Node = node(), + Error1 = {error, {no_continuation, foobar}} = disk_log:chunk_info(foobar), - ?line "The term" ++ _ = format_error(Error1), - ?line {ok, I2} = disk_log:chunk_step(n, I1, 1), - ?line {error, {badarg, continuation}} = disk_log:chunk_step(n, foobar, 1), - ?line {I3, [4]} = disk_log:chunk(n, I2, 1), - ?line {ok, I4} = disk_log:chunk_step(n, I3, -1), - ?line {_, [1]} = disk_log:chunk(n, I4, 1), - ?line {error, {badarg, continuation}} = disk_log:bchunk(n, 'begin'), - ?line {Ib1, [Bin1,Bin2]} = disk_log:bchunk(n, start, 2), - ?line 1 = binary_to_term(Bin1), - ?line 2 = binary_to_term(Bin2), - ?line {ok, Ib2} = disk_log:chunk_step(n, Ib1, 1), - ?line {Ib3, [Bin3]} = disk_log:bchunk(n, Ib2, 1), - ?line 4 = binary_to_term(Bin3), - ?line {ok, Ib4} = disk_log:chunk_step(n, Ib3, -1), - ?line {_, [Bin4]} = disk_log:bchunk(n, Ib4, 1), - ?line 1 = binary_to_term(Bin4), - ?line {Ib5, [Bin1, Bin2, Bin17]} = disk_log:bchunk(n, start), - ?line 3 = binary_to_term(Bin17), - ?line {Ib6, [Bin3]} = disk_log:bchunk(n, Ib5, infinity), - ?line eof = disk_log:bchunk(n, Ib6, infinity), - ?line ok = disk_log:close(n), - ?line del(File, No), % cleanup + "The term" ++ _ = format_error(Error1), + {ok, I2} = disk_log:chunk_step(n, I1, 1), + {error, {badarg, continuation}} = disk_log:chunk_step(n, foobar, 1), + {I3, [4]} = disk_log:chunk(n, I2, 1), + {ok, I4} = disk_log:chunk_step(n, I3, -1), + {_, [1]} = disk_log:chunk(n, I4, 1), + {error, {badarg, continuation}} = disk_log:bchunk(n, 'begin'), + {Ib1, [Bin1,Bin2]} = disk_log:bchunk(n, start, 2), + 1 = binary_to_term(Bin1), + 2 = binary_to_term(Bin2), + {ok, Ib2} = disk_log:chunk_step(n, Ib1, 1), + {Ib3, [Bin3]} = disk_log:bchunk(n, Ib2, 1), + 4 = binary_to_term(Bin3), + {ok, Ib4} = disk_log:chunk_step(n, Ib3, -1), + {_, [Bin4]} = disk_log:bchunk(n, Ib4, 1), + 1 = binary_to_term(Bin4), + {Ib5, [Bin1, Bin2, Bin17]} = disk_log:bchunk(n, start), + 3 = binary_to_term(Bin17), + {Ib6, [Bin3]} = disk_log:bchunk(n, Ib5, infinity), + eof = disk_log:bchunk(n, Ib6, infinity), + ok = disk_log:close(n), + del(File, No), % cleanup %% external log, cannot read chunks - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external}, {size, {100,No}}]), - ?line {error, {badarg, continuation}} = disk_log:chunk(n, 'begin'), - ?line {error, {format_external, n}} = disk_log:chunk(n, start), - ?line Error2 = {error, {not_internal_wrap, n}} = + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external}, {size, {100,No}}]), + {error, {badarg, continuation}} = disk_log:chunk(n, 'begin'), + {error, {format_external, n}} = disk_log:chunk(n, start), + Error2 = {error, {not_internal_wrap, n}} = disk_log:chunk_step(n, start, 1), - ?line "The requested" ++ _ = format_error(Error2), - ?line ok = disk_log:close(n), - ?line del(File, No), + "The requested" ++ _ = format_error(Error2), + ok = disk_log:close(n), + del(File, No), %% wrap, read_write - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {100,No}}]), - ?line ok = disk_log:log_terms(n, [B,B,B,B]), - ?line {C1, [_]} = disk_log:chunk(n, start), - ?line {C2, [_]} = disk_log:chunk(n, C1), - ?line {C3, [_]} = disk_log:chunk(n, C2), - ?line {C4, [_]} = disk_log:chunk(n, C3, 1), - ?line eof = disk_log:chunk(n, C4), - ?line {C5, [_]} = disk_log:chunk(n, start), - ?line {ok, C6} = disk_log:chunk_step(n, C5, 1), - ?line {C7, [_]} = disk_log:chunk(n, C6), - ?line {ok, C8} = disk_log:chunk_step(n, C7, 1), - ?line {_, [_]} = disk_log:chunk(n, C8), - ?line ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {100,No}}]), + ok = disk_log:log_terms(n, [B,B,B,B]), + {C1, [_]} = disk_log:chunk(n, start), + {C2, [_]} = disk_log:chunk(n, C1), + {C3, [_]} = disk_log:chunk(n, C2), + {C4, [_]} = disk_log:chunk(n, C3, 1), + eof = disk_log:chunk(n, C4), + {C5, [_]} = disk_log:chunk(n, start), + {ok, C6} = disk_log:chunk_step(n, C5, 1), + {C7, [_]} = disk_log:chunk(n, C6), + {ok, C8} = disk_log:chunk_step(n, C7, 1), + {_, [_]} = disk_log:chunk(n, C8), + ok = disk_log:close(n), %% wrap, read_only - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {mode, read_only}, - {format, internal}, {size, {100,No}}]), - ?line {CC1, [_]} = disk_log:chunk(n, start), - ?line {CC2, [_]} = disk_log:chunk(n, CC1), - ?line {CC3, [_]} = disk_log:chunk(n, CC2), - ?line {CC4, [_]} = disk_log:chunk(n, CC3, 1), - ?line eof = disk_log:chunk(n, CC4), - ?line {CC5, [_]} = disk_log:chunk(n, start), - ?line {ok, CC6} = disk_log:chunk_step(n, CC5, 1), - ?line {CC7, [_]} = disk_log:chunk(n, CC6), - ?line {ok, CC8} = disk_log:chunk_step(n, CC7, 1), - ?line {_, [_]} = disk_log:chunk(n, CC8), - ?line ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {mode, read_only}, + {format, internal}, {size, {100,No}}]), + {CC1, [_]} = disk_log:chunk(n, start), + {CC2, [_]} = disk_log:chunk(n, CC1), + {CC3, [_]} = disk_log:chunk(n, CC2), + {CC4, [_]} = disk_log:chunk(n, CC3, 1), + eof = disk_log:chunk(n, CC4), + {CC5, [_]} = disk_log:chunk(n, start), + {ok, CC6} = disk_log:chunk_step(n, CC5, 1), + {CC7, [_]} = disk_log:chunk(n, CC6), + {ok, CC8} = disk_log:chunk_step(n, CC7, 1), + {_, [_]} = disk_log:chunk(n, CC8), + ok = disk_log:close(n), %% OTP-3716. A bug: {Error, List} and {Error, List, Bad} could be %% returned from chunk/2. %% Magic bytes not OK. %% File header (8 bytes) OK, item header not OK. - ?line InvalidFile = add_ext(File, 1), - ?line crash(InvalidFile, 15), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {mode, read_only}, - {format, internal}, {size, {100,No}}]), - ?line {_, [], 61} = disk_log:chunk(n, start), - ?line ok = disk_log:close(n), + InvalidFile = add_ext(File, 1), + crash(InvalidFile, 15), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {mode, read_only}, + {format, internal}, {size, {100,No}}]), + {_, [], 61} = disk_log:chunk(n, start), + ok = disk_log:close(n), %% read_write... - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {100,No}}]), - ?line Error3 = {error, {corrupt_log_file, Culprit}} = + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {100,No}}]), + Error3 = {error, {corrupt_log_file, Culprit}} = disk_log:chunk(n, start), - ?line "The disk log file" ++ _ = format_error(Error3), - ?line Culprit = InvalidFile, - ?line ok = disk_log:close(n), - ?line del(File, No), + "The disk log file" ++ _ = format_error(Error3), + Culprit = InvalidFile, + ok = disk_log:close(n), + del(File, No), %% Two wrap log files, writing the second one, then reading the first %% one, where a bogus term resides. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {40,No}}]), - ?line ok = disk_log:log_terms(n, [{this,is}]), % first file full - ?line ok = disk_log:log_terms(n, [{some,terms}]), % second file full - ?line 2 = curf(n), - ?line BadFile = add_ext(File, 1), - ?line crash(BadFile, 28), % the _binary_ is now invalid - ?line {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1), - ?line BadFile = BFile, - ?line ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {40,No}}]), + ok = disk_log:log_terms(n, [{this,is}]), % first file full + ok = disk_log:log_terms(n, [{some,terms}]), % second file full + 2 = curf(n), + BadFile = add_ext(File, 1), + crash(BadFile, 28), % the _binary_ is now invalid + {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1), + BadFile = BFile, + ok = disk_log:close(n), %% The same, with a halt log. - ?line file:delete(File), % cleanup - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line ok = disk_log:log_terms(n, [{this,is}]), - ?line ok = disk_log:sync(n), - ?line crash(File, 28), % the _binary_ is now invalid - ?line {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1), - ?line crash(File, 10), - ?line {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1), - ?line true = File == File2, - ?line ok = disk_log:close(n), - ?line del(File, No), + file:delete(File), % cleanup + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + ok = disk_log:log_terms(n, [{this,is}]), + ok = disk_log:sync(n), + crash(File, 28), % the _binary_ is now invalid + {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1), + crash(File, 10), + {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1), + true = File == File2, + ok = disk_log:close(n), + del(File, No), %% halt, read_write - ?line file:delete(File), % cleanup - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line ok = disk_log:log_terms(n, [BB,BB,BB,BB]), - ?line {D1, [Ch1]} = disk_log:chunk(n, start, 1), - ?line Ch1 = BB, - ?line {D2, [Ch2]} = disk_log:chunk(n, D1, 1), - ?line Ch2 = BB, - ?line {D3, [Ch3]} = disk_log:chunk(n, D2, 1), - ?line Ch3 = BB, - ?line {D4, [Ch4]} = disk_log:chunk(n, D3, 1), - ?line Ch4 = BB, - ?line eof = disk_log:chunk(n, D4), - ?line ok = disk_log:close(n), + file:delete(File), % cleanup + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + ok = disk_log:log_terms(n, [BB,BB,BB,BB]), + {D1, [Ch1]} = disk_log:chunk(n, start, 1), + Ch1 = BB, + {D2, [Ch2]} = disk_log:chunk(n, D1, 1), + Ch2 = BB, + {D3, [Ch3]} = disk_log:chunk(n, D2, 1), + Ch3 = BB, + {D4, [Ch4]} = disk_log:chunk(n, D3, 1), + Ch4 = BB, + eof = disk_log:chunk(n, D4), + ok = disk_log:close(n), %% halt, read_only - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal},{mode,read_only}]), - ?line {E1, [Ch5]} = disk_log:chunk(n, start, 1), - ?line Ch5 = BB, - ?line {E2, [Ch6]} = disk_log:chunk(n, E1, 1), - ?line Ch6 = BB, - ?line {E3, [Ch7]} = disk_log:chunk(n, E2, 1), - ?line Ch7 = BB, - ?line {E4, [Ch8]} = disk_log:chunk(n, E3, 1), - ?line Ch8 = BB, - ?line eof = disk_log:chunk(n, E4), - ?line ok = disk_log:close(n), - ?line file:delete(File), % cleanup + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal},{mode,read_only}]), + {E1, [Ch5]} = disk_log:chunk(n, start, 1), + Ch5 = BB, + {E2, [Ch6]} = disk_log:chunk(n, E1, 1), + Ch6 = BB, + {E3, [Ch7]} = disk_log:chunk(n, E2, 1), + Ch7 = BB, + {E4, [Ch8]} = disk_log:chunk(n, E3, 1), + Ch8 = BB, + eof = disk_log:chunk(n, E4), + ok = disk_log:close(n), + file:delete(File), % cleanup %% More than 64 kB term. - ?line BBB = term_to_binary(lists:duplicate(66000,$a)), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line ok = disk_log:log_terms(n, [BBB]), - ?line {F1, [BBB1]} = disk_log:chunk(n, start), - ?line BBB1 = BBB, - ?line eof = disk_log:chunk(n, F1), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_only}]), - ?line {F1r, [BBB2]} = disk_log:chunk(n, start), - ?line BBB2 = BBB, - ?line eof = disk_log:chunk(n, F1r), - ?line ok = disk_log:close(n), - - ?line truncate(File, 8192), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line {error, {corrupt_log_file, _}} = disk_log:chunk(n, start), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_only}]), - ?line {K1, [], 8176} = disk_log:chunk(n, start), - ?line eof = disk_log:chunk(n, K1), - ?line ok = disk_log:close(n), - ?line file:delete(File), % cleanup + BBB = term_to_binary(lists:duplicate(66000,$a)), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + ok = disk_log:log_terms(n, [BBB]), + {F1, [BBB1]} = disk_log:chunk(n, start), + BBB1 = BBB, + eof = disk_log:chunk(n, F1), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_only}]), + {F1r, [BBB2]} = disk_log:chunk(n, start), + BBB2 = BBB, + eof = disk_log:chunk(n, F1r), + ok = disk_log:close(n), + + truncate(File, 8192), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + {error, {corrupt_log_file, _}} = disk_log:chunk(n, start), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_only}]), + {K1, [], 8176} = disk_log:chunk(n, start), + eof = disk_log:chunk(n, K1), + ok = disk_log:close(n), + file:delete(File), % cleanup %% OTP-3716. A bug: eof in the middle of the last element is not ok. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line ok = disk_log:log_terms(n, [B,BB]), - ?line ok = disk_log:close(n), - ?line truncate(File, 80), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line {G1, [_]} = disk_log:chunk(n, start, 1), - ?line {error, {corrupt_log_file, _}} = disk_log:chunk(n, G1, 1), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_only}]), - ?line {G1r, [_]} = disk_log:chunk(n, start, 1), - ?line {_, [], 4} = disk_log:chunk(n, G1r, 1), - ?line ok = disk_log:close(n), - ?line file:delete(File), % cleanup + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + ok = disk_log:log_terms(n, [B,BB]), + ok = disk_log:close(n), + truncate(File, 80), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + {G1, [_]} = disk_log:chunk(n, start, 1), + {error, {corrupt_log_file, _}} = disk_log:chunk(n, G1, 1), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_only}]), + {G1r, [_]} = disk_log:chunk(n, start, 1), + {_, [], 4} = disk_log:chunk(n, G1r, 1), + ok = disk_log:close(n), + file:delete(File), % cleanup %% Opening a wrap log read-only. The second of four terms is destroyed. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {size, {4000,No}}]), - ?line ok = disk_log:log_terms(n, - [{this,is},{some,terms},{on,a},{wrap,file}]), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, internal}, {mode, read_only}]), - ?line CrashFile = add_ext(File, 1), - ?line crash(CrashFile, 51), % the binary term {some,terms} is now bad - ?line {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10), - ?line {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1), - ?line eof = disk_log:chunk(n, H2), - ?line ok = disk_log:close(n), - ?line del(File, No), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {size, {4000,No}}]), + ok = disk_log:log_terms(n, + [{this,is},{some,terms},{on,a},{wrap,file}]), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal}, {mode, read_only}]), + CrashFile = add_ext(File, 1), + crash(CrashFile, 51), % the binary term {some,terms} is now bad + {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1), + eof = disk_log:chunk(n, H2), + ok = disk_log:close(n), + del(File, No), %% The same as last, but with a halt log. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_write}]), - ?line ok = disk_log:alog_terms(n, [{this,is},{some,terms}]), - ?line ok = disk_log:log_terms(n, [{on,a},{halt,file}]), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_only}]), - ?line crash(File, 51), % the binary term {some,terms} is now bad - ?line {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10), - ?line {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1), - ?line eof = disk_log:chunk(n, J2), - ?line ok = disk_log:close(n), - ?line file:delete(File), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_write}]), + ok = disk_log:alog_terms(n, [{this,is},{some,terms}]), + ok = disk_log:log_terms(n, [{on,a},{halt,file}]), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_only}]), + crash(File, 51), % the binary term {some,terms} is now bad + {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1), + eof = disk_log:chunk(n, J2), + ok = disk_log:close(n), + file:delete(File), %% OTP-7641. Same as last one, but the size of the bad term is %% less than ?HEADERSz (8) bytes. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_write}]), - ?line ok = disk_log:alog_terms(n, [{this,is},{s}]), - ?line ok = disk_log:log_terms(n, [{on,a},{halt,file}]), - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}, {mode, read_only}]), - ?line crash(File, 44), % the binary term {s} is now bad - ?line {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10), - ?line {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11), - ?line eof = disk_log:chunk(n, J21), - ?line ok = disk_log:close(n), - ?line file:delete(File), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_write}]), + ok = disk_log:alog_terms(n, [{this,is},{s}]), + ok = disk_log:log_terms(n, [{on,a},{halt,file}]), + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}, {mode, read_only}]), + crash(File, 44), % the binary term {s} is now bad + {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10), + {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11), + eof = disk_log:chunk(n, J21), + ok = disk_log:close(n), + file:delete(File), %% Minimal MD5-proctected term, and maximal unprotected term. %% A chunk ends in the middle of the MD5-sum. - ?line MD5term = mk_bytes(64*1024-8), - ?line NotMD5term = mk_bytes((64*1024-8)-1), - ?line Term2 = mk_bytes((64*1024-8)-16), - ?line MD5L = [MD5term,NotMD5term,Term2,MD5term,MD5term,NotMD5term], - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line ok = disk_log:log_terms(n, MD5L), - ?line true = MD5L == get_all_terms(n), - ?line ok = disk_log:close(n), - ?line true = MD5L == get_all_terms(n, File, halt), - ?line crash(File, 21), % the MD5-sum of the first term is now bad - ?line true = {tl(MD5L),64*1024-8} == get_all_terms_and_bad(n, File, halt), - ?line {_,64*1024-8} = get_all_binary_terms_and_bad(n, File, halt), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal}]), - ?line {error, {corrupt_log_file, _}} = disk_log:chunk(n, start), - ?line ok = disk_log:close(n), - ?line file:delete(File), + MD5term = mk_bytes(64*1024-8), + NotMD5term = mk_bytes((64*1024-8)-1), + Term2 = mk_bytes((64*1024-8)-16), + MD5L = [MD5term,NotMD5term,Term2,MD5term,MD5term,NotMD5term], + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + ok = disk_log:log_terms(n, MD5L), + true = MD5L == get_all_terms(n), + ok = disk_log:close(n), + true = MD5L == get_all_terms(n, File, halt), + crash(File, 21), % the MD5-sum of the first term is now bad + true = {tl(MD5L),64*1024-8} == get_all_terms_and_bad(n, File, halt), + {_,64*1024-8} = get_all_binary_terms_and_bad(n, File, halt), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {format, internal}]), + {error, {corrupt_log_file, _}} = disk_log:chunk(n, start), + ok = disk_log:close(n), + file:delete(File), %% A file with "old" terms (magic word is MAGICINT). DataDir = ?datadir(Conf), OldTermsFileOrig = filename:join(DataDir, "old_terms.LOG"), OldTermsFile = filename:join(Dir, "old_terms.LOG"), - ?line copy_file(OldTermsFileOrig, OldTermsFile), - ?line {[_,_,_,_],0} = get_all_terms_and_bad(n, OldTermsFile, halt), - ?line {ok, n} = disk_log:open([{name, n}, {file, OldTermsFile}, - {type, halt}, {format, internal}]), - ?line [_,_,_,_] = get_all_terms(n), - ?line ok = disk_log:close(n), - ?line file:delete(OldTermsFile), + copy_file(OldTermsFileOrig, OldTermsFile), + {[_,_,_,_],0} = get_all_terms_and_bad(n, OldTermsFile, halt), + {ok, n} = disk_log:open([{name, n}, {file, OldTermsFile}, + {type, halt}, {format, internal}]), + [_,_,_,_] = get_all_terms(n), + ok = disk_log:close(n), + file:delete(OldTermsFile), ok. -error_index(suite) -> []; -error_index(doc) -> - ["OTP-5558. Keep the contents of index files after disk crash."]; +%% OTP-5558. Keep the contents of index files after disk crash. error_index(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), + Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line IdxFile = File ++ ".idx", - ?line No = 4, - ?line file:delete(File), - ?line del(File, No), % cleanup + File = filename:join(Dir, "n.LOG"), + IdxFile = File ++ ".idx", + No = 4, + file:delete(File), + del(File, No), % cleanup Args = [{name,n},{type,wrap},{size,{100,No}},{file,File}], - ?line {ok, n} = disk_log:open(Args), - ?line ok = disk_log:close(n), - ?line Q = qlen(), + {ok, n} = disk_log:open(Args), + ok = disk_log:close(n), + Q = qlen(), P0 = pps(), - ?line ok = file:write_file(IdxFile, <<"abc">>), - ?line {error, {invalid_index_file, _}} = disk_log:open(Args), - ?line {error, {invalid_index_file, _}} = disk_log:open(Args), - ?line {error, {invalid_index_file, _}} = disk_log:open(Args), - - ?line del(File, No), - ?line true = (P0 == pps()), - ?line true = (Q == qlen()), + ok = file:write_file(IdxFile, <<"abc">>), + {error, {invalid_index_file, _}} = disk_log:open(Args), + {error, {invalid_index_file, _}} = disk_log:open(Args), + {error, {invalid_index_file, _}} = disk_log:open(Args), + + del(File, No), + true = (P0 == pps()), + true = (Q == qlen()), ok. - -truncate(suite) -> []; -truncate(doc) -> - ["Test truncate/1 on halt and wrap logs."]; + +%% Test truncate/1 on halt and wrap logs. truncate(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line Q = qlen(), + Q = qlen(), Halt = join(Dir, "halt.LOG"), - % Halt logs. - - ?line file:delete(Halt), % cleanup - ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt}, - {head, header}, {notify, true}]), - ?line infinity = sz(halt), - ?line ok = disk_log:truncate(halt, tjohej), - ?line rec(1, {disk_log, node(), halt, {truncated, 1}}), - ?line ok = disk_log:change_size(halt, 10000), - ?line 10000 = sz(halt), - ?line disk_log:close(halt), - ?line [tjohej] = get_all_terms(halt, Halt, halt), - ?line file:delete(Halt), - - ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt}, - {head, header}, {notify, true}]), - ?line ok = disk_log:truncate(halt), - ?line rec(1, {disk_log, node(), halt, {truncated, 1}}), - ?line disk_log:close(halt), - ?line [header] = get_all_terms(halt, Halt, halt), - ?line file:delete(Halt), - - ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, - {file, Halt}, {format, external}, - {head, "header"}, {notify, false}]), - ?line ok = disk_log:btruncate(halt, "apa"), - ?line disk_log:close(halt), - ?line 3 = file_size(Halt), - ?line file:delete(Halt), - + %% Halt logs. + + file:delete(Halt), % cleanup + {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt}, + {head, header}, {notify, true}]), + infinity = sz(halt), + ok = disk_log:truncate(halt, tjohej), + rec(1, {disk_log, node(), halt, {truncated, 1}}), + ok = disk_log:change_size(halt, 10000), + 10000 = sz(halt), + disk_log:close(halt), + [tjohej] = get_all_terms(halt, Halt, halt), + file:delete(Halt), + + {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt}, + {head, header}, {notify, true}]), + ok = disk_log:truncate(halt), + rec(1, {disk_log, node(), halt, {truncated, 1}}), + disk_log:close(halt), + [header] = get_all_terms(halt, Halt, halt), + file:delete(Halt), + + {ok, halt} = disk_log:open([{name, halt}, {type, halt}, + {file, Halt}, {format, external}, + {head, "header"}, {notify, false}]), + ok = disk_log:btruncate(halt, "apa"), + disk_log:close(halt), + 3 = file_size(Halt), + file:delete(Halt), + %% Wrap logs. - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line B = mk_bytes(60), - ?line del(File, No), % cleanup + File = filename:join(Dir, "n.LOG"), + No = 4, + B = mk_bytes(60), + del(File, No), % cleanup %% Internal with header. - ?line Size = {100, No}, - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {head, header}, {notify, true}, - {size, Size}]), - ?line ok = disk_log:log_terms(n, [B,B,B]), + Size = {100, No}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {head, header}, {notify, true}, + {size, Size}]), + ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:truncate(n, apa), - ?line rec(1, {disk_log, node(), n, {truncated, 6}}), - ?line {0, 0} = no_overflows(n), - ?line 23 = curb(n), - ?line 1 = curf(n), - ?line 1 = cur_cnt(n), - ?line true = (Size == sz(n)), - - ?line ok = disk_log:log_terms(n, [B, B]), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:close(n), - ?line [apa, _, header, _] = get_all_terms(n, File, wrap), - ?line del(File, No), - + rec(2, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:truncate(n, apa), + rec(1, {disk_log, node(), n, {truncated, 6}}), + {0, 0} = no_overflows(n), + 23 = curb(n), + 1 = curf(n), + 1 = cur_cnt(n), + true = (Size == sz(n)), + + ok = disk_log:log_terms(n, [B, B]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:close(n), + [apa, _, header, _] = get_all_terms(n, File, wrap), + del(File, No), + %% Internal without general header. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, - {size, {100, No}}]), - ?line ok = disk_log:log_terms(n, [B,B,B]), - ?line rec(2, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:truncate(n, apa), - ?line rec(1, {disk_log, node(), n, {truncated, 3}}), - ?line {0, 0} = no_overflows(n), - ?line 23 = curb(n), - ?line 1 = curf(n), - ?line 1 = cur_cnt(n), - ?line true = (Size == sz(n)), - - ?line ok = disk_log:log_terms(n, [B, B]), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:close(n), - ?line [apa, _, _] = get_all_terms(n, File, wrap), - ?line del(File, No), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, + {size, {100, No}}]), + ok = disk_log:log_terms(n, [B,B,B]), + rec(2, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:truncate(n, apa), + rec(1, {disk_log, node(), n, {truncated, 3}}), + {0, 0} = no_overflows(n), + 23 = curb(n), + 1 = curf(n), + 1 = cur_cnt(n), + true = (Size == sz(n)), + + ok = disk_log:log_terms(n, [B, B]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:close(n), + [apa, _, _] = get_all_terms(n, File, wrap), + del(File, No), %% Internal without any header. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, - {size, {100, No}}]), - ?line ok = disk_log:log_terms(n, [B,B,B]), - ?line rec(2, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:truncate(n), - ?line rec(1, {disk_log, node(), n, {truncated, 3}}), - ?line {0, 0} = no_overflows(n), - ?line 8 = curb(n), - ?line 1 = curf(n), - ?line 0 = cur_cnt(n), - ?line true = (Size == sz(n)), - - ?line ok = disk_log:log_terms(n, [B, B]), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:close(n), - ?line [_, _] = get_all_terms(n, File, wrap), - ?line del(File, No), - ?line Q = qlen(), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, + {size, {100, No}}]), + ok = disk_log:log_terms(n, [B,B,B]), + rec(2, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:truncate(n), + rec(1, {disk_log, node(), n, {truncated, 3}}), + {0, 0} = no_overflows(n), + 8 = curb(n), + 1 = curf(n), + 0 = cur_cnt(n), + true = (Size == sz(n)), + + ok = disk_log:log_terms(n, [B, B]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:close(n), + [_, _] = get_all_terms(n, File, wrap), + del(File, No), + Q = qlen(), ok. -many_users(suite) -> []; -many_users(doc) -> - ["Test many users logging and sync:ing at the same time."]; +%% Test many users logging and sync:ing at the same time. many_users(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), N = 100, @@ -3199,32 +3124,32 @@ many_users(Conf) when is_list(Conf) -> Fun1 = fun(Name, Pid, I) -> disk_log:log(Name, {Pid, I}) end, Fun2 = fun(Name, Pid, I) -> ok = disk_log:log(Name, {Pid, I}), disk_log:sync(Name) end, - ?line {C1, T1} = many(Fun2, NoClients, N, halt, internal, infinity, Dir), - ?line true = lists:duplicate(NoClients, ok) == C1, - ?line true = length(T1) == N*NoClients, - ?line {C2, T2} = many(Fun1, NoClients, N, halt, internal, 1000, Dir), - ?line true = lists:duplicate(NoClients, {error, {full,"log.LOG"}}) == C2, - ?line true = length(T2) > 0, - ?line {C3, T3} = many(Fun2, NoClients, N, wrap, internal, - {300*NoClients,200}, Dir), - ?line true = lists:duplicate(NoClients, ok) == C3, - ?line true = length(T3) == N*NoClients, + {C1, T1} = many(Fun2, NoClients, N, halt, internal, infinity, Dir), + true = lists:duplicate(NoClients, ok) == C1, + true = length(T1) == N*NoClients, + {C2, T2} = many(Fun1, NoClients, N, halt, internal, 1000, Dir), + true = lists:duplicate(NoClients, {error, {full,"log.LOG"}}) == C2, + true = length(T2) > 0, + {C3, T3} = many(Fun2, NoClients, N, wrap, internal, + {300*NoClients,200}, Dir), + true = lists:duplicate(NoClients, ok) == C3, + true = length(T3) == N*NoClients, ok. many(Fun, NoClients, N, Type, Format, Size, Dir) -> Name = "log.LOG", File = filename:join(Dir, Name), del_files(Size, File), - ?line Q = qlen(), - ?line {ok, _} = disk_log:open([{name,Name}, {type,Type}, {size,Size}, - {format,Format}, {file,File}]), - ?line Pids = spawn_clients(NoClients, client, [self(), Name, N, Fun]), - ?line Checked = check_clients(Pids), - ?line ok = disk_log:close(Name), - ?line Terms = get_all_terms(Name, File, Type), - ?line del_files(Size, File), - ?line Q = qlen(), - ?line {Checked, Terms}. + Q = qlen(), + {ok, _} = disk_log:open([{name,Name}, {type,Type}, {size,Size}, + {format,Format}, {file,File}]), + Pids = spawn_clients(NoClients, client, [self(), Name, N, Fun]), + Checked = check_clients(Pids), + ok = disk_log:close(Name), + Terms = get_all_terms(Name, File, Type), + del_files(Size, File), + Q = qlen(), + {Checked, Terms}. spawn_clients(0, _F, _A) -> []; @@ -3251,211 +3176,208 @@ del_files(_Size, File) -> -info_current(suite) -> []; -info_current(doc) -> - ["Test no_current_{bytes, items} as returned by info/0."]; +%% Test no_current_{bytes, items} as returned by info/0. info_current(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), + File = filename:join(Dir, "n.LOG"), No = 4, B = mk_bytes(60), BB = mk_bytes(160), % bigger than a single wrap log file SB = mk_bytes(10), % much smaller than a single wrap log file - ?line del(File, No),% cleanup + del(File, No),% cleanup - ?line Q = qlen(), + Q = qlen(), %% Internal with header. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {head, header}, {size, {100,No}}]), - ?line {26, 1} = {curb(n), cur_cnt(n)}, - ?line {1, 1} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log(n, B), - ?line {94, 2} = {curb(n), cur_cnt(n)}, - ?line {2, 2} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, - {head, header}, {size, {100,No}}]), - ?line {94, 2} = {curb(n), cur_cnt(n)}, - ?line {0, 2} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {94, 2} = {curb(n), cur_cnt(n)}, - ?line {2, 4} = {no_written_items(n), no_items(n)}, - ?line disk_log:inc_wrap_file(n), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {26, 1} = {curb(n), cur_cnt(n)}, - ?line {3, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [B,B,B]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {head, header}, {size, {100,No}}]), + {26, 1} = {curb(n), cur_cnt(n)}, + {1, 1} = {no_written_items(n), no_items(n)}, + ok = disk_log:log(n, B), + {94, 2} = {curb(n), cur_cnt(n)}, + {2, 2} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, + {head, header}, {size, {100,No}}]), + {94, 2} = {curb(n), cur_cnt(n)}, + {0, 2} = {no_written_items(n), no_items(n)}, + ok = disk_log:log(n, B), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {94, 2} = {curb(n), cur_cnt(n)}, + {2, 4} = {no_written_items(n), no_items(n)}, + disk_log:inc_wrap_file(n), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {26, 1} = {curb(n), cur_cnt(n)}, + {3, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line {94, 2} = {curb(n), cur_cnt(n)}, - ?line {8, 7} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line {94, 2} = {curb(n), cur_cnt(n)}, - ?line {12, 7} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [BB,BB]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + rec(1, {disk_log, node(), n, {wrap, 2}}), + {94, 2} = {curb(n), cur_cnt(n)}, + {8, 7} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + {94, 2} = {curb(n), cur_cnt(n)}, + {12, 7} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 2}}), - ?line {194, 2} = {curb(n), cur_cnt(n)}, - ?line {16, 7} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [SB,SB,SB]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line {80, 4} = {curb(n), cur_cnt(n)}, - ?line {20, 9} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line del(File, No), + rec(2, {disk_log, node(), n, {wrap, 2}}), + {194, 2} = {curb(n), cur_cnt(n)}, + {16, 7} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [SB,SB,SB]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + {80, 4} = {curb(n), cur_cnt(n)}, + {20, 9} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + del(File, No), %% Internal without header. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {size, {100,No}}]), - ?line {8, 0} = {curb(n), cur_cnt(n)}, - ?line {0, 0} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log(n, B), - ?line {76, 1} = {curb(n), cur_cnt(n)}, - ?line {1, 1} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, {size, {100,No}}]), - ?line {76, 1} = {curb(n), cur_cnt(n)}, - ?line {0, 1} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {76, 1} = {curb(n), cur_cnt(n)}, - ?line {1, 2} = {no_written_items(n), no_items(n)}, - ?line disk_log:inc_wrap_file(n), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {8, 0} = {curb(n), cur_cnt(n)}, - ?line {1, 2} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [B,B,B]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {size, {100,No}}]), + {8, 0} = {curb(n), cur_cnt(n)}, + {0, 0} = {no_written_items(n), no_items(n)}, + ok = disk_log:log(n, B), + {76, 1} = {curb(n), cur_cnt(n)}, + {1, 1} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, {size, {100,No}}]), + {76, 1} = {curb(n), cur_cnt(n)}, + {0, 1} = {no_written_items(n), no_items(n)}, + ok = disk_log:log(n, B), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {76, 1} = {curb(n), cur_cnt(n)}, + {1, 2} = {no_written_items(n), no_items(n)}, + disk_log:inc_wrap_file(n), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {8, 0} = {curb(n), cur_cnt(n)}, + {1, 2} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line {76, 1} = {curb(n), cur_cnt(n)}, - ?line {4, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line ok = disk_log:log_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line {76, 1} = {curb(n), cur_cnt(n)}, - ?line {6, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [BB,BB]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + rec(1, {disk_log, node(), n, {wrap, 1}}), + {76, 1} = {curb(n), cur_cnt(n)}, + {4, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 1}}), + ok = disk_log:log_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 1}}), + {76, 1} = {curb(n), cur_cnt(n)}, + {6, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 1}}), - ?line {176, 1} = {curb(n), cur_cnt(n)}, - ?line {8, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:log_terms(n, [SB,SB,SB]), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line {62, 3} = {curb(n), cur_cnt(n)}, - ?line {11, 6} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line del(File, No), + rec(2, {disk_log, node(), n, {wrap, 1}}), + {176, 1} = {curb(n), cur_cnt(n)}, + {8, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:log_terms(n, [SB,SB,SB]), + rec(1, {disk_log, node(), n, {wrap, 1}}), + {62, 3} = {curb(n), cur_cnt(n)}, + {11, 6} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + del(File, No), %% External with header. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external}, {head, "header"}, - {size, {100,No}}]), - ?line {6, 1} = {curb(n), cur_cnt(n)}, - ?line {1, 1} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog(n, B), - ?line {62, 2} = {curb(n), cur_cnt(n)}, - ?line {2, 2} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external}, {head, "header"}, - {notify, true}, {size, {100,No}}]), - ?line {62, 2} = {curb(n), cur_cnt(n)}, - ?line {0, 2} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {62, 2} = {curb(n), cur_cnt(n)}, - ?line {2, 4} = {no_written_items(n), no_items(n)}, - ?line disk_log:inc_wrap_file(n), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {6, 1} = {curb(n), cur_cnt(n)}, - ?line {3, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [B,B,B]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external}, {head, "header"}, + {size, {100,No}}]), + {6, 1} = {curb(n), cur_cnt(n)}, + {1, 1} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog(n, B), + {62, 2} = {curb(n), cur_cnt(n)}, + {2, 2} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external}, {head, "header"}, + {notify, true}, {size, {100,No}}]), + {62, 2} = {curb(n), cur_cnt(n)}, + {0, 2} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog(n, B), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {62, 2} = {curb(n), cur_cnt(n)}, + {2, 4} = {no_written_items(n), no_items(n)}, + disk_log:inc_wrap_file(n), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {6, 1} = {curb(n), cur_cnt(n)}, + {3, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line {62, 2} = {curb(n), cur_cnt(n)}, - ?line {8, 7} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line ok = disk_log:blog_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line {62, 2} = {curb(n), cur_cnt(n)}, - ?line {12, 7} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [BB,BB]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + rec(1, {disk_log, node(), n, {wrap, 2}}), + {62, 2} = {curb(n), cur_cnt(n)}, + {8, 7} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + ok = disk_log:blog_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 2}}), + {62, 2} = {curb(n), cur_cnt(n)}, + {12, 7} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 2}}), - ?line {162, 2} = {curb(n), cur_cnt(n)}, - ?line {16, 7} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [SB,SB,SB]), - - ?line rec(1, {disk_log, node(), n, {wrap, 2}}), - ?line {24, 4} = {curb(n), cur_cnt(n)}, - ?line {20, 9} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line del(File, No), + rec(2, {disk_log, node(), n, {wrap, 2}}), + {162, 2} = {curb(n), cur_cnt(n)}, + {16, 7} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [SB,SB,SB]), + + rec(1, {disk_log, node(), n, {wrap, 2}}), + {24, 4} = {curb(n), cur_cnt(n)}, + {20, 9} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + del(File, No), %% External without header. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {format, external}, {size, {100,No}}]), - ?line {0, 0} = {curb(n), cur_cnt(n)}, - ?line {0, 0} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog(n, B), - ?line {56, 1} = {curb(n), cur_cnt(n)}, - ?line {1, 1} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, - {notify, true}, - {format, external}, {size, {100,No}}]), - ?line {56, 1} = {curb(n), cur_cnt(n)}, - ?line {0, 1} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {56, 1} = {curb(n), cur_cnt(n)}, - ?line {1, 2} = {no_written_items(n), no_items(n)}, - ?line disk_log:inc_wrap_file(n), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line {0, 0} = {curb(n), cur_cnt(n)}, - ?line {1, 2} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [B,B,B]), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, external}, {size, {100,No}}]), + {0, 0} = {curb(n), cur_cnt(n)}, + {0, 0} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog(n, B), + {56, 1} = {curb(n), cur_cnt(n)}, + {1, 1} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {notify, true}, + {format, external}, {size, {100,No}}]), + {56, 1} = {curb(n), cur_cnt(n)}, + {0, 1} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog(n, B), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {56, 1} = {curb(n), cur_cnt(n)}, + {1, 2} = {no_written_items(n), no_items(n)}, + disk_log:inc_wrap_file(n), + rec(1, {disk_log, node(), n, {wrap, 0}}), + {0, 0} = {curb(n), cur_cnt(n)}, + {1, 2} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line {56, 1} = {curb(n), cur_cnt(n)}, - ?line {4, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line ok = disk_log:blog_terms(n, [B]), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line {56, 1} = {curb(n), cur_cnt(n)}, - ?line {6, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [BB,BB]), + rec(1, {disk_log, node(), n, {wrap, 0}}), + rec(1, {disk_log, node(), n, {wrap, 1}}), + {56, 1} = {curb(n), cur_cnt(n)}, + {4, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 1}}), + ok = disk_log:blog_terms(n, [B]), + rec(1, {disk_log, node(), n, {wrap, 1}}), + {56, 1} = {curb(n), cur_cnt(n)}, + {6, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 1}}), - ?line {156, 1} = {curb(n), cur_cnt(n)}, - ?line {8, 4} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:blog_terms(n, [SB,SB,SB]), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line {18, 3} = {curb(n), cur_cnt(n)}, - ?line {11, 6} = {no_written_items(n), no_items(n)}, - ?line ok = disk_log:close(n), - ?line del(File, No), - - ?line Q = qlen(), + rec(2, {disk_log, node(), n, {wrap, 1}}), + {156, 1} = {curb(n), cur_cnt(n)}, + {8, 4} = {no_written_items(n), no_items(n)}, + ok = disk_log:blog_terms(n, [SB,SB,SB]), + rec(1, {disk_log, node(), n, {wrap, 1}}), + {18, 3} = {curb(n), cur_cnt(n)}, + {11, 6} = {no_written_items(n), no_items(n)}, + ok = disk_log:close(n), + del(File, No), + + Q = qlen(), ok. -change_size_before(suite) -> []; change_size_before(doc) -> ["Change size of a wrap log file before we have reached " "to the file index corresponding to the new size"]; @@ -3478,138 +3400,136 @@ change_size_before(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), del(File, 5), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, - {type, wrap}, {size, {100,5}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:change_size(a, {100, 3}), - ?line [Log_1_1, Log_1_2, - Log_2_1, Log_2_2] = get_all_terms(a), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_1_2_1), - ?line disk_log:log(a, Log_1_2_2), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_1_2_1, Log_1_2_2] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,3}}]), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_1_2_1, Log_1_2_2] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, + {type, wrap}, {size, {100,5}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:change_size(a, {100, 3}), + [Log_1_1, Log_1_2, + Log_2_1, Log_2_2] = get_all_terms(a), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_1_2_1), + disk_log:log(a, Log_1_2_2), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_1_2_1, Log_1_2_2] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,3}}]), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_1_2_1, Log_1_2_2] = get_all_terms(a), disk_log:close(a), del(File, 5), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {60,5}}, {format, external}]), - ?line disk_log:blog(a, Log_1_1), - ?line disk_log:blog(a, Log_1_2), - ?line disk_log:blog(a, Log_2_1), - ?line disk_log:blog(a, Log_2_2), - ?line disk_log:change_size(a, {60, 3}), - ?line ok = disk_log:sync(a), - ?line {ok, Fd1} = file:open(File ++ ".1", [read]), - ?line Log11_12 = Log_1_1 ++ Log_1_2, - ?line {ok,Log11_12} = file:read(Fd1, 200), - ?line ok = file:close(Fd1), - ?line {ok, Fd2} = file:open(File ++ ".2", [read]), -% ?t:format(0, "~p~n",[file:read(Fd2, 200)]), - ?line Log21_22 = Log_2_1 ++ Log_2_2, - ?line {ok,Log21_22} = file:read(Fd2, 200), - ?line ok = file:close(Fd2), - ?line disk_log:blog(a, Log_3_1), - ?line disk_log:blog(a, Log_3_2), - ?line disk_log:blog(a, Log_1_2_1), - ?line disk_log:blog(a, Log_1_2_2), - ?line ok = disk_log:sync(a), - ?line {ok, Fd2a} = file:open(File ++ ".2", [read]), - ?line {ok,Log21_22} = file:read(Fd2a, 200), - ?line ok = file:close(Fd2a), - ?line {ok, Fd3a} = file:open(File ++ ".3", [read]), - ?line Log31_32 = Log_3_1 ++ Log_3_2, - ?line {ok,Log31_32} = file:read(Fd3a, 200), - ?line ok = file:close(Fd3a), - ?line {ok, Fd1a} = file:open(File ++ ".1", [read]), - ?line Log121_122 = Log_1_2_1 ++ Log_1_2_2, - ?line {ok,Log121_122} = file:read(Fd1a, 200), - ?line ok = file:close(Fd1a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {60,3}}, {format, external}]), - ?line {ok, Fd2b} = file:open(File ++ ".2", [read]), - ?line {ok,Log21_22} = file:read(Fd2b, 200), - ?line ok = file:close(Fd2b), - ?line {ok, Fd3b} = file:open(File ++ ".3", [read]), - ?line {ok,Log31_32} = file:read(Fd3b, 200), - ?line ok = file:close(Fd3b), - ?line {ok, Fd1b} = file:open(File ++ ".1", [read]), - ?line {ok,Log121_122} = file:read(Fd1b, 200), - ?line ok = file:close(Fd1b), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {60,5}}, {format, external}]), + disk_log:blog(a, Log_1_1), + disk_log:blog(a, Log_1_2), + disk_log:blog(a, Log_2_1), + disk_log:blog(a, Log_2_2), + disk_log:change_size(a, {60, 3}), + ok = disk_log:sync(a), + {ok, Fd1} = file:open(File ++ ".1", [read]), + Log11_12 = Log_1_1 ++ Log_1_2, + {ok,Log11_12} = file:read(Fd1, 200), + ok = file:close(Fd1), + {ok, Fd2} = file:open(File ++ ".2", [read]), + Log21_22 = Log_2_1 ++ Log_2_2, + {ok,Log21_22} = file:read(Fd2, 200), + ok = file:close(Fd2), + disk_log:blog(a, Log_3_1), + disk_log:blog(a, Log_3_2), + disk_log:blog(a, Log_1_2_1), + disk_log:blog(a, Log_1_2_2), + ok = disk_log:sync(a), + {ok, Fd2a} = file:open(File ++ ".2", [read]), + {ok,Log21_22} = file:read(Fd2a, 200), + ok = file:close(Fd2a), + {ok, Fd3a} = file:open(File ++ ".3", [read]), + Log31_32 = Log_3_1 ++ Log_3_2, + {ok,Log31_32} = file:read(Fd3a, 200), + ok = file:close(Fd3a), + {ok, Fd1a} = file:open(File ++ ".1", [read]), + Log121_122 = Log_1_2_1 ++ Log_1_2_2, + {ok,Log121_122} = file:read(Fd1a, 200), + ok = file:close(Fd1a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {60,3}}, {format, external}]), + {ok, Fd2b} = file:open(File ++ ".2", [read]), + {ok,Log21_22} = file:read(Fd2b, 200), + ok = file:close(Fd2b), + {ok, Fd3b} = file:open(File ++ ".3", [read]), + {ok,Log31_32} = file:read(Fd3b, 200), + ok = file:close(Fd3b), + {ok, Fd1b} = file:open(File ++ ".1", [read]), + {ok,Log121_122} = file:read(Fd1b, 200), + ok = file:close(Fd1b), disk_log:close(a), del(File, 5), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:change_size(a, {60, 3}), - ?line [Log_1_1, Log_1_2, - Log_2_1, Log_2_2] = get_all_terms(a), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_1_2_1), - ?line [Log_2_1, Log_2_2, - Log_3_1, - Log_1_2_1] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60,3}}]), - ?line [Log_2_1, Log_2_2, - Log_3_1, - Log_1_2_1] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:change_size(a, {60, 3}), + [Log_1_1, Log_1_2, + Log_2_1, Log_2_2] = get_all_terms(a), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_1_2_1), + [Log_2_1, Log_2_2, + Log_3_1, + Log_1_2_1] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60,3}}]), + [Log_2_1, Log_2_2, + Log_3_1, + Log_1_2_1] = get_all_terms(a), disk_log:close(a), del(File, 5), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60, 3}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:change_size(a, {100, 5}), - ?line [Log_1_1, - Log_2_1] = get_all_terms(a), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:log(a, Log_5_1), - ?line disk_log:log(a, Log_5_2), - ?line disk_log:log(a, Log_1_2_1), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_4_1, Log_4_2, - Log_5_1, Log_5_2, - Log_1_2_1] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100, 5}}]), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_4_1, Log_4_2, - Log_5_1, Log_5_2, - Log_1_2_1] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60, 3}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_2_1), + disk_log:change_size(a, {100, 5}), + [Log_1_1, + Log_2_1] = get_all_terms(a), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:log(a, Log_5_1), + disk_log:log(a, Log_5_2), + disk_log:log(a, Log_1_2_1), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_4_1, Log_4_2, + Log_5_1, Log_5_2, + Log_1_2_1] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100, 5}}]), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_4_1, Log_4_2, + Log_5_1, Log_5_2, + Log_1_2_1] = get_all_terms(a), disk_log:close(a), del(File, 5). -change_size_during(suite) -> []; -change_size_during(doc) -> ["Change size of a wrap log file while logging " - "to a file index between the old and the new size"]; +%% Change size of a wrap log file while logging to a file index +%% between the old and the new size. change_size_during(Conf) when is_list(Conf) -> Log_1_1 = "first log first message", @@ -3633,114 +3553,111 @@ change_size_during(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:log(a, Log_5_1), - ?line disk_log:log(a, Log_5_2), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:change_size(a, {100, 3}), - ?line [Log_5_1, Log_5_2, - Log_1_1, Log_1_2, - Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_4_1, Log_4_2] = get_all_terms(a), - ?line disk_log:log(a, Log_1_2_1), - ?line disk_log:log(a, Log_1_2_2), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_4_1, Log_4_2, - Log_1_2_1, Log_1_2_2] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_4_1, Log_4_2, - Log_1_2_1, Log_1_2_2] = get_all_terms(a), - ?line disk_log:log(a, Log_2_2_1), - ?line disk_log:log(a, Log_2_2_2), - ?line disk_log:log(a, Log_3_2_1), - ?line disk_log:log(a, Log_3_2_2), - ?line disk_log:log(a, Log_1_3_1), - ?line disk_log:log(a, Log_1_3_2), - ?line [Log_2_2_1, Log_2_2_2, - Log_3_2_1, Log_3_2_2, - Log_1_3_1, Log_1_3_2] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:log(a, Log_5_1), + disk_log:log(a, Log_5_2), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:change_size(a, {100, 3}), + [Log_5_1, Log_5_2, + Log_1_1, Log_1_2, + Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_4_1, Log_4_2] = get_all_terms(a), + disk_log:log(a, Log_1_2_1), + disk_log:log(a, Log_1_2_2), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_4_1, Log_4_2, + Log_1_2_1, Log_1_2_2] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_4_1, Log_4_2, + Log_1_2_1, Log_1_2_2] = get_all_terms(a), + disk_log:log(a, Log_2_2_1), + disk_log:log(a, Log_2_2_2), + disk_log:log(a, Log_3_2_1), + disk_log:log(a, Log_3_2_2), + disk_log:log(a, Log_1_3_1), + disk_log:log(a, Log_1_3_2), + [Log_2_2_1, Log_2_2_2, + Log_3_2_1, Log_3_2_2, + Log_1_3_1, Log_1_3_2] = get_all_terms(a), disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]), - ?line [Log_2_2_1, Log_2_2_2, - Log_3_2_1, Log_3_2_2, - Log_1_3_1, Log_1_3_2] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]), + [Log_2_2_1, Log_2_2_2, + Log_3_2_1, Log_3_2_2, + Log_1_3_1, Log_1_3_2] = get_all_terms(a), disk_log:close(a), del(File, 5), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:log(a, Log_5_1), - ?line disk_log:log(a, Log_5_2), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:log(a, Log_5_1), - ?line disk_log:log(a, Log_5_2), - ?line disk_log:change_size(a, {100, 3}), - ?line [Log_1_1, Log_1_2, - Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_4_1, Log_4_2, - Log_5_1, Log_5_2] = get_all_terms(a), - ?line disk_log:log(a, Log_1_2_1), - ?line disk_log:log(a, Log_1_2_2), - ?line disk_log:log(a, Log_2_2_1), - ?line disk_log:log(a, Log_2_2_2), - ?line disk_log:log(a, Log_3_2_1), - ?line disk_log:log(a, Log_3_2_2), - ?line disk_log:log(a, Log_1_3_1), - ?line disk_log:log(a, Log_1_3_2), - ?line [Log_2_2_1, Log_2_2_2, - Log_3_2_1, Log_3_2_2, - Log_1_3_1, Log_1_3_2] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]), - ?line [Log_2_2_1, Log_2_2_2, - Log_3_2_1, Log_3_2_2, - Log_1_3_1, Log_1_3_2] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:log(a, Log_5_1), + disk_log:log(a, Log_5_2), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:log(a, Log_5_1), + disk_log:log(a, Log_5_2), + disk_log:change_size(a, {100, 3}), + [Log_1_1, Log_1_2, + Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_4_1, Log_4_2, + Log_5_1, Log_5_2] = get_all_terms(a), + disk_log:log(a, Log_1_2_1), + disk_log:log(a, Log_1_2_2), + disk_log:log(a, Log_2_2_1), + disk_log:log(a, Log_2_2_2), + disk_log:log(a, Log_3_2_1), + disk_log:log(a, Log_3_2_2), + disk_log:log(a, Log_1_3_1), + disk_log:log(a, Log_1_3_2), + [Log_2_2_1, Log_2_2_2, + Log_3_2_1, Log_3_2_2, + Log_1_3_1, Log_1_3_2] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]), + [Log_2_2_1, Log_2_2_2, + Log_3_2_1, Log_3_2_2, + Log_1_3_1, Log_1_3_2] = get_all_terms(a), disk_log:close(a), del(File, 5). -change_size_after(suite) -> []; -change_size_after(doc) -> - ["Change size of a wrap log file before we have reached " - "(on the second round) " - "to the file index corresponding to the new size"]; +%% Change size of a wrap log file before we have reached (on the +%% second round) to the file index corresponding to the new size. change_size_after(Conf) when is_list(Conf) -> Log_1_1 = "first log first message", @@ -3758,172 +3675,169 @@ change_size_after(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "a.LOG"), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,5}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:log(a, Log_5_1), - ?line disk_log:log(a, Log_5_2), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:change_size(a, {100, 3}), - ?line [Log_3_1,Log_3_2, - Log_4_1, Log_4_2, - Log_5_1, Log_5_2, - Log_1_1, Log_1_2, - Log_2_1, Log_2_2] = get_all_terms(a), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_1_2_1), - ?line disk_log:log(a, Log_1_2_2), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_1_2_1, Log_1_2_2] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,3}}]), - ?line [Log_2_1, Log_2_2, - Log_3_1, Log_3_2, - Log_1_2_1, Log_1_2_2] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,5}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:log(a, Log_5_1), + disk_log:log(a, Log_5_2), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:change_size(a, {100, 3}), + [Log_3_1,Log_3_2, + Log_4_1, Log_4_2, + Log_5_1, Log_5_2, + Log_1_1, Log_1_2, + Log_2_1, Log_2_2] = get_all_terms(a), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_1_2_1), + disk_log:log(a, Log_1_2_2), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_1_2_1, Log_1_2_2] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,3}}]), + [Log_2_1, Log_2_2, + Log_3_1, Log_3_2, + Log_1_2_1, Log_1_2_2] = get_all_terms(a), disk_log:close(a), del(File, 5), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {100,5}}]), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_3_2), - ?line disk_log:log(a, Log_4_1), - ?line disk_log:log(a, Log_4_2), - ?line disk_log:log(a, Log_5_1), - ?line disk_log:log(a, Log_5_2), - ?line disk_log:log(a, Log_1_1), - ?line disk_log:log(a, Log_1_2), - ?line disk_log:log(a, Log_2_1), - ?line disk_log:log(a, Log_2_2), - ?line disk_log:change_size(a, {60, 3}), - ?line [Log_3_1,Log_3_2, - Log_4_1, Log_4_2, - Log_5_1, Log_5_2, - Log_1_1, Log_1_2, - Log_2_1, Log_2_2] = get_all_terms(a), - ?line disk_log:log(a, Log_3_1), - ?line disk_log:log(a, Log_1_2_1), - ?line [Log_2_1, Log_2_2, - Log_3_1, - Log_1_2_1] = get_all_terms(a), - - ?line disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, - {size, {60,3}}]), - ?line [Log_2_1, Log_2_2, - Log_3_1, - Log_1_2_1] = get_all_terms(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {100,5}}]), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_3_2), + disk_log:log(a, Log_4_1), + disk_log:log(a, Log_4_2), + disk_log:log(a, Log_5_1), + disk_log:log(a, Log_5_2), + disk_log:log(a, Log_1_1), + disk_log:log(a, Log_1_2), + disk_log:log(a, Log_2_1), + disk_log:log(a, Log_2_2), + disk_log:change_size(a, {60, 3}), + [Log_3_1,Log_3_2, + Log_4_1, Log_4_2, + Log_5_1, Log_5_2, + Log_1_1, Log_1_2, + Log_2_1, Log_2_2] = get_all_terms(a), + disk_log:log(a, Log_3_1), + disk_log:log(a, Log_1_2_1), + [Log_2_1, Log_2_2, + Log_3_1, + Log_1_2_1] = get_all_terms(a), + + disk_log:close(a), + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {size, {60,3}}]), + [Log_2_1, Log_2_2, + Log_3_1, + Log_1_2_1] = get_all_terms(a), disk_log:close(a), del(File, 5). -default_size(suite) -> []; -default_size(doc) -> ["Open an existing wrap log without size option "]; +%% Open an existing wrap log without size option . default_size(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "a.LOG"), - ?line {error, {badarg, size}} = disk_log:open([{name,a}, {file, File}, + Dir = ?privdir(Conf), + File = filename:join(Dir, "a.LOG"), + {error, {badarg, size}} = disk_log:open([{name,a}, {file, File}, {type, wrap}]), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]), - ?line disk_log:close(a), + disk_log:close(a), - ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}]), - ?line {100, 5} = disk_log_1:read_size_file(File), - ?line ok = disk_log:close(a), - ?line del(File, 5). + {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}]), + {100, 5} = disk_log_1:read_size_file(File), + ok = disk_log:close(a), + del(File, 5). -change_size2(suite) -> []; -change_size2(doc) -> ["Testing change_size/2 a bit more..."]; +%% Testing change_size/2 a bit more... change_size2(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup %% External halt. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {size, 100000}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {size, 100000}, {format, external}, {type, halt}]), - ?line B = mk_bytes(60), % 56 actually... - ?line ok = disk_log:blog_terms(n, [B,list_to_binary(B),B]), - ?line Error1 = {error, {new_size_too_small,n,168}} = + B = mk_bytes(60), % 56 actually... + ok = disk_log:blog_terms(n, [B,list_to_binary(B),B]), + Error1 = {error, {new_size_too_small,n,168}} = disk_log:change_size(n, 167), - ?line "The current size" ++ _ = format_error(Error1), - ?line ok = disk_log:change_size(n, infinity), - ?line ok = disk_log:change_size(n, 168), - ?line ok = disk_log:close(n), - ?line file:delete(File), % cleanup + "The current size" ++ _ = format_error(Error1), + ok = disk_log:change_size(n, infinity), + ok = disk_log:change_size(n, 168), + ok = disk_log:close(n), + file:delete(File), % cleanup %% External wrap. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}, {notify, true}, {format, external}]), - ?line BB = mk_bytes(160), - ?line ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files + BB = mk_bytes(160), + ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files %% Used to be one message, but now one per wrapped file. - ?line rec(3, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:blog_terms(n, [BB, BB]), + rec(3, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:blog_terms(n, [BB, BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 1}}), - ?line ok = disk_log:change_size(n, {100, 2}), - ?line ok = disk_log:change_size(n, {100, 2}), - ?line {100, 2} = sz(n), - ?line ok = disk_log:balog_terms(n, [BB, BB]), - ?line ok = disk_log:balog_terms(n, [BB]), - ?line ok = disk_log:blog_terms(n, [BB]), + rec(2, {disk_log, node(), n, {wrap, 1}}), + ok = disk_log:change_size(n, {100, 2}), + ok = disk_log:change_size(n, {100, 2}), + {100, 2} = sz(n), + ok = disk_log:balog_terms(n, [BB, BB]), + ok = disk_log:balog_terms(n, [BB]), + ok = disk_log:blog_terms(n, [BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(4, {disk_log, node(), n, {wrap, 1}}), - ?line ok = disk_log:change_size(n, {100, 4}), - ?line ok = disk_log:close(n), - ?line del(File, No), + rec(4, {disk_log, node(), n, {wrap, 1}}), + ok = disk_log:change_size(n, {100, 4}), + ok = disk_log:close(n), + del(File, No), %% Internal wrap. - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}, {notify, true}, {format, internal}]), - ?line ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files + ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files %% Used to be one message, but now one per wrapped file. - ?line rec(3, {disk_log, node(), n, {wrap, 0}}), - ?line ok = disk_log:blog_terms(n, [BB, BB]), + rec(3, {disk_log, node(), n, {wrap, 0}}), + ok = disk_log:blog_terms(n, [BB, BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(2, {disk_log, node(), n, {wrap, 1}}), - ?line ok = disk_log:change_size(n, {100, 2}), - ?line {100, 2} = sz(n), - ?line ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), + rec(2, {disk_log, node(), n, {wrap, 1}}), + ok = disk_log:change_size(n, {100, 2}), + {100, 2} = sz(n), + ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), %% Used to be one message, but now one per wrapped file. - ?line rec(4, {disk_log, node(), n, {wrap, 1}}), - ?line ok = disk_log:close(n), - ?line del(File, No). + rec(4, {disk_log, node(), n, {wrap, 1}}), + ok = disk_log:close(n), + del(File, No). -change_size_truncate(suite) -> []; -change_size_truncate(doc) -> ["OTP-3484: truncating index file"]; +%% OTP-3484: truncating index file. change_size_truncate(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "bert.LOG"), - ?line No = 3, - ?line B = mk_bytes(60), + File = filename:join(Dir, "bert.LOG"), + No = 3, + B = mk_bytes(60), %% The problem here is truncation of the index file. One cannot easily %% check that the index file is correctly updated, but print_index_file() @@ -3933,541 +3847,527 @@ change_size_truncate(Conf) when is_list(Conf) -> %% Change the size immediately after creating the log, while there %% are no log files. This used to write stuff a negative offset %% from the beginning of the file. - ?line del(File, No+1), - ?line {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File}, + del(File, No+1), + {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File}, {notify, true}, {size,{1000,255}}]), - ?line ok = disk_log:change_size(bert,{100,No}), - ?line ok = disk_log:blog(bert, B), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 0}}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 0}}), - ?line 3 = curf(bert), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line 1 = curf(bert), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - - % Three items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), - ?line 3 = curf(bert), - ?line ok = disk_log:change_size(bert,{100,1}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - % Three items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - % One item expected. - % disk_log_1:print_index_file("bert.LOG.idx"), - - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line ok = disk_log:close(bert), - ?line del(File, No), + ok = disk_log:change_size(bert,{100,No}), + ok = disk_log:blog(bert, B), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 0}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 0}}), + 3 = curf(bert), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + 1 = curf(bert), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + + %% Three items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), + 3 = curf(bert), + ok = disk_log:change_size(bert,{100,1}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + %% Three items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + %% One item expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), + + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:close(bert), + del(File, No), %% Part 2. %% Change the size twice, the second time while the the effects of %% the first changed have not yet been handled. Finally close before %% the index file has been truncated. - ?line del(File, No), - ?line {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File}, + del(File, No), + {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File}, {notify, true}, {size,{100,No}}]), - ?line ok = disk_log:blog(bert, B), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 0}}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 0}}), + ok = disk_log:blog(bert, B), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 0}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 0}}), - ?line 3 = curf(bert), - ?line ok = disk_log:change_size(bert,{100,No-1}), + 3 = curf(bert), + ok = disk_log:change_size(bert,{100,No-1}), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line 1 = curf(bert), - ?line ok = disk_log:change_size(bert,{100,No+1}), + 1 = curf(bert), + ok = disk_log:change_size(bert,{100,No+1}), - % Three items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), + %% Three items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), - % Three items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), + %% Three items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), - ?line 2 = curf(bert), - ?line ok = disk_log:change_size(bert,{100,1}), + 2 = curf(bert), + ok = disk_log:change_size(bert,{100,1}), - % Three items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), + %% Three items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), - ?line ok = disk_log:close(bert), + ok = disk_log:close(bert), - % State: .siz is 1, current file is 2, index file size is 3... + %% State: .siz is 1, current file is 2, index file size is 3... - ?line {ok, bert} = disk_log:open([{name,bert}, {file, File}, + {ok, bert} = disk_log:open([{name,bert}, {file, File}, {type,wrap}, {notify, true}]), - % Three items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), + %% Three items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), - ?line 2 = curf(bert), - ?line ok = disk_log:blog(bert, B), - ?line rec(1, {disk_log, node(), bert, {wrap, 1}}), - ?line ok = disk_log:close(bert), + 2 = curf(bert), + ok = disk_log:blog(bert, B), + rec(1, {disk_log, node(), bert, {wrap, 1}}), + ok = disk_log:close(bert), - ?line {ok, bert} = disk_log:open([{name,bert}, {file, File}, + {ok, bert} = disk_log:open([{name,bert}, {file, File}, {type,wrap}, {notify, true}]), - % Two items expected. - % disk_log_1:print_index_file("bert.LOG.idx"), + %% Two items expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), - ?line 1 = curf(bert), - ?line ok = disk_log:blog(bert, B), + 1 = curf(bert), + ok = disk_log:blog(bert, B), %% Expect {wrap 0}. Nothing lost now, last wrap notification %% reported one lost item. - ?line rec(1, {disk_log, node(), bert, {wrap, 0}}), + rec(1, {disk_log, node(), bert, {wrap, 0}}), - % One item expected. - % disk_log_1:print_index_file("bert.LOG.idx"), - ?line ok = disk_log:close(bert), + %% One item expected. + %% disk_log_1:print_index_file("bert.LOG.idx"), + ok = disk_log:close(bert), - ?line del(File, No), + del(File, No), ok. -change_attribute(suite) -> []; -change_attribute(doc) -> - ["Change notify and head"]; +%% Change notify and head. change_attribute(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), - ?line File = filename:join(Dir, "n.LOG"), - ?line No = 4, - ?line del(File, No), % cleanup - ?line B = mk_bytes(60), + File = filename:join(Dir, "n.LOG"), + No = 4, + del(File, No), % cleanup + B = mk_bytes(60), - ?line Q = qlen(), + Q = qlen(), - % test change_notify - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + %% test change_notify + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}]), - ?line {ok, n} = disk_log:open([{name, n}]), % ignored... - ?line ok = disk_log:log_terms(n, [B,B]), - ?line {error, {badarg, notify}} = disk_log:change_notify(n, self(), wrong), - ?line ok = disk_log:change_notify(n, self(), false), - ?line ok = disk_log:change_notify(n, self(), true), - ?line Error1 = {error, {not_owner, _}} = + {ok, n} = disk_log:open([{name, n}]), % ignored... + ok = disk_log:log_terms(n, [B,B]), + {error, {badarg, notify}} = disk_log:change_notify(n, self(), wrong), + ok = disk_log:change_notify(n, self(), false), + ok = disk_log:change_notify(n, self(), true), + Error1 = {error, {not_owner, _}} = disk_log:change_notify(n, none, true), - ?line "The pid" ++ _ = format_error(Error1), - ?line 2 = no_written_items(n), - ?line 0 = users(n), - ?line Parent = self(), - ?line Pid = spawn(fun() -> disk_log:close(n), Parent ! {self(),done} end), - ?line receive {Pid, done} -> ok end, - ?line 0 = users(n), - ?line 1 = length(owners(n)), - - % test change_header - ?line {error, {badarg, head}} = disk_log:change_header(n, none), - ?line {error, {badarg, head}} = + "The pid" ++ _ = format_error(Error1), + 2 = no_written_items(n), + 0 = users(n), + Parent = self(), + Pid = spawn(fun() -> disk_log:close(n), Parent ! {self(),done} end), + receive {Pid, done} -> ok end, + 0 = users(n), + 1 = length(owners(n)), + + %% test change_header + {error, {badarg, head}} = disk_log:change_header(n, none), + {error, {badarg, head}} = disk_log:change_header(n, {head_func, {1,2,3}}), - ?line ok = disk_log:change_header(n, {head, header}), - ?line ok = disk_log:log(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line 4 = no_written_items(n), - ?line ok = disk_log:change_header(n, {head, none}), - ?line ok = disk_log:log(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 0}}), - ?line 5 = no_written_items(n), - ?line ok = disk_log:change_header(n, + ok = disk_log:change_header(n, {head, header}), + ok = disk_log:log(n, B), + rec(1, {disk_log, node(), n, {wrap, 0}}), + 4 = no_written_items(n), + ok = disk_log:change_header(n, {head, none}), + ok = disk_log:log(n, B), + rec(1, {disk_log, node(), n, {wrap, 0}}), + 5 = no_written_items(n), + ok = disk_log:change_header(n, {head_func, {?MODULE, head_fun, [{ok,header}]}}), - ?line ok = disk_log:log(n, B), - ?line rec(1, {disk_log, node(), n, {wrap, 1}}), - ?line 7 = no_written_items(n), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:close(n), - ?line del(File, No), - ?line file:delete(File), % cleanup - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {format, external}, + ok = disk_log:log(n, B), + rec(1, {disk_log, node(), n, {wrap, 1}}), + 7 = no_written_items(n), + ok = disk_log:close(n), + {error, no_such_log} = disk_log:close(n), + del(File, No), + file:delete(File), % cleanup + {ok, n} = disk_log:open([{name, n}, {file, File}, {format, external}, {type, halt}]), - ?line {error, {badarg, head}} = disk_log:change_header(n, {head, header}), - ?line ok = disk_log:change_header(n, {head, "header"}), - ?line ok = disk_log:close(n), - ?line file:delete(File), + {error, {badarg, head}} = disk_log:change_header(n, {head, header}), + ok = disk_log:change_header(n, {head, "header"}), + ok = disk_log:close(n), + file:delete(File), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}]), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}]), - ?line ok = disk_log:change_notify(n, self(), true), - ?line ok = disk_log:change_header(n, {head, tjolahopp}), - ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + ok = disk_log:change_notify(n, self(), true), + ok = disk_log:change_header(n, {head, tjolahopp}), + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {100,No}}, {notify, true}]), - ?line ok = disk_log:close(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line Q = qlen(), - ?line del(File, No). + ok = disk_log:close(n), + {error, no_such_log} = disk_log:info(n), + Q = qlen(), + del(File, No). -dist_open(suite) -> []; -dist_open(doc) -> - ["Open a distributed log"]; +%% Open a distributed log. dist_open(Conf) when is_list(Conf) -> - ?line PrivDir = ?privdir(Conf), - ?line true = is_alive(), - - ?line Q = qlen(), - ?line File = filename:join(PrivDir, "n.LOG"), - ?line File1 = filename:join(PrivDir, "n1.LOG"), - ?line No = 3, - ?line file:delete(File), - ?line del(File, No), % cleanup - ?line del(File1, No), % cleanup - ?line B = mk_bytes(60), - - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA), - ?line wait_for_ready_net(), + PrivDir = ?privdir(Conf), + true = is_alive(), + + Q = qlen(), + File = filename:join(PrivDir, "n.LOG"), + File1 = filename:join(PrivDir, "n1.LOG"), + No = 3, + file:delete(File), + del(File, No), % cleanup + del(File1, No), % cleanup + B = mk_bytes(60), + + PA = filename:dirname(code:which(?MODULE)), + {ok, Node} = start_node(disk_log, "-pa " ++ PA), + wait_for_ready_net(), %% open non-distributed on this node: - ?line {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {distributed, []}]), - ?line Error1 = {error, {halt_log, n}} = disk_log:inc_wrap_file(n), - ?line "The halt log" ++ _ = format_error(Error1), - ?line ok = disk_log:lclose(n), - ?line file:delete(File), + Error1 = {error, {halt_log, n}} = disk_log:inc_wrap_file(n), + "The halt log" ++ _ = format_error(Error1), + ok = disk_log:lclose(n), + file:delete(File), %% open distributed on this node: - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt}, {distributed, [node()]}]), %% the error message is ignored: - ?line ok = disk_log:inc_wrap_file(n), - ?line ok = disk_log:close(n), - ?line file:delete(File), + ok = disk_log:inc_wrap_file(n), + ok = disk_log:close(n), + file:delete(File), %% open a wrap log on this node, write something on this node - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}]), - ?line ok = disk_log:log(n, B), - ?line ok = disk_log:close(n), + ok = disk_log:log(n, B), + ok = disk_log:close(n), %% open a wrap log on this node and aother node, write something - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}]), - ?line {[_],[]} = disk_log:open([{name, n}, {file, File1}, + {[_],[]} = disk_log:open([{name, n}, {file, File1}, {type, wrap}, {size, {50, No}}, {distributed, [Node]}]), - ?line ok = disk_log:log(n, B), - ?line ok = rpc:call(Node, disk_log, log, [n, B]), - ?line ok = disk_log:close(n), - ?line del(File, No), - ?line del(File1, No), - ?line file:delete(File), + ok = disk_log:log(n, B), + ok = rpc:call(Node, disk_log, log, [n, B]), + ok = disk_log:close(n), + del(File, No), + del(File1, No), + file:delete(File), %% open a wrap log on this node and another node, use lclose - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}]), - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}, {linkto,none}]), - ?line {[_],[]} = disk_log:open([{name, n}, {file, File1}, + {[_],[]} = disk_log:open([{name, n}, {file, File1}, {type, wrap}, {size, {50, No}}, {distributed, [Node]}]), - ?line [_, _] = distributed(n), - ?line ok = disk_log:lclose(n, Node), - ?line [_] = distributed(n), - ?line ok = disk_log:lclose(n), - ?line ok = disk_log:lclose(n), - ?line {error, no_such_log} = disk_log:info(n), - ?line del(File, No), - ?line del(File1, No), - ?line file:delete(File), - - % open an invalid log file, and see how error are handled - ?line First = "n.LOG.1", - ?line make_file(PrivDir, First, 8), - - ?line {[], [_,_]} = disk_log:open([{name, n}, {file, File}, + [_, _] = distributed(n), + ok = disk_log:lclose(n, Node), + [_] = distributed(n), + ok = disk_log:lclose(n), + ok = disk_log:lclose(n), + {error, no_such_log} = disk_log:info(n), + del(File, No), + del(File1, No), + file:delete(File), + + %% open an invalid log file, and see how error are handled + First = "n.LOG.1", + make_file(PrivDir, First, 8), + + {[], [_,_]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [Node,node()]}]), - ?line del(File, No), - ?line file:delete(File), + del(File, No), + file:delete(File), - % open a wrap on one other node (not on this node) - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, + %% open a wrap on one other node (not on this node) + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [Node]}]), - ?line ok = rpc:call(Node, disk_log, log, [n, B]), - ?line {error, no_such_log} = disk_log:lclose(n), - ?line ok = disk_log:close(n), + ok = rpc:call(Node, disk_log, log, [n, B]), + {error, no_such_log} = disk_log:lclose(n), + ok = disk_log:close(n), - ?line Q = qlen(), + Q = qlen(), - ?line {error, no_such_log} = disk_log:info(n), - ?line del(File, No), - ?line file:delete(File), - ?line stop_node(Node), + {error, no_such_log} = disk_log:info(n), + del(File, No), + file:delete(File), + stop_node(Node), ok. -dist_error_open(suite) -> []; -dist_error_open(doc) -> - ["Open a log distributed and not distributed"]; +%% Open a log distributed and not distributed. dist_error_open(Conf) when is_list(Conf) -> - ?line PrivDir = ?privdir(Conf), - ?line true = is_alive(), - - ?line Q = qlen(), - ?line File = filename:join(PrivDir, "bert.LOG"), - ?line File1 = filename:join(PrivDir, "bert1.LOG"), - ?line No = 3, - ?line file:delete(File), - ?line del(File, No), % cleanup - ?line del(File1, No), % cleanup - - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA), - ?line wait_for_ready_net(), - - % open non-distributed on this node: - ?line {ok,n} = disk_log:open([{name, n}, {file, File}, + PrivDir = ?privdir(Conf), + true = is_alive(), + + Q = qlen(), + File = filename:join(PrivDir, "bert.LOG"), + File1 = filename:join(PrivDir, "bert1.LOG"), + No = 3, + file:delete(File), + del(File, No), % cleanup + del(File1, No), % cleanup + + PA = filename:dirname(code:which(?MODULE)), + {ok, Node} = start_node(disk_log, "-pa " ++ PA), + wait_for_ready_net(), + + %% open non-distributed on this node: + {ok,n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}]), - % trying to open distributed on this node (error): - ?line {[],[Error1={ENode,{error,{node_already_open,n}}}]} = + %% trying to open distributed on this node (error): + {[],[Error1={ENode,{error,{node_already_open,n}}}]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}]), - ?line true = + true = lists:prefix(lists:flatten(io_lib:format("~p: The distribution", [ENode])), format_error(Error1)), - ?line ok = disk_log:lclose(n), + ok = disk_log:lclose(n), - % open distributed on this node: - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, + %% open distributed on this node: + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}]), - % trying to open non-distributed on this node (error): - ?line {_,{node_already_open,n}} = + %% trying to open non-distributed on this node (error): + {_,{node_already_open,n}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {size, {50, No}}]), - ?line ok = disk_log:close(n), - ?line Q = qlen(), + ok = disk_log:close(n), + Q = qlen(), - ?line del(File, No), - ?line del(File1, No), - ?line file:delete(File), - ?line stop_node(Node), + del(File, No), + del(File1, No), + file:delete(File), + stop_node(Node), ok. -dist_notify(suite) -> []; -dist_notify(doc) -> - ["Notification from other node"]; +%% Notification from other node. dist_notify(Conf) when is_list(Conf) -> - ?line PrivDir = ?privdir(Conf), - ?line true = is_alive(), + PrivDir = ?privdir(Conf), + true = is_alive(), - ?line File = filename:join(PrivDir, "bert.LOG"), - ?line File1 = filename:join(PrivDir, "bert1.LOG"), - ?line No = 3, - ?line B = mk_bytes(60), - ?line file:delete(File), - ?line file:delete(File1), - ?line del(File, No), % cleanup - ?line del(File1, No), - - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA), - ?line wait_for_ready_net(), - - % opening distributed on this node: - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, {notify, false}, + File = filename:join(PrivDir, "bert.LOG"), + File1 = filename:join(PrivDir, "bert1.LOG"), + No = 3, + B = mk_bytes(60), + file:delete(File), + file:delete(File1), + del(File, No), % cleanup + del(File1, No), + + PA = filename:dirname(code:which(?MODULE)), + {ok, Node} = start_node(disk_log, "-pa " ++ PA), + wait_for_ready_net(), + + %% opening distributed on this node: + {[_],[]} = disk_log:open([{name, n}, {file, File}, {notify, false}, {type, wrap}, {size, {50, No}}, {distributed, [node()]}]), - % opening distributed on other node: - ?line {[_],[]} = disk_log:open([{name, n}, {file, File1}, + %% opening distributed on other node: + {[_],[]} = disk_log:open([{name, n}, {file, File1}, {notify, true}, {linkto, self()}, {type, wrap}, {size, {50, No}}, {distributed, [Node]}]), - ?line disk_log:alog(n, B), - ?line disk_log:alog(n, B), - ?line ok = disk_log:sync(n), - ?line rec(1, {disk_log, Node, n, {wrap, 0}}), - ?line ok = disk_log:close(n), - - ?line del(File, No), - ?line del(File1, No), - ?line file:delete(File), - ?line stop_node(Node), + disk_log:alog(n, B), + disk_log:alog(n, B), + ok = disk_log:sync(n), + rec(1, {disk_log, Node, n, {wrap, 0}}), + ok = disk_log:close(n), + + del(File, No), + del(File1, No), + file:delete(File), + stop_node(Node), ok. -dist_terminate(suite) -> []; -dist_terminate(doc) -> - ["Terminating nodes with distributed logs"]; +%% Terminating nodes with distributed logs. dist_terminate(Conf) when is_list(Conf) -> - ?line Dir = ?privdir(Conf), - ?line true = is_alive(), + Dir = ?privdir(Conf), + true = is_alive(), - ?line File = filename:join(Dir, "n.LOG"), - ?line File1 = filename:join(Dir, "n1.LOG"), + File = filename:join(Dir, "n.LOG"), + File1 = filename:join(Dir, "n1.LOG"), No = 1, del(File, No), % cleanup del(File1, No), % cleanup - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA), - ?line wait_for_ready_net(), + PA = filename:dirname(code:which(?MODULE)), + {ok, Node} = start_node(disk_log, "-pa " ++ PA), + wait_for_ready_net(), %% Distributed versions of two of the situations in close_block(/1. %% One of two owners terminates. - ?line Pid1 = spawn_link(?MODULE, lserv, [n]), - ?line Pid2 = spawn_link(?MODULE, lserv, [n]), - ?line {[{_, {ok, n}}], []} = sync_do(Pid1, {dist_open, File, node()}), - ?line {[{_, {ok, n}}], []} = sync_do(Pid2, {dist_open, File1, Node}), - ?line [_] = sync_do(Pid1, owners), - ?line [_] = sync_do(Pid2, owners), - ?line 0 = sync_do(Pid1, users), - ?line 0 = sync_do(Pid2, users), - ?line sync_do(Pid1, terminate), - ?line [_] = sync_do(Pid2, owners), - ?line 0 = sync_do(Pid2, users), - ?line sync_do(Pid2, terminate), - ?line {error, no_such_log} = disk_log:info(n), + Pid1 = spawn_link(?MODULE, lserv, [n]), + Pid2 = spawn_link(?MODULE, lserv, [n]), + {[{_, {ok, n}}], []} = sync_do(Pid1, {dist_open, File, node()}), + {[{_, {ok, n}}], []} = sync_do(Pid2, {dist_open, File1, Node}), + [_] = sync_do(Pid1, owners), + [_] = sync_do(Pid2, owners), + 0 = sync_do(Pid1, users), + 0 = sync_do(Pid2, users), + sync_do(Pid1, terminate), + [_] = sync_do(Pid2, owners), + 0 = sync_do(Pid2, users), + sync_do(Pid2, terminate), + {error, no_such_log} = disk_log:info(n), %% Users terminate (no link...). - ?line Pid3 = spawn_link(?MODULE, lserv, [n]), - ?line Pid4 = spawn_link(?MODULE, lserv, [n]), - ?line {[{_, {ok, n}}], []} = + Pid3 = spawn_link(?MODULE, lserv, [n]), + Pid4 = spawn_link(?MODULE, lserv, [n]), + {[{_, {ok, n}}], []} = sync_do(Pid3, {dist_open, File, none, node()}), - ?line {[{_, {ok, n}}], []} = + {[{_, {ok, n}}], []} = sync_do(Pid4, {dist_open, File1, none, Node}), - ?line [] = sync_do(Pid3, owners), - ?line [] = sync_do(Pid4, owners), - ?line 1 = sync_do(Pid3, users), - ?line 1 = sync_do(Pid4, users), - ?line sync_do(Pid3, terminate), - ?line [] = sync_do(Pid4, owners), - ?line 1 = sync_do(Pid4, users), - ?line sync_do(Pid4, terminate), - ?line ok = disk_log:close(n), % closing all nodes - ?line {error, no_such_log} = disk_log:info(n), + [] = sync_do(Pid3, owners), + [] = sync_do(Pid4, owners), + 1 = sync_do(Pid3, users), + 1 = sync_do(Pid4, users), + sync_do(Pid3, terminate), + [] = sync_do(Pid4, owners), + 1 = sync_do(Pid4, users), + sync_do(Pid4, terminate), + ok = disk_log:close(n), % closing all nodes + {error, no_such_log} = disk_log:info(n), - ?line del(File, No), - ?line del(File1, No), - ?line stop_node(Node), + del(File, No), + del(File1, No), + stop_node(Node), ok. -dist_accessible(suite) -> []; -dist_accessible(doc) -> - ["Accessible logs on nodes"]; +%% Accessible logs on nodes. dist_accessible(Conf) when is_list(Conf) -> - ?line PrivDir = ?privdir(Conf), - - ?line true = is_alive(), - - ?line F1 = filename:join(PrivDir, "a.LOG"), - ?line file:delete(F1), - ?line F2 = filename:join(PrivDir, "b.LOG"), - ?line file:delete(F2), - ?line F3 = filename:join(PrivDir, "c.LOG"), - ?line file:delete(F3), - ?line F4 = filename:join(PrivDir, "d.LOG"), - ?line file:delete(F1), - ?line F5 = filename:join(PrivDir, "e.LOG"), - ?line file:delete(F2), - ?line F6 = filename:join(PrivDir, "f.LOG"), - ?line file:delete(F3), - - ?line {[],[]} = disk_log:accessible_logs(), - ?line {ok, a} = disk_log:open([{name, a}, {type, halt}, {file, F1}]), - ?line {[a],[]} = disk_log:accessible_logs(), - ?line {ok, b} = disk_log:open([{name, b}, {type, halt}, {file, F2}]), - ?line {[a,b],[]} = disk_log:accessible_logs(), - ?line {ok, c} = disk_log:open([{name, c}, {type, halt}, {file, F3}]), - ?line {[a,b,c],[]} = disk_log:accessible_logs(), - - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA), - ?line wait_for_ready_net(), - - ?line {[_],[]} = disk_log:open([{name, a}, {file, F4}, {type, halt}, + PrivDir = ?privdir(Conf), + + true = is_alive(), + + F1 = filename:join(PrivDir, "a.LOG"), + file:delete(F1), + F2 = filename:join(PrivDir, "b.LOG"), + file:delete(F2), + F3 = filename:join(PrivDir, "c.LOG"), + file:delete(F3), + F4 = filename:join(PrivDir, "d.LOG"), + file:delete(F1), + F5 = filename:join(PrivDir, "e.LOG"), + file:delete(F2), + F6 = filename:join(PrivDir, "f.LOG"), + file:delete(F3), + + {[],[]} = disk_log:accessible_logs(), + {ok, a} = disk_log:open([{name, a}, {type, halt}, {file, F1}]), + {[a],[]} = disk_log:accessible_logs(), + {ok, b} = disk_log:open([{name, b}, {type, halt}, {file, F2}]), + {[a,b],[]} = disk_log:accessible_logs(), + {ok, c} = disk_log:open([{name, c}, {type, halt}, {file, F3}]), + {[a,b,c],[]} = disk_log:accessible_logs(), + + PA = filename:dirname(code:which(?MODULE)), + {ok, Node} = start_node(disk_log, "-pa " ++ PA), + wait_for_ready_net(), + + {[_],[]} = disk_log:open([{name, a}, {file, F4}, {type, halt}, {distributed, [Node]}]), - ?line {[a,b,c],[]} = disk_log:accessible_logs(), - ?line {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []), - ?line {[_],[]} = disk_log:open([{name, b}, {file, F5}, {type, halt}, + {[a,b,c],[]} = disk_log:accessible_logs(), + {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []), + {[_],[]} = disk_log:open([{name, b}, {file, F5}, {type, halt}, {distributed, [Node]}]), - ?line {[],[a,b]} = rpc:call(Node, disk_log, accessible_logs, []), - ?line {[_],[]} = disk_log:open([{name, c}, {file, F6}, {type, halt}, + {[],[a,b]} = rpc:call(Node, disk_log, accessible_logs, []), + {[_],[]} = disk_log:open([{name, c}, {file, F6}, {type, halt}, {distributed, [Node]}]), - ?line {[],[a,b,c]} = rpc:call(Node, disk_log, accessible_logs, []), - ?line {[a,b,c],[]} = disk_log:accessible_logs(), - ?line ok = disk_log:close(a), - ?line {[b,c],[a]} = disk_log:accessible_logs(), - ?line ok = disk_log:close(b), - ?line {[c],[a,b]} = disk_log:accessible_logs(), - ?line ok = disk_log:close(b), - ?line {[c],[a]} = disk_log:accessible_logs(), - ?line {[],[a,c]} = rpc:call(Node, disk_log, accessible_logs, []), - ?line ok = disk_log:close(c), - ?line {[],[a,c]} = disk_log:accessible_logs(), - ?line ok = disk_log:close(c), - ?line {[],[a]} = disk_log:accessible_logs(), - ?line {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []), - ?line ok = disk_log:close(a), - ?line {[],[]} = disk_log:accessible_logs(), - ?line {[],[]} = rpc:call(Node, disk_log, accessible_logs, []), - - ?line file:delete(F1), - ?line file:delete(F2), - ?line file:delete(F3), - ?line file:delete(F4), - ?line file:delete(F5), - ?line file:delete(F6), - - ?line stop_node(Node), + {[],[a,b,c]} = rpc:call(Node, disk_log, accessible_logs, []), + {[a,b,c],[]} = disk_log:accessible_logs(), + ok = disk_log:close(a), + {[b,c],[a]} = disk_log:accessible_logs(), + ok = disk_log:close(b), + {[c],[a,b]} = disk_log:accessible_logs(), + ok = disk_log:close(b), + {[c],[a]} = disk_log:accessible_logs(), + {[],[a,c]} = rpc:call(Node, disk_log, accessible_logs, []), + ok = disk_log:close(c), + {[],[a,c]} = disk_log:accessible_logs(), + ok = disk_log:close(c), + {[],[a]} = disk_log:accessible_logs(), + {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []), + ok = disk_log:close(a), + {[],[]} = disk_log:accessible_logs(), + {[],[]} = rpc:call(Node, disk_log, accessible_logs, []), + + file:delete(F1), + file:delete(F2), + file:delete(F3), + file:delete(F4), + file:delete(F5), + file:delete(F6), + + stop_node(Node), ok. -dist_deadlock(suite) -> []; -dist_deadlock(doc) -> - ["OTP-4405. Deadlock between two nodes could happen."]; +%% OTP-4405. Deadlock between two nodes could happen. dist_deadlock(Conf) when is_list(Conf) -> - ?line PrivDir = ?privdir(Conf), + PrivDir = ?privdir(Conf), - ?line true = is_alive(), + true = is_alive(), - ?line F1 = filename:join(PrivDir, "a.LOG"), - ?line file:delete(F1), - ?line F2 = filename:join(PrivDir, "b.LOG"), - ?line file:delete(F2), + F1 = filename:join(PrivDir, "a.LOG"), + file:delete(F1), + F2 = filename:join(PrivDir, "b.LOG"), + file:delete(F2), - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node1} = start_node(disk_log_node1, "-pa " ++ PA), - ?line {ok, Node2} = start_node(disk_log_node2, "-pa " ++ PA), - ?line wait_for_ready_net(), + PA = filename:dirname(code:which(?MODULE)), + {ok, Node1} = start_node(disk_log_node1, "-pa " ++ PA), + {ok, Node2} = start_node(disk_log_node2, "-pa " ++ PA), + wait_for_ready_net(), Self = self(), Fun1 = fun() -> dist_dl(Node2, a, F1, Self) end, @@ -4477,11 +4377,11 @@ dist_deadlock(Conf) when is_list(Conf) -> receive {P1, a} -> ok end, receive {P2, b} -> ok end, - ?line stop_node(Node1), - ?line stop_node(Node2), + stop_node(Node1), + stop_node(Node2), - ?line file:delete(F1), - ?line file:delete(F2), + file:delete(F1), + file:delete(F2), ok. dist_dl(Node, Name, File, Pid) -> @@ -4492,12 +4392,10 @@ dist_dl(Node, Name, File, Pid) -> Pid ! {self(), Name}, ok. -dist_open2(suite) -> []; -dist_open2(doc) -> - ["OTP-4480. Opening several logs simultaneously."]; +%% OTP-4480. Opening several logs simultaneously. dist_open2(Conf) when is_list(Conf) -> - ?line true = is_alive(), - ?line {ok, _Pg2} = pg2:start(), + true = is_alive(), + {ok, _Pg2} = pg2:start(), dist_open2_1(Conf, 0), dist_open2_1(Conf, 100), @@ -4513,9 +4411,9 @@ dist_open2(Conf) when is_list(Conf) -> %% to open the log. The second one succeeds, and the third one is %% attached. P0 = pps(), - ?line File0 = "n.LOG", - ?line File = filename:join(PrivDir, File0), - ?line make_file(PrivDir, File0, 8), + File0 = "n.LOG", + File = filename:join(PrivDir, File0), + make_file(PrivDir, File0, 8), Parent = self(), F1 = fun() -> R = disk_log:open([{name, Log}, {file, File}, @@ -4529,18 +4427,18 @@ dist_open2(Conf) when is_list(Conf) -> Parent ! {self(), R}, timer:sleep(300) end, - ?line Pid1 = spawn(F1), + Pid1 = spawn(F1), timer:sleep(10), - ?line Pid2 = spawn(F2), - ?line Pid3 = spawn(F2), + Pid2 = spawn(F2), + Pid3 = spawn(F2), - ?line receive {Pid1,R1} -> {[],[_]} = R1 end, - ?line receive {Pid2,R2} -> {[_],[]} = R2 end, - ?line receive {Pid3,R3} -> {[_],[]} = R3 end, + receive {Pid1,R1} -> {[],[_]} = R1 end, + receive {Pid2,R2} -> {[_],[]} = R2 end, + receive {Pid3,R3} -> {[_],[]} = R3 end, timer:sleep(500), - ?line file:delete(File), - ?line true = (P0 == pps()), + file:delete(File), + true = (P0 == pps()), %% This time the first process has a naughty head_func. This test %% does not add very much. Perhaps it should be removed. However, @@ -4561,15 +4459,15 @@ dist_open2(Conf) when is_list(Conf) -> {type,halt}]), Parent ! {self(), R} end, - ?line Pid4 = spawn(F3), + Pid4 = spawn(F3), timer:sleep(10), - ?line Pid5 = spawn(F4), - ?line Pid6 = spawn(F4), + Pid5 = spawn(F4), + Pid6 = spawn(F4), %% The timing is crucial here. - ?line R = case receive {Pid4,R4} -> R4 end of + R = case receive {Pid4,R4} -> R4 end of {error, no_such_log} -> - ?line R5 = receive {Pid5, R5a} -> R5a end, - ?line R6 = receive {Pid6, R6a} -> R6a end, + R5 = receive {Pid5, R5a} -> R5a end, + R6 = receive {Pid6, R6a} -> R6a end, case {R5, R6} of {{repaired, _, _, _}, {ok, Log}} -> ok; {{ok, Log}, {repaired, _, _, _}} -> ok; @@ -4577,16 +4475,16 @@ dist_open2(Conf) when is_list(Conf) -> end, ok; {ok, Log} -> % uninteresting case - ?line receive {Pid5,_R5} -> ok end, - ?line receive {Pid6,_R6} -> ok end, + receive {Pid5,_R5} -> ok end, + receive {Pid6,_R6} -> ok end, {comment, "Timing dependent test did not check anything."} end, timer:sleep(100), - ?line {error, no_such_log} = disk_log:close(Log), + {error, no_such_log} = disk_log:close(Log), file:delete(File), - ?line true = (P0 == pps()), + true = (P0 == pps()), No = 2, Log2 = n2, @@ -4598,7 +4496,7 @@ dist_open2(Conf) when is_list(Conf) -> %% processes should be able to attach to other log without having to %% wait. - ?line {ok,Log} = + {ok,Log} = disk_log:open([{name,Log},{file,File},{type,wrap},{size,{100,No}}]), Pid = spawn(fun() -> receive {HeadPid, start} -> ok end, @@ -4607,15 +4505,15 @@ dist_open2(Conf) when is_list(Conf) -> HeadPid ! {self(), done} end), HeadFunc = {?MODULE, slow_header, [Pid]}, - ?line ok = disk_log:change_header(Log, {head_func, HeadFunc}), - ?line ok = disk_log:inc_wrap_file(Log), % header is written + ok = disk_log:change_header(Log, {head_func, HeadFunc}), + ok = disk_log:inc_wrap_file(Log), % header is written timer:sleep(100), - ?line ok = disk_log:close(Log), + ok = disk_log:close(Log), file:delete(File2), del(File, No), - ?line true = (P0 == pps()), + true = (P0 == pps()), R. @@ -4625,13 +4523,13 @@ dist_open2_1(Conf, Delay) -> Log = n, A0 = [{name,Log},{file,File},{type,halt}], - ?line create_opened_log(File, A0), + create_opened_log(File, A0), P0 = pps(), Log2 = log2, File2 = "log2.LOG", - ?line file:delete(File2), - ?line {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]), + file:delete(File2), + {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]), Parent = self(), F = fun() -> @@ -4639,28 +4537,28 @@ dist_open2_1(Conf, Delay) -> timer:sleep(Delay), Parent ! {self(), R} end, - ?line Pid1 = spawn(F), + Pid1 = spawn(F), timer:sleep(10), - ?line Pid2 = spawn(F), - ?line Pid3 = spawn(F), - ?line {error, no_such_log} = disk_log:log(Log, term), % is repairing now - ?line 0 = qlen(), + Pid2 = spawn(F), + Pid3 = spawn(F), + {error, no_such_log} = disk_log:log(Log, term), % is repairing now + 0 = qlen(), %% The file is already open, so this will not take long. - ?line {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]), - ?line 0 = qlen(), % still repairing - ?line ok = disk_log:close(Log2), - ?line {error, no_such_log} = disk_log:close(Log2), - ?line file:delete(File2), - - ?line receive {Pid1,R1} -> {repaired,_,_,_} = R1 end, - ?line receive {Pid2,R2} -> {ok,_} = R2 end, - ?line receive {Pid3,R3} -> {ok,_} = R3 end, + {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]), + 0 = qlen(), % still repairing + ok = disk_log:close(Log2), + {error, no_such_log} = disk_log:close(Log2), + file:delete(File2), + + receive {Pid1,R1} -> {repaired,_,_,_} = R1 end, + receive {Pid2,R2} -> {ok,_} = R2 end, + receive {Pid3,R3} -> {ok,_} = R3 end, timer:sleep(500), - ?line {error, no_such_log} = disk_log:info(Log), + {error, no_such_log} = disk_log:info(Log), file:delete(File), - ?line true = (P0 == pps()), + true = (P0 == pps()), ok. @@ -4669,18 +4567,18 @@ dist_open2_2(Conf, Delay) -> File = filename:join(Dir, "n.LOG"), Log = n, - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, Node1} = start_node(disk_log_node2, "-pa " ++ PA), - ?line wait_for_ready_net(), + PA = filename:dirname(code:which(?MODULE)), + {ok, Node1} = start_node(disk_log_node2, "-pa " ++ PA), + wait_for_ready_net(), P0 = pps(), A0 = [{name,Log},{file,File},{type,halt}], - ?line create_opened_log(File, A0), + create_opened_log(File, A0), Log2 = log2, File2 = "log2.LOG", - ?line file:delete(File2), - ?line {[{Node1,{ok,Log2}}],[]} = + file:delete(File2), + {[{Node1,{ok,Log2}}],[]} = disk_log:open([{name,Log2},{file,File2},{type,halt}, {distributed,[Node1]}]), @@ -4693,32 +4591,32 @@ dist_open2_2(Conf, Delay) -> Parent ! {self(), R} end, %% And {priority, ...} probably has no effect either. - ?line Pid1 = spawn_opt(F, [{priority, low}]), - % timer:sleep(1), % no guarantee that Pid1 will return {repaired, ...} - ?line Pid2 = spawn_opt(F, [{priority, low}]), - ?line {error, no_such_log} = + Pid1 = spawn_opt(F, [{priority, low}]), + %% timer:sleep(1), % no guarantee that Pid1 will return {repaired, ...} + Pid2 = spawn_opt(F, [{priority, low}]), + {error, no_such_log} = disk_log:log(Log, term), % maybe repairing now - ?line 0 = qlen(), + 0 = qlen(), %% The file is already open, so this will not take long. - ?line {[{Node1,{ok,Log2}}],[]} = + {[{Node1,{ok,Log2}}],[]} = disk_log:open([{name,Log2},{file,File2},{type,halt}, {distributed,[Node1]}]), - ?line 0 = qlen(), % probably still repairing - ?line ok = disk_log:close(Log2), - ?line file:delete(File2), + 0 = qlen(), % probably still repairing + ok = disk_log:close(Log2), + file:delete(File2), - ?line receive {Pid1,R1} -> R1 end, - ?line receive {Pid2,R2} -> R2 end, - ?line case {R1, R2} of + receive {Pid1,R1} -> R1 end, + receive {Pid2,R2} -> R2 end, + case {R1, R2} of {{[{Node1,{repaired,_,_,_}}],[]}, {[{Node1,{ok,Log}}],[]}} -> ok; {{[{Node1,{ok,Log}}],[]}, {[{Node1,{repaired,_,_,_}}],[]}} -> ok end, - ?line true = (P0 == pps()), - ?line stop_node(Node1), + true = (P0 == pps()), + stop_node(Node1), file:delete(File), ok. @@ -4751,38 +4649,35 @@ log_terms(Log, N) -> ok = disk_log:log(Log, {term, N}), log_terms(Log, N-1). -other_groups(suite) -> []; -other_groups(doc) -> - ["OTP-5810. Cope with pg2 groups that are not disk logs."]; +%% OTP-5810. Cope with pg2 groups that are not disk logs. other_groups(Conf) when is_list(Conf) -> - ?line true = is_alive(), - ?line PrivDir = ?privdir(Conf), + true = is_alive(), + PrivDir = ?privdir(Conf), - ?line File = filename:join(PrivDir, "n.LOG"), - ?line file:delete(File), + File = filename:join(PrivDir, "n.LOG"), + file:delete(File), - ?line {[],[]} = disk_log:accessible_logs(), - ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt}, + {[],[]} = disk_log:accessible_logs(), + {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt}, {distributed, [node()]}]), - ?line {[],[n]} = disk_log:accessible_logs(), + {[],[n]} = disk_log:accessible_logs(), Group = grupp, - ?line pg2:create(Group), - ?line ok = pg2:join(Group, self()), - ?line {[],[n]} = disk_log:accessible_logs(), - ?line [_] = + pg2:create(Group), + ok = pg2:join(Group, self()), + {[],[n]} = disk_log:accessible_logs(), + [_] = lists:filter(fun(P) -> disk_log:pid2name(P) =/= undefined end, erlang:processes()), - ?line pg2:delete(Group), - ?line {[],[n]} = disk_log:accessible_logs(), - ?line ok = disk_log:close(n), - ?line {[],[]} = disk_log:accessible_logs(), - ?line file:delete(File), + pg2:delete(Group), + {[],[n]} = disk_log:accessible_logs(), + ok = disk_log:close(n), + {[],[]} = disk_log:accessible_logs(), + file:delete(File), ok. --define(MAX, 16384). % MAX in disk_log_1.erl -evil(suite) -> []; -evil(doc) -> ["Evil cases such as closed file descriptor port."]; +-define(MAX, ?MAX_FWRITE_CACHE). % as in disk_log_1.erl +%% Evil cases such as closed file descriptor port. evil(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "n.LOG"), @@ -4790,62 +4685,62 @@ evil(Conf) when is_list(Conf) -> %% Not a very thorough test. - ?line ok = setup_evil_filled_cache_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:log(Log, apa), - ?line ok = disk_log:close(Log), + ok = setup_evil_filled_cache_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:log(Log, apa), + ok = disk_log:close(Log), - ?line ok = setup_evil_filled_cache_halt(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:truncate(Log, apa), - ?line ok = stop_evil(Log), + ok = setup_evil_filled_cache_halt(Log, Dir), + {error, {file_error,_,einval}} = disk_log:truncate(Log, apa), + ok = stop_evil(Log), %% White box test. file:delete(File), - ?line Ports0 = erlang:ports(), - ?line {ok, Log} = disk_log:open([{name,Log},{file,File},{type,halt}, + Ports0 = erlang:ports(), + {ok, Log} = disk_log:open([{name,Log},{file,File},{type,halt}, {size,?MAX+50},{format,external}]), - ?line [Fd] = erlang:ports() -- Ports0, - ?line {B,_} = x_mk_bytes(30), - ?line ok = disk_log:blog(Log, <<0:(?MAX+1)/unit:8>>), - ?line exit(Fd, kill), - ?line {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]), - ?line ok= disk_log:close(Log), + [Fd] = erlang:ports() -- Ports0, + {B,_} = x_mk_bytes(30), + ok = disk_log:blog(Log, <<0:(?MAX-1)/unit:8>>), + exit(Fd, kill), + {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]), + ok= disk_log:close(Log), file:delete(File), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:close(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:close(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:log(Log, apa), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:log(Log, apa), + ok = stop_evil(Log), - ?line ok = setup_evil_halt(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:log(Log, apa), - ?line ok = stop_evil(Log), + ok = setup_evil_halt(Log, Dir), + {error, {file_error,_,einval}} = disk_log:log(Log, apa), + ok = stop_evil(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:reopen(Log, apa), - ?line {error, {file_error,_,einval}} = disk_log:reopen(Log, apa), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:reopen(Log, apa), + {error, {file_error,_,einval}} = disk_log:reopen(Log, apa), + ok = stop_evil(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:reopen(Log, apa), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:reopen(Log, apa), + ok = stop_evil(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:inc_wrap_file(Log), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:inc_wrap_file(Log), + ok = stop_evil(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:chunk(Log, start), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:chunk(Log, start), + ok = stop_evil(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:truncate(Log), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:truncate(Log), + ok = stop_evil(Log), - ?line ok = setup_evil_wrap(Log, Dir), - ?line {error, {file_error,_,einval}} = disk_log:chunk_step(Log, start, 1), - ?line ok = stop_evil(Log), + ok = setup_evil_wrap(Log, Dir), + {error, {file_error,_,einval}} = disk_log:chunk_step(Log, start, 1), + ok = stop_evil(Log), io:format("messages: ~p~n", [erlang:process_info(self(), messages)]), del(File, 2), @@ -4894,25 +4789,23 @@ setup_evil_filled_cache(Log, Args, Dir) -> exit(Fd, kill), ok. -otp_6278(suite) -> []; -otp_6278(doc) -> ["OTP-6278. open/1 creates no status or crash report."]; +%% OTP-6278. open/1 creates no status or crash report. otp_6278(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = filename:join(Dir, "no_such_dir/no_such_file"), - ?line error_logger:add_report_handler(?MODULE, self()), - ?line {error, {file_error, _, _}} = + error_logger:add_report_handler(?MODULE, self()), + {error, {file_error, _, _}} = disk_log:open([{name,n},{file,File}]), receive {crash_report,_Pid,Report} -> - ?line io:format("Unexpected: ~p\n", [Report]), - ?line ?t:fail() + io:format("Unexpected: ~p\n", [Report]), + ct:fail(failed) after 1000 -> ok end, - ?line error_logger:delete_report_handler(?MODULE). + error_logger:delete_report_handler(?MODULE). -otp_10131(suite) -> []; -otp_10131(doc) -> ["OTP-10131. head_func type."]; +%% OTP-10131. head_func type. otp_10131(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), Log = otp_10131, @@ -4979,7 +4872,7 @@ copy_wrap_log(FromName, ToName, N, FromDir, ToDir) -> -define(BUFSIZE, 8192). copy_file(Src, Dest) -> - % ?t:format("copying from ~p to ~p~n", [Src, Dest]), + %% io:format("copying from ~p to ~p~n", [Src, Dest]), {ok, InFd} = file:open(Src, [raw, binary, read]), {ok, OutFd} = file:open(Dest, [raw, binary, write]), ok = copy_file1(InFd, OutFd), @@ -5104,50 +4997,15 @@ get_known(Node) -> %% Copied from erl_distribution_SUITE.erl: start_node(Name, Param) -> - ?t:start_node(Name, slave, [{args, Param}]). + test_server:start_node(Name, slave, [{args, Param}]). stop_node(Node) -> - ?t:stop_node(Node). - -%from(H, [H | T]) -> T; -%from(H, [_ | T]) -> from(H, T); -%from(_H, []) -> []. - + test_server:stop_node(Node). -%% Check for NFS cache size, this is called from init_per_testcase() and -%% makes different tests run depending on the size of the NFS cache on -%% VxWorks. Possibly this could be adopted to Windows too, but we seldom use -%% NFS when testing on windows, so I can find better things to do. -%% The port program used simply reads the nfsCacheSize variable on the board. -%% If the board is configured without NFS, the port program will fail to load -%% and this will return 0, which may or may not be the wrong thing to do. +%% from(H, [H | T]) -> T; +%% from(H, [_ | T]) -> from(H, T); +%% from(_H, []) -> []. -check_nfs(_Config) -> - 0. - -skip_expand([]) -> - []; -skip_expand([Case | T]) -> - case (catch apply(?MODULE, Case, [suite])) of - {'EXIT', _} -> - [Case | skip_expand(T)]; - [] -> - [Case | skip_expand(T)]; - Res -> - skip_expand(Res) ++ skip_expand(T) - end. - - -skip_list(Config) -> - case check_nfs(Config) of - 0 -> - skip_expand(?SKIP_NO_CACHE); - _ -> - skip_expand(?SKIP_LARGE_CACHE) - end. - -should_skip(_Test,_Config) -> - false. %%----------------------------------------------------------------- %% The error_logger handler used. @@ -5159,6 +5017,9 @@ init(Tester) -> handle_event({error_report, _GL, {Pid, crash_report, Report}}, Tester) -> Tester ! {crash_report, Pid, Report}, {ok, Tester}; +handle_event({info_msg, _GL, {Pid, F,A}}, Tester) -> + Tester ! {info_msg, Pid, F, A}, + {ok, Tester}; handle_event(_Event, State) -> {ok, State}. diff --git a/lib/kernel/test/disk_log_SUITE_data/wrap_log_test.erl b/lib/kernel/test/disk_log_SUITE_data/wrap_log_test.erl index 1cd1a4b0a4..38449b6bb3 100644 --- a/lib/kernel/test/disk_log_SUITE_data/wrap_log_test.erl +++ b/lib/kernel/test/disk_log_SUITE_data/wrap_log_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/erl_boot_server_SUITE.erl b/lib/kernel/test/erl_boot_server_SUITE.erl index 954880e252..1eaa2cf500 100644 --- a/lib/kernel/test/erl_boot_server_SUITE.erl +++ b/lib/kernel/test/erl_boot_server_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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. @@ -19,7 +19,7 @@ %% -module(erl_boot_server_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). @@ -34,7 +34,9 @@ %% Changed for the new erl_boot_server for R3A by Bjorn Gustavsson. %%----------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [start, start_link, stop, add, delete, responses]. @@ -57,274 +59,262 @@ end_per_group(_GroupName, Config) -> -define(all_ones, {255, 255, 255, 255}). -start(doc) -> "Tests the erl_boot_server:start/1 function."; +%% Tests the erl_boot_server:start/1 function. start(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(50)), - ?line [Host1, Host2|_] = good_hosts(Config), + [Host1, Host2|_] = good_hosts(Config), %% Bad arguments. BadHost = "bad__host", - ?line {error, {badarg, {}}} = erl_boot_server:start({}), - ?line {error, {badarg, atom}} = erl_boot_server:start(atom), - ?line {error, {badarg, [atom, BadHost]}} = + {error, {badarg, {}}} = erl_boot_server:start({}), + {error, {badarg, atom}} = erl_boot_server:start(atom), + {error, {badarg, [atom, BadHost]}} = erl_boot_server:start([atom, BadHost]), - ?line {error, {badarg, [Host1, BadHost]}} = + {error, {badarg, [Host1, BadHost]}} = erl_boot_server:start([Host1, BadHost]), %% Test once. - ?line {ok, Pid1} = erl_boot_server:start([Host1]), - ?line {error, {already_started, Pid1}} = + {ok, Pid1} = erl_boot_server:start([Host1]), + {error, {already_started, Pid1}} = erl_boot_server:start([Host1]), - ?line exit(Pid1, kill), + exit(Pid1, kill), %% Test again. - test_server:sleep(1), - ?line {ok, Pid2} = erl_boot_server:start([Host1, Host2]), - ?line {error, {already_started, Pid2}} = + ct:sleep(1), + {ok, Pid2} = erl_boot_server:start([Host1, Host2]), + {error, {already_started, Pid2}} = erl_boot_server:start([Host1, Host2]), - ?line exit(Pid2, kill), - test_server:sleep(1), + exit(Pid2, kill), + ct:sleep(1), - ?line test_server:timetrap_cancel(Dog), ok. -start_link(doc) -> "Tests the erl_boot_server:start_link/1 function."; +%% Tests the erl_boot_server:start_link/1 function. start_link(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line [Host1, Host2|_] = good_hosts(Config), + [Host1, Host2|_] = good_hosts(Config), OldFlag = process_flag(trap_exit, true), - ?line {error, {badarg, {}}} = erl_boot_server:start_link({}), - ?line {error, {badarg, atom}} = erl_boot_server:start_link(atom), - ?line BadHost = "bad__host", - ?line {error, {badarg, [atom, BadHost]}} = + {error, {badarg, {}}} = erl_boot_server:start_link({}), + {error, {badarg, atom}} = erl_boot_server:start_link(atom), + BadHost = "bad__host", + {error, {badarg, [atom, BadHost]}} = erl_boot_server:start_link([atom, BadHost]), - ?line {ok, Pid1} = erl_boot_server:start_link([Host1]), - ?line {error, {already_started, Pid1}} = + {ok, Pid1} = erl_boot_server:start_link([Host1]), + {error, {already_started, Pid1}} = erl_boot_server:start_link([Host1]), - ?line shutdown(Pid1), + shutdown(Pid1), - ?line {ok, Pid2} = erl_boot_server:start_link([Host1, Host2]), - ?line {error, {already_started, Pid2}} = + {ok, Pid2} = erl_boot_server:start_link([Host1, Host2]), + {error, {already_started, Pid2}} = erl_boot_server:start_link([Host1, Host2]), - ?line shutdown(Pid2), + shutdown(Pid2), process_flag(trap_exit, OldFlag), - ?line test_server:timetrap_cancel(Dog), ok. -stop(doc) -> "Tests that no processes are left if a boot server is killed."; +%% Tests that no processes are left if a boot server is killed. stop(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(50)), - ?line [Host1|_] = good_hosts(Config), + [Host1|_] = good_hosts(Config), %% Start a boot server and kill it. Make sure that any helper processes %% dies. - % Make sure the inet_gethost_native server is already started, - % otherwise it will make this test fail: - ?line inet:getaddr(localhost, inet), - ?line Before = processes(), - ?line {ok, Pid} = erl_boot_server:start([Host1]), - ?line New = processes() -- [Pid|Before], - ?line exit(Pid, kill), - ?line receive after 100 -> ok end, - ?line case [P || P <- New, is_process_alive(P)] of - [] -> - ok; - NotKilled -> - test_server:fail({not_killed, NotKilled}) - end, - ?line test_server:timetrap_cancel(Dog), + %% Make sure the inet_gethost_native server is already started, + %% otherwise it will make this test fail: + inet:getaddr(localhost, inet), + Before = processes(), + {ok, Pid} = erl_boot_server:start([Host1]), + New = processes() -- [Pid|Before], + exit(Pid, kill), + receive after 100 -> ok end, + case [P || P <- New, is_process_alive(P)] of + [] -> + ok; + NotKilled -> + ct:fail({not_killed, NotKilled}) + end, ok. -add(doc) -> "Tests the erl_boot_server:add/1 function."; +%% Tests the erl_boot_server:add/1 function. add(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line OldFlag = process_flag(trap_exit, true), - ?line {ok, Pid1} = erl_boot_server:start_link([]), - ?line [] = erl_boot_server:which_slaves(), - ?line [Host1, Host2, Host3|_] = good_hosts(Config), + OldFlag = process_flag(trap_exit, true), + {ok, Pid1} = erl_boot_server:start_link([]), + [] = erl_boot_server:which_slaves(), + [Host1, Host2, Host3|_] = good_hosts(Config), %% Try bad values. - ?line {error, {badarg, {}}} = erl_boot_server:add_slave({}), - ?line {error, {badarg, [atom]}} = erl_boot_server:add_slave([atom]), - ?line BadHost = "bad__host", - ?line {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost), - ?line [] = erl_boot_server:which_slaves(), + {error, {badarg, {}}} = erl_boot_server:add_slave({}), + {error, {badarg, [atom]}} = erl_boot_server:add_slave([atom]), + BadHost = "bad__host", + {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost), + [] = erl_boot_server:which_slaves(), %% Add good host names. - ?line {ok, Ip1} = inet:getaddr(Host1, inet), - ?line {ok, Ip2} = inet:getaddr(Host2, inet), - ?line {ok, Ip3} = inet:getaddr(Host3, inet), - ?line MIp1 = {?all_ones, Ip1}, - ?line MIp2 = {?all_ones, Ip2}, - ?line MIp3 = {?all_ones, Ip3}, - ?line ok = erl_boot_server:add_slave(Host1), - ?line [MIp1] = erl_boot_server:which_slaves(), - ?line ok = erl_boot_server:add_slave(Host2), - ?line M_Ip1_Ip2 = lists:sort([MIp1, MIp2]), - ?line M_Ip1_Ip2 = lists:sort(erl_boot_server:which_slaves()), - ?line ok = erl_boot_server:add_slave(Host3), - ?line M_Ip1_Ip2_Ip3 = lists:sort([MIp3|M_Ip1_Ip2]), - ?line M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(), + {ok, Ip1} = inet:getaddr(Host1, inet), + {ok, Ip2} = inet:getaddr(Host2, inet), + {ok, Ip3} = inet:getaddr(Host3, inet), + MIp1 = {?all_ones, Ip1}, + MIp2 = {?all_ones, Ip2}, + MIp3 = {?all_ones, Ip3}, + ok = erl_boot_server:add_slave(Host1), + [MIp1] = erl_boot_server:which_slaves(), + ok = erl_boot_server:add_slave(Host2), + M_Ip1_Ip2 = lists:sort([MIp1, MIp2]), + M_Ip1_Ip2 = lists:sort(erl_boot_server:which_slaves()), + ok = erl_boot_server:add_slave(Host3), + M_Ip1_Ip2_Ip3 = lists:sort([MIp3|M_Ip1_Ip2]), + M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(), %% Add duplicate names. - ?line ok = erl_boot_server:add_slave(Host3), - ?line M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(), + ok = erl_boot_server:add_slave(Host3), + M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(), %% More bad names. - ?line {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost), - ?line M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(), + {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost), + M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(), %% Cleanup. - ?line shutdown(Pid1), - ?line process_flag(trap_exit, OldFlag), - ?line test_server:timetrap_cancel(Dog), + shutdown(Pid1), + process_flag(trap_exit, OldFlag), ok. -delete(doc) -> "Tests the erl_boot_server:delete/1 function."; +%% Tests the erl_boot_server:delete/1 function. delete(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line OldFlag = process_flag(trap_exit, true), + OldFlag = process_flag(trap_exit, true), - ?line [Host1, Host2, Host3|_] = good_hosts(Config), - ?line {ok, Ip1} = inet:getaddr(Host1, inet), - ?line {ok, Ip2} = inet:getaddr(Host2, inet), - ?line {ok, Ip3} = inet:getaddr(Host3, inet), - ?line MIp1 = {?all_ones, Ip1}, - ?line MIp2 = {?all_ones, Ip2}, - ?line MIp3 = {?all_ones, Ip3}, + [Host1, Host2, Host3|_] = good_hosts(Config), + {ok, Ip1} = inet:getaddr(Host1, inet), + {ok, Ip2} = inet:getaddr(Host2, inet), + {ok, Ip3} = inet:getaddr(Host3, inet), + MIp1 = {?all_ones, Ip1}, + MIp2 = {?all_ones, Ip2}, + MIp3 = {?all_ones, Ip3}, - ?line {ok, Pid1} = erl_boot_server:start_link([Host1, Host2, Host3]), - ?line M_Ip123 = lists:sort([MIp1, MIp2, MIp3]), - ?line M_Ip123 = erl_boot_server:which_slaves(), + {ok, Pid1} = erl_boot_server:start_link([Host1, Host2, Host3]), + M_Ip123 = lists:sort([MIp1, MIp2, MIp3]), + M_Ip123 = erl_boot_server:which_slaves(), %% Do some bad attempts and check that the list of slaves is intact. - ?line {error, {badarg, {}}} = erl_boot_server:delete_slave({}), - ?line {error, {badarg, [atom]}} = erl_boot_server:delete_slave([atom]), - ?line BadHost = "bad__host", - ?line {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost), - ?line M_Ip123 = erl_boot_server:which_slaves(), + {error, {badarg, {}}} = erl_boot_server:delete_slave({}), + {error, {badarg, [atom]}} = erl_boot_server:delete_slave([atom]), + BadHost = "bad__host", + {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost), + M_Ip123 = erl_boot_server:which_slaves(), %% Delete Host2 and make sure it's gone. - ?line ok = erl_boot_server:delete_slave(Host2), - ?line M_Ip13 = lists:sort([MIp1, MIp3]), - ?line M_Ip13 = erl_boot_server:which_slaves(), - - ?line ok = erl_boot_server:delete_slave(Host1), - ?line [MIp3] = erl_boot_server:which_slaves(), - ?line ok = erl_boot_server:delete_slave(Host1), - ?line [MIp3] = erl_boot_server:which_slaves(), - - ?line {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost), - ?line [MIp3] = erl_boot_server:which_slaves(), - - ?line ok = erl_boot_server:delete_slave(Ip3), - ?line [] = erl_boot_server:which_slaves(), - ?line ok = erl_boot_server:delete_slave(Ip3), - ?line [] = erl_boot_server:which_slaves(), - - ?line shutdown(Pid1), - ?line process_flag(trap_exit, OldFlag), - ?line test_server:timetrap_cancel(Dog), + ok = erl_boot_server:delete_slave(Host2), + M_Ip13 = lists:sort([MIp1, MIp3]), + M_Ip13 = erl_boot_server:which_slaves(), + + ok = erl_boot_server:delete_slave(Host1), + [MIp3] = erl_boot_server:which_slaves(), + ok = erl_boot_server:delete_slave(Host1), + [MIp3] = erl_boot_server:which_slaves(), + + {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost), + [MIp3] = erl_boot_server:which_slaves(), + + ok = erl_boot_server:delete_slave(Ip3), + [] = erl_boot_server:which_slaves(), + ok = erl_boot_server:delete_slave(Ip3), + [] = erl_boot_server:which_slaves(), + + shutdown(Pid1), + process_flag(trap_exit, OldFlag), ok. -responses(doc) -> "Tests erl_boot_server responses to slave requests."; +%% Tests erl_boot_server responses to slave requests. responses(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(30)), - ?line process_flag(trap_exit, true), + process_flag(trap_exit, true), %% Copy from inet_boot.hrl EBOOT_PORT = 4368, EBOOT_REQUEST = "EBOOTQ", EBOOT_REPLY = "EBOOTR", - ?line {ok,Host} = inet:gethostname(), - ?line {ok,Ip} = inet:getaddr(Host, inet), + {ok,Host} = inet:gethostname(), + {ok,Ip} = inet:getaddr(Host, inet), ThisVer = erlang:system_info(version), - ?line {ok,BootPid} = erl_boot_server:start_link([Host]), + {ok,BootPid} = erl_boot_server:start_link([Host]), %% Send junk - ?line S1 = open_udp(), - ?line prim_inet:sendto(S1, Ip, EBOOT_PORT, ["0"]), + S1 = open_udp(), + prim_inet:sendto(S1, Ip, EBOOT_PORT, ["0"]), receive What -> - ?line close_udp(S1), - ?line ?t:fail({"got unexpected response",What}) + close_udp(S1), + ct:fail({"got unexpected response",What}) after 100 -> ok end, %% Req from a slave with same erlang vsn. - ?line S2 = open_udp(), - ?line prim_inet:sendto(S2, Ip, EBOOT_PORT, [EBOOT_REQUEST,ThisVer]), + S2 = open_udp(), + prim_inet:sendto(S2, Ip, EBOOT_PORT, [EBOOT_REQUEST,ThisVer]), receive {udp,S2,Ip,_Port1,Resp1} -> - ?line close_udp(S2), - ?line EBOOT_REPLY = string:substr(Resp1, 1, length(EBOOT_REPLY)), - ?line Rest1 = string:substr(Resp1, length(EBOOT_REPLY)+1, length(Resp1)), - ?line [_,_,_ | ThisVer] = Rest1 + close_udp(S2), + EBOOT_REPLY = string:substr(Resp1, 1, length(EBOOT_REPLY)), + Rest1 = string:substr(Resp1, length(EBOOT_REPLY)+1, length(Resp1)), + [_,_,_ | ThisVer] = Rest1 after 2000 -> - ?line close_udp(S2), - ?line ?t:fail("no boot server response; same vsn") + close_udp(S2), + ct:fail("no boot server response; same vsn") end, - + %% Req from a slave with other erlang vsn. - ?line S3 = open_udp(), - ?line prim_inet:sendto(S3, Ip, EBOOT_PORT, [EBOOT_REQUEST,"1.0"]), + S3 = open_udp(), + prim_inet:sendto(S3, Ip, EBOOT_PORT, [EBOOT_REQUEST,"1.0"]), receive Anything -> - ?line close_udp(S3), - ?line ?t:fail({"got unexpected response",Anything}) + close_udp(S3), + ct:fail({"got unexpected response",Anything}) after 100 -> ok end, %% Kill the boot server and wait for it to disappear. - ?line unlink(BootPid), - ?line BootPidMref = erlang:monitor(process, BootPid), - ?line exit(BootPid, kill), + unlink(BootPid), + BootPidMref = erlang:monitor(process, BootPid), + exit(BootPid, kill), receive {'DOWN',BootPidMref,_,_,_} -> ok end, - ?line {ok,BootPid2} = erl_boot_server:start_link(["127.0.0.1"]), + {ok,BootPid2} = erl_boot_server:start_link(["127.0.0.1"]), %% Req from slave with invalid ip address. - ?line S4 = open_udp(), + S4 = open_udp(), Ret = case Ip of {127,0,0,1} -> {comment,"IP address for this host is 127.0.0.1"}; _ -> - ?line prim_inet:sendto(S4, Ip, EBOOT_PORT, - [EBOOT_REQUEST,ThisVer]), + prim_inet:sendto(S4, Ip, EBOOT_PORT, + [EBOOT_REQUEST,ThisVer]), receive Huh -> - ?line close_udp(S4), - ?line ?t:fail({"got unexpected response",Huh}) + close_udp(S4), + ct:fail({"got unexpected response",Huh}) after 100 -> ok end end, - ?line unlink(BootPid2), - ?line exit(BootPid2, kill), + unlink(BootPid2), + exit(BootPid2, kill), %% Now wait for any late unexpected messages. receive Whatever -> - ?line ?t:fail({unexpected_message,Whatever}) + ct:fail({unexpected_message,Whatever}) after 4000 -> - ?line close_udp(S1), - ?line close_udp(S3), - ?line close_udp(S4), + close_udp(S1), + close_udp(S3), + close_udp(S4), ok end, - ?line test_server:timetrap_cancel(Dog), Ret. shutdown(Pid) -> @@ -335,7 +325,7 @@ shutdown(Pid) -> after 1000 -> %% The timeout used to be 1 ms, which could be too short time for the %% SMP emulator on a slow computer with one CPU. - test_server:fail(shutdown) + ct:fail(shutdown) end. good_hosts(_Config) -> @@ -347,10 +337,10 @@ good_hosts(_Config) -> [GoodHost1, GoodHost2, GoodHost3]. open_udp() -> - ?line {ok, S} = prim_inet:open(udp, inet, dgram), - ?line ok = prim_inet:setopts(S, [{mode,list},{active,true}, - {deliver,term},{broadcast,true}]), - ?line {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0), + {ok, S} = prim_inet:open(udp, inet, dgram), + ok = prim_inet:setopts(S, [{mode,list},{active,true}, + {deliver,term},{broadcast,true}]), + {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0), S. close_udp(S) -> diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index 2f73ab170a..e34b4d77d2 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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. @@ -19,13 +19,15 @@ %% -module(erl_distribution_SUITE). -%-define(line_trace, 1). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). --export([tick/1, tick_change/1, illegal_nodenames/1, hidden_node/1, +-export([tick/1, tick_change/1, + nodenames/1, hostnames/1, + illegal_nodenames/1, hidden_node/1, + setopts/1, table_waste/1, net_setuptime/1, inet_dist_options_options/1, @@ -43,6 +45,8 @@ -export([get_socket_priorities/0, tick_cli_test/1, tick_cli_test1/1, tick_serv_test/2, tick_serv_test1/1, + run_remote_test/1, + setopts_do/2, keep_conn/1, time_ping/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -51,7 +55,6 @@ -export([pinger/1]). - -define(DUMMY_NODE,dummy@test01). %%----------------------------------------------------------------- @@ -61,10 +64,13 @@ %% erl -sname master -rsh ctrsh %%----------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,4}}]. all() -> - [tick, tick_change, illegal_nodenames, hidden_node, + [tick, tick_change, nodenames, hostnames, illegal_nodenames, + hidden_node, setopts, table_waste, net_setuptime, inet_dist_options_options, {group, monitor_nodes}]. @@ -89,29 +95,28 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - +init_per_testcase(TC, Config) when TC == hostnames; + TC == nodenames -> + file:make_dir("hostnames_nodedir"), + file:write_file("hostnames_nodedir/ignore_core_files",""), + Config; init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog=?t:timetrap(?t:minutes(4)), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. -tick(suite) -> []; -tick(doc) -> []; tick(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(120)), PaDir = filename:dirname(code:which(erl_distribution_SUITE)), - + %% First check that the normal case is OK! - ?line {ok, Node} = start_node(dist_test, "-pa " ++ PaDir), + {ok, Node} = start_node(dist_test, "-pa " ++ PaDir), rpc:call(Node, erl_distribution_SUITE, tick_cli_test, [node()]), - + erlang:monitor_node(Node, true), receive {nodedown, Node} -> - test_server:fail("nodedown from other node") + ct:fail("nodedown from other node") after 30000 -> erlang:monitor_node(Node, false), stop_node(Node) @@ -129,20 +134,20 @@ tick(Config) when is_list(Config) -> %% Set the ticktime on the server node to 100 secs so the server %% node doesn't tick the client node within the interval ... - ?line {ok, ServNode} = start_node(dist_test_server, - "-kernel net_ticktime 100 " - "-pa " ++ PaDir), + {ok, ServNode} = start_node(dist_test_server, + "-kernel net_ticktime 100 " + "-pa " ++ PaDir), rpc:call(ServNode, erl_distribution_SUITE, tick_serv_test, [Node, node()]), - ?line {ok, _} = start_node(dist_test, - "-kernel net_ticktime 12 " - "-pa " ++ PaDir), + {ok, _} = start_node(dist_test, + "-kernel net_ticktime 12 " + "-pa " ++ PaDir), rpc:call(Node, erl_distribution_SUITE, tick_cli_test, [ServNode]), - + spawn_link(erl_distribution_SUITE, keep_conn, [Node]), {tick_serv, ServNode} ! {i_want_the_result, self()}, - + monitor_node(ServNode, true), monitor_node(Node, true), @@ -154,56 +159,145 @@ tick(Config) when is_list(Config) -> {tick_test, Error} -> stop_node(ServNode), stop_node(Node), - test_server:fail(Error); + ct:fail(Error); {nodedown, Node} -> stop_node(ServNode), - test_server:fail("client node died"); + ct:fail("client node died"); {nodedown, ServNode} -> stop_node(Node), - test_server:fail("server node died") + ct:fail("server node died") end, - ?line test_server:timetrap_cancel(Dog), ok. -table_waste(doc) -> - ["Checks that pinging nonexistyent nodes does not waste space in distribution table"]; -table_waste(suite) -> - []; +%% Checks that pinging nonexistyent nodes does not waste space in distribution table. table_waste(Config) when is_list(Config) -> - ?line {ok, HName} = inet:gethostname(), + {ok, HName} = inet:gethostname(), F = fun(0,_F) -> []; (N,F) -> - ?line Name = list_to_atom("erl_distribution_"++integer_to_list(N)++ - "@"++HName), - ?line pang = net_adm:ping(Name), - ?line F(N-1,F) + Name = list_to_atom("erl_distribution_"++integer_to_list(N)++ + "@"++HName), + pang = net_adm:ping(Name), + F(N-1,F) end, - ?line F(256,F), - ?line {ok, N} = start_node(erl_distribution_300,""), - ?line stop_node(N), + F(256,F), + {ok, N} = start_node(erl_distribution_300,""), + stop_node(N), ok. - - -illegal_nodenames(doc) -> - ["Test that pinging an illegal nodename does not kill the node"]; -illegal_nodenames(suite) -> - []; +%% Test that starting nodes with different legal name part works, and that illegal +%% ones are filtered +nodenames(Config) when is_list(Config) -> + legal("a1@b"), + legal("a-1@b"), + legal("a_1@b"), + + illegal("cdé@a"), + illegal("te欢st@a"). + +%% Test that starting nodes with different legal host part works, and that illegal +%% ones are filtered +hostnames(Config) when is_list(Config) -> + Host = gethostname(), + legal([$a,$@|atom_to_list(Host)]), + legal("1@b1"), + legal("b@b1-c"), + legal("c@b1_c"), + legal("d@b1#c"), + legal("f@::1"), + legal("g@1:bc3:4e3f:f20:0:1"), + + case file:native_name_encoding() of + latin1 -> ignore; + _ -> legal("e@b1é") + end, + long_hostnames(net_kernel:longnames()), + + illegal("h@testالع"), + illegal("i@языtest"), + illegal("j@te欢st"). + +long_hostnames(true) -> + legal("[email protected]"), + legal("[email protected]"), + legal("[email protected]_c.d"), + legal("[email protected]"), + legal("[email protected]"); +long_hostnames(false) -> + illegal("[email protected]"). + +legal(Name) -> + case test_node(Name) of + started -> + ok; + not_started -> + ct:fail("no ~p node started", [Name]) + end. + +illegal(Name) -> + case test_node(Name, true) of + not_started -> + ok; + started -> + ct:fail("~p node started with illegal name", [Name]) + end. + +test_node(Name) -> + test_node(Name, false). +test_node(Name, Illigal) -> + ProgName = atom_to_list(lib:progname()), + Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++ + " -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++ + case Illigal of + true -> + " -eval \"timer:sleep(10000),init:stop().\""; + false -> + "" + end, + net_kernel:monitor_nodes(true), + BinCommand = unicode:characters_to_binary(Command, utf8), + Prt = open_port({spawn, BinCommand}, [stream,{cd,"hostnames_nodedir"}]), + Node = list_to_atom(Name), + receive + {nodeup, Node} -> + net_kernel:monitor_nodes(false), + slave:stop(Node), + started + after 5000 -> + net_kernel:monitor_nodes(false), + not_started + end. + +long_or_short() -> + case net_kernel:longnames() of + true -> " -name "; + false -> " -sname " + end. + +% get the localhost's name, depending on the using name policy +gethostname() -> + Hostname = case net_kernel:longnames() of + true-> + net_adm:localhost(); + _-> + {ok, Name}=inet:gethostname(), + Name + end, + list_to_atom(Hostname). + +%% Test that pinging an illegal nodename does not kill the node. illegal_nodenames(Config) when is_list(Config) -> - ?line Dog=?t:timetrap(?t:minutes(2)), PaDir = filename:dirname(code:which(erl_distribution_SUITE)), - ?line {ok, Node}=start_node(illegal_nodenames, "-pa " ++ PaDir), + {ok, Node}=start_node(illegal_nodenames, "-pa " ++ PaDir), monitor_node(Node, true), - ?line RPid=rpc:call(Node, erlang, spawn, - [?MODULE, pinger, [self()]]), + RPid=rpc:call(Node, erlang, spawn, + [?MODULE, pinger, [self()]]), receive {RPid, pinged} -> ok; {nodedown, Node} -> - ?t:fail("Remote node died.") + ct:fail("Remote node died.") end, stop_node(Node), - ?t:timetrap_cancel(Dog), ok. pinger(Starter) -> @@ -213,7 +307,7 @@ pinger(Starter) -> ok. -net_setuptime(doc) -> ["Test that you can set the net_setuptime properly"]; +%% Test that you can set the net_setuptime properly. net_setuptime(Config) when is_list(Config) -> %% In this test case, we reluctantly accept shorter times than the given %% setup time, because the connection attempt can end in a @@ -221,28 +315,28 @@ net_setuptime(Config) when is_list(Config) -> Res0 = do_test_setuptime("2"), io:format("Res0 = ~p", [Res0]), - ?line true = (Res0 =< 4000), + true = (Res0 =< 4000), Res1 = do_test_setuptime("0.3"), io:format("Res1 = ~p", [Res1]), - ?line true = (Res1 =< 500), + true = (Res1 =< 500), ok. do_test_setuptime(Setuptime) when is_list(Setuptime) -> - ?line PaDir = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = start_node(dist_setuptime_test, "-pa " ++ PaDir ++ - " -kernel net_setuptime " ++ Setuptime), - ?line Res = rpc:call(Node,?MODULE,time_ping,[?DUMMY_NODE]), - ?line stop_node(Node), + PaDir = filename:dirname(code:which(?MODULE)), + {ok, Node} = start_node(dist_setuptime_test, "-pa " ++ PaDir ++ + " -kernel net_setuptime " ++ Setuptime), + Res = rpc:call(Node,?MODULE,time_ping,[?DUMMY_NODE]), + stop_node(Node), Res. time_ping(Node) -> T0 = erlang:monotonic_time(), pang = net_adm:ping(Node), T1 = erlang:monotonic_time(), - erlang:convert_time_unit(T1 - T0, native, milli_seconds). + erlang:convert_time_unit(T1 - T0, native, millisecond). %% Keep the connection with the client node up. -%% This is neccessary as the client node runs with much shorter +%% This is necessary as the client node runs with much shorter %% tick time !! keep_conn(Node) -> sleep(1), @@ -283,7 +377,7 @@ tick_cli_test1(Node) -> receive {whats_the_result, From} -> Diff = erlang:convert_time_unit(T2-T1, native, - milli_seconds), + millisecond), case Diff of T when T > 8000, T < 16000 -> From ! {tick_test, T}; @@ -295,161 +389,319 @@ tick_cli_test1(Node) -> end end. +setopts(Config) when is_list(Config) -> + register(setopts_regname, self()), + [N1,N2,N3,N4] = get_nodenames(4, setopts), + + {_N1F,Port1} = start_node_unconnected(N1, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), "1", "ping"]), + 0 = wait_for_port_exit(Port1), + + {_N2F,Port2} = start_node_unconnected(N2, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), "2", "ping"]), + 0 = wait_for_port_exit(Port2), + + {ok, LSock} = gen_tcp:listen(0, [{packet,2}, {active,false}]), + {ok, LTcpPort} = inet:port(LSock), -tick_change(doc) -> ["OTP-4255"]; -tick_change(suite) -> []; + {N3F,Port3} = start_node_unconnected(N3, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), + "1", integer_to_list(LTcpPort)]), + wait_and_connect(LSock, N3F, Port3), + 0 = wait_for_port_exit(Port3), + + {N4F,Port4} = start_node_unconnected(N4, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), + "2", integer_to_list(LTcpPort)]), + wait_and_connect(LSock, N4F, Port4), + 0 = wait_for_port_exit(Port4), + + ok. + +wait_and_connect(LSock, NodeName, NodePort) -> + {ok, Sock} = gen_tcp:accept(LSock), + {ok, "Connect please"} = gen_tcp:recv(Sock, 0), + flush_from_port(NodePort), + pong = net_adm:ping(NodeName), + gen_tcp:send(Sock, "Connect done"), + gen_tcp:close(Sock). + + +flush_from_port(Port) -> + flush_from_port(Port, 10). + +flush_from_port(Port, Timeout) -> + receive + {Port,{data,String}} -> + io:format("~p: ~s\n", [Port, String]), + flush_from_port(Port, Timeout) + after Timeout -> + timeout + end. + +wait_for_port_exit(Port) -> + case (receive M -> M end) of + {Port,{exit_status,Status}} -> + Status; + {Port,{data,String}} -> + io:format("~p: ~s\n", [Port, String]), + wait_for_port_exit(Port) + end. + +run_remote_test([FuncStr, TestNodeStr | Args]) -> + Status = try + io:format("Node ~p started~n", [node()]), + TestNode = list_to_atom(TestNodeStr), + io:format("Node ~p spawning function ~p~n", [node(), FuncStr]), + {Pid,Ref} = spawn_monitor(?MODULE, list_to_atom(FuncStr), [TestNode, Args]), + io:format("Node ~p waiting for function ~p~n", [node(), FuncStr]), + receive + {'DOWN', Ref, process, Pid, normal} -> + 0; + Other -> + io:format("Node ~p got unexpected msg: ~p\n",[node(), Other]), + 1 + end + catch + C:E -> + io:format("Node ~p got EXCEPTION ~p:~p\nat ~p\n", + [node(), C, E, erlang:get_stacktrace()]), + 2 + end, + io:format("Node ~p doing halt(~p).\n",[node(), Status]), + erlang:halt(Status). + +% Do the actual test on the remote node +setopts_do(TestNode, [OptNr, ConnectData]) -> + [] = nodes(), + {Opt, Val} = opt_from_nr(OptNr), + ok = net_kernel:setopts(new, [{Opt, Val}]), + + [] = nodes(), + {error, noconnection} = net_kernel:getopts(TestNode, [Opt]), + + case ConnectData of + "ping" -> % We connect + net_adm:ping(TestNode); + TcpPort -> % Other connect + {ok, Sock} = gen_tcp:connect("localhost", list_to_integer(TcpPort), + [{active,false},{packet,2}]), + ok = gen_tcp:send(Sock, "Connect please"), + {ok, "Connect done"} = gen_tcp:recv(Sock, 0), + gen_tcp:close(Sock) + end, + [TestNode] = nodes(), + {ok, [{Opt,Val}]} = net_kernel:getopts(TestNode, [Opt]), + {error, noconnection} = net_kernel:getopts('pixie@fairyland', [Opt]), + + NewVal = change_val(Val), + ok = net_kernel:setopts(TestNode, [{Opt, NewVal}]), + {ok, [{Opt,NewVal}]} = net_kernel:getopts(TestNode, [Opt]), + + ok = net_kernel:setopts(TestNode, [{Opt, Val}]), + {ok, [{Opt,Val}]} = net_kernel:getopts(TestNode, [Opt]), + + ok. + +opt_from_nr("1") -> {nodelay, true}; +opt_from_nr("2") -> {nodelay, false}. + +change_val(true) -> false; +change_val(false) -> true. + +start_node_unconnected(Name, Mod, Func, Args) -> + FullName = full_node_name(Name), + CmdLine = mk_node_cmdline(Name,Mod,Func,Args), + io:format("Starting node ~p: ~s~n", [FullName, CmdLine]), + case open_port({spawn, CmdLine}, [exit_status]) of + Port when is_port(Port) -> + {FullName, Port}; + Error -> + exit({failed_to_start_node, FullName, Error}) + end. + +full_node_name(PreName) -> + HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end, + atom_to_list(node())), + list_to_atom(atom_to_list(PreName) ++ HostSuffix). + +mk_node_cmdline(Name,Mod,Func,Args) -> + Static = "-noinput", + Pa = filename:dirname(code:which(?MODULE)), + Prog = case catch init:get_argument(progname) of + {ok,[[P]]} -> P; + _ -> exit(no_progname_argument_found) + end, + NameSw = case net_kernel:longnames() of + false -> "-sname "; + true -> "-name "; + _ -> exit(not_distributed_node) + end, + {ok, Pwd} = file:get_cwd(), + NameStr = atom_to_list(Name), + Prog ++ " " + ++ Static ++ " " + ++ NameSw ++ " " ++ NameStr + ++ " -pa " ++ Pa + ++ " -env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr + ++ " -setcookie " ++ atom_to_list(erlang:get_cookie()) + ++ " -run " ++ atom_to_list(Mod) ++ " " ++ atom_to_list(Func) + ++ " " ++ string:join(Args, " "). + + +%% OTP-4255. tick_change(Config) when is_list(Config) -> - ?line PaDir = filename:dirname(code:which(?MODULE)), - ?line [BN, CN] = get_nodenames(2, tick_change), - ?line DefaultTT = net_kernel:get_net_ticktime(), - ?line unchanged = net_kernel:set_net_ticktime(DefaultTT, 60), - ?line case DefaultTT of - I when is_integer(I) -> ?line ok; - _ -> ?line ?t:fail(DefaultTT) - end, - - % In case other nodes are connected + PaDir = filename:dirname(code:which(?MODULE)), + [BN, CN] = get_nodenames(2, tick_change), + DefaultTT = net_kernel:get_net_ticktime(), + unchanged = net_kernel:set_net_ticktime(DefaultTT, 60), + case DefaultTT of + I when is_integer(I) -> ok; + _ -> ct:fail(DefaultTT) + end, + + %% In case other nodes are connected case nodes(connected) of - [] -> ?line net_kernel:set_net_ticktime(10, 0); - _ -> ?line rpc:multicall(nodes([this, connected]), net_kernel, - set_net_ticktime, [10, 5]) + [] -> net_kernel:set_net_ticktime(10, 0); + _ -> rpc:multicall(nodes([this, connected]), net_kernel, + set_net_ticktime, [10, 5]) end, - ?line wait_until(fun () -> 10 == net_kernel:get_net_ticktime() end), - ?line {ok, B} = start_node(BN, "-kernel net_ticktime 10 -pa " ++ PaDir), - ?line {ok, C} = start_node(CN, "-kernel net_ticktime 10 -hidden -pa " - ++ PaDir), + wait_until(fun () -> 10 == net_kernel:get_net_ticktime() end), + {ok, B} = start_node(BN, "-kernel net_ticktime 10 -pa " ++ PaDir), + {ok, C} = start_node(CN, "-kernel net_ticktime 10 -hidden -pa " + ++ PaDir), - ?line OTE = process_flag(trap_exit, true), + OTE = process_flag(trap_exit, true), case catch begin - ?line run_tick_change_test(B, C, 10, 1, PaDir), - ?line run_tick_change_test(B, C, 1, 10, PaDir) + run_tick_change_test(B, C, 10, 1, PaDir), + run_tick_change_test(B, C, 1, 10, PaDir) end of {'EXIT', Reason} -> - ?line stop_node(B), - ?line stop_node(C), + stop_node(B), + stop_node(C), %% In case other nodes are connected case nodes(connected) of - [] -> ?line net_kernel:set_net_ticktime(DefaultTT, 0); - _ -> ?line rpc:multicall(nodes([this, connected]), net_kernel, - set_net_ticktime, [DefaultTT, 10]) + [] -> net_kernel:set_net_ticktime(DefaultTT, 0); + _ -> rpc:multicall(nodes([this, connected]), net_kernel, + set_net_ticktime, [DefaultTT, 10]) end, - ?line wait_until(fun () -> - DefaultTT == net_kernel:get_net_ticktime() - end), - ?line process_flag(trap_exit, OTE), - ?t:fail(Reason); + wait_until(fun () -> + DefaultTT == net_kernel:get_net_ticktime() + end), + process_flag(trap_exit, OTE), + ct:fail(Reason); _ -> ok end, - ?line process_flag(trap_exit, OTE), - ?line stop_node(B), - ?line stop_node(C), + process_flag(trap_exit, OTE), + stop_node(B), + stop_node(C), - % In case other nodes are connected + %% In case other nodes are connected case nodes(connected) of - [] -> ?line net_kernel:set_net_ticktime(DefaultTT, 0); - _ -> ?line rpc:multicall(nodes([this, connected]), net_kernel, - set_net_ticktime, [DefaultTT, 5]) + [] -> net_kernel:set_net_ticktime(DefaultTT, 0); + _ -> rpc:multicall(nodes([this, connected]), net_kernel, + set_net_ticktime, [DefaultTT, 5]) end, - ?line wait_until(fun () -> DefaultTT == net_kernel:get_net_ticktime() end), - ?line ok. + wait_until(fun () -> DefaultTT == net_kernel:get_net_ticktime() end), + ok. wait_for_nodedowns(Tester, Ref) -> receive {nodedown, Node} -> - ?t:format("~p~n", [{node(), {nodedown, Node}}]), - ?line Tester ! {Ref, {node(), {nodedown, Node}}} + io:format("~p~n", [{node(), {nodedown, Node}}]), + Tester ! {Ref, {node(), {nodedown, Node}}} end, wait_for_nodedowns(Tester, Ref). run_tick_change_test(B, C, PrevTT, TT, PaDir) -> - ?line [DN, EN] = get_nodenames(2, tick_change), - - ?line Tester = self(), - ?line Ref = make_ref(), - ?line MonitorNodes = fun (Nodes) -> - ?line lists:foreach( - fun (N) -> - ?line monitor_node(N,true) - end, - Nodes), - wait_for_nodedowns(Tester, Ref) - end, - - ?line {ok, D} = start_node(DN, "-kernel net_ticktime " - ++ integer_to_list(PrevTT) ++ " -pa " ++ PaDir), - - ?line NMA = spawn_link(fun () -> MonitorNodes([B, C, D]) end), - ?line NMB = spawn_link(B, fun () -> MonitorNodes([node(), C, D]) end), - ?line NMC = spawn_link(C, fun () -> MonitorNodes([node(), B, D]) end), - - ?line MaxTT = case PrevTT > TT of - true -> ?line PrevTT; - false -> ?line TT - end, + [DN, EN] = get_nodenames(2, tick_change), + + Tester = self(), + Ref = make_ref(), + MonitorNodes = fun (Nodes) -> + lists:foreach( + fun (N) -> + monitor_node(N,true) + end, + Nodes), + wait_for_nodedowns(Tester, Ref) + end, + + {ok, D} = start_node(DN, "-kernel net_ticktime " + ++ integer_to_list(PrevTT) ++ " -pa " ++ PaDir), + + NMA = spawn_link(fun () -> MonitorNodes([B, C, D]) end), + NMB = spawn_link(B, fun () -> MonitorNodes([node(), C, D]) end), + NMC = spawn_link(C, fun () -> MonitorNodes([node(), B, D]) end), + + MaxTT = case PrevTT > TT of + true -> PrevTT; + false -> TT + end, - ?line CheckResult = make_ref(), - ?line spawn_link(fun () -> - receive - after (25 + MaxTT)*1000 -> - Tester ! CheckResult - end - end), + CheckResult = make_ref(), + spawn_link(fun () -> + receive + after (25 + MaxTT)*1000 -> + Tester ! CheckResult + end + end), - % In case other nodes than these are connected + %% In case other nodes than these are connected case nodes(connected) -- [B, C, D] of - [] -> ?line ok; - OtherNodes -> ?line rpc:multicall(OtherNodes, net_kernel, - set_net_ticktime, [TT, 20]) + [] -> ok; + OtherNodes -> rpc:multicall(OtherNodes, net_kernel, + set_net_ticktime, [TT, 20]) end, - ?line change_initiated = net_kernel:set_net_ticktime(TT,20), - ?line {ongoing_change_to,_} = net_kernel:set_net_ticktime(TT,20), - ?line sleep(3), - ?line change_initiated = rpc:call(B,net_kernel,set_net_ticktime,[TT,15]), - ?line sleep(7), - ?line change_initiated = rpc:call(C,net_kernel,set_net_ticktime,[TT,10]), - - ?line {ok, E} = start_node(EN, "-kernel net_ticktime " - ++ integer_to_list(TT) ++ " -pa " ++ PaDir), - ?line NME = spawn_link(E, fun () -> MonitorNodes([node(), B, C, D]) end), - ?line NMA2 = spawn_link(fun () -> MonitorNodes([E]) end), - ?line NMB2 = spawn_link(B, fun () -> MonitorNodes([E]) end), - ?line NMC2 = spawn_link(C, fun () -> MonitorNodes([E]) end), - - receive CheckResult -> ?line ok end, - - ?line unlink(NMA), exit(NMA, kill), - ?line unlink(NMB), exit(NMB, kill), - ?line unlink(NMC), exit(NMC, kill), - ?line unlink(NME), exit(NME, kill), - ?line unlink(NMA2), exit(NMA2, kill), - ?line unlink(NMB2), exit(NMB2, kill), - ?line unlink(NMC2), exit(NMC2, kill), + change_initiated = net_kernel:set_net_ticktime(TT,20), + {ongoing_change_to,_} = net_kernel:set_net_ticktime(TT,20), + sleep(3), + change_initiated = rpc:call(B,net_kernel,set_net_ticktime,[TT,15]), + sleep(7), + change_initiated = rpc:call(C,net_kernel,set_net_ticktime,[TT,10]), + + {ok, E} = start_node(EN, "-kernel net_ticktime " + ++ integer_to_list(TT) ++ " -pa " ++ PaDir), + NME = spawn_link(E, fun () -> MonitorNodes([node(), B, C, D]) end), + NMA2 = spawn_link(fun () -> MonitorNodes([E]) end), + NMB2 = spawn_link(B, fun () -> MonitorNodes([E]) end), + NMC2 = spawn_link(C, fun () -> MonitorNodes([E]) end), + + receive CheckResult -> ok end, + + unlink(NMA), exit(NMA, kill), + unlink(NMB), exit(NMB, kill), + unlink(NMC), exit(NMC, kill), + unlink(NME), exit(NME, kill), + unlink(NMA2), exit(NMA2, kill), + unlink(NMB2), exit(NMB2, kill), + unlink(NMC2), exit(NMC2, kill), %% The node not changing ticktime should have been disconnected from the %% other nodes - receive {Ref, {Node, {nodedown, D}}} when Node == node() -> ?line ok - after 0 -> ?line exit({?LINE, no_nodedown}) + receive {Ref, {Node, {nodedown, D}}} when Node == node() -> ok + after 0 -> exit({?LINE, no_nodedown}) end, - receive {Ref, {B, {nodedown, D}}} -> ?line ok - after 0 -> ?line exit({?LINE, no_nodedown}) + receive {Ref, {B, {nodedown, D}}} -> ok + after 0 -> exit({?LINE, no_nodedown}) end, - receive {Ref, {C, {nodedown, D}}} -> ?line ok - after 0 -> ?line exit({?LINE, no_nodedown}) + receive {Ref, {C, {nodedown, D}}} -> ok + after 0 -> exit({?LINE, no_nodedown}) end, - receive {Ref, {E, {nodedown, D}}} -> ?line ok - after 0 -> ?line exit({?LINE, no_nodedown}) + receive {Ref, {E, {nodedown, D}}} -> ok + after 0 -> exit({?LINE, no_nodedown}) end, %% No other connections should have been broken receive {Ref, Reason} -> - ?line stop_node(E), - ?line exit({?LINE, Reason}); + stop_node(E), + exit({?LINE, Reason}); {'EXIT', Pid, Reason} when Pid == NMA; Pid == NMB; Pid == NMC; @@ -457,70 +709,65 @@ run_tick_change_test(B, C, PrevTT, TT, PaDir) -> Pid == NMA2; Pid == NMB2; Pid == NMC2 -> - ?line stop_node(E), + stop_node(E), - ?line exit({?LINE, {node(Pid), Reason}}) + exit({?LINE, {node(Pid), Reason}}) after 0 -> - ?line TT = net_kernel:get_net_ticktime(), - ?line TT = rpc:call(B, net_kernel, get_net_ticktime, []), - ?line TT = rpc:call(C, net_kernel, get_net_ticktime, []), - ?line TT = rpc:call(E, net_kernel, get_net_ticktime, []), - ?line stop_node(E), - ?line ok + TT = net_kernel:get_net_ticktime(), + TT = rpc:call(B, net_kernel, get_net_ticktime, []), + TT = rpc:call(C, net_kernel, get_net_ticktime, []), + TT = rpc:call(E, net_kernel, get_net_ticktime, []), + stop_node(E), + ok end. %% %% Basic tests of hidden node. %% -hidden_node(doc) -> - ["Basic test of hidden node"]; -hidden_node(suite) -> - []; +%% Basic test of hidden node. hidden_node(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(40)), PaDir = filename:dirname(code:which(?MODULE)), VArgs = "-pa " ++ PaDir, HArgs = "-hidden -pa " ++ PaDir, - ?line {ok, V} = start_node(visible_node, VArgs), + {ok, V} = start_node(visible_node, VArgs), VMN = start_monitor_nodes_proc(V), - ?line {ok, H} = start_node(hidden_node, HArgs), - % Connect visible_node -> hidden_node + {ok, H} = start_node(hidden_node, HArgs), + %% Connect visible_node -> hidden_node connect_nodes(V, H), test_nodes(V, H), stop_node(H), sleep(5), check_monitor_nodes_res(VMN, H), stop_node(V), - ?line {ok, H} = start_node(hidden_node, HArgs), + {ok, H} = start_node(hidden_node, HArgs), HMN = start_monitor_nodes_proc(H), - ?line {ok, V} = start_node(visible_node, VArgs), - % Connect hidden_node -> visible_node + {ok, V} = start_node(visible_node, VArgs), + %% Connect hidden_node -> visible_node connect_nodes(H, V), test_nodes(V, H), stop_node(V), sleep(5), check_monitor_nodes_res(HMN, V), stop_node(H), - ?line ?t:timetrap_cancel(Dog), ok. connect_nodes(A, B) -> - % Check that they haven't already connected. - ?line false = lists:member(A, rpc:call(B, erlang, nodes, [connected])), - ?line false = lists:member(B, rpc:call(A, erlang, nodes, [connected])), - % Connect them. - ?line pong = rpc:call(A, net_adm, ping, [B]). - + %% Check that they haven't already connected. + false = lists:member(A, rpc:call(B, erlang, nodes, [connected])), + false = lists:member(B, rpc:call(A, erlang, nodes, [connected])), + %% Connect them. + pong = rpc:call(A, net_adm, ping, [B]). + test_nodes(V, H) -> - % No nodes should be visible on hidden_node - ?line [] = rpc:call(H, erlang, nodes, []), - % visible_node should be hidden on hidden_node - ?line true = lists:member(V, rpc:call(H, erlang, nodes, [hidden])), - % hidden_node node shouldn't be visible on visible_node - ?line false = lists:member(H, rpc:call(V, erlang, nodes, [])), - % hidden_node should be hidden on visible_node - ?line true = lists:member(H, rpc:call(V, erlang, nodes, [hidden])). + %% No nodes should be visible on hidden_node + [] = rpc:call(H, erlang, nodes, []), + %% visible_node should be hidden on hidden_node + true = lists:member(V, rpc:call(H, erlang, nodes, [hidden])), + %% hidden_node node shouldn't be visible on visible_node + false = lists:member(H, rpc:call(V, erlang, nodes, [])), + %% hidden_node should be hidden on visible_node + true = lists:member(H, rpc:call(V, erlang, nodes, [hidden])). mn_loop(MNs) -> receive @@ -548,21 +795,19 @@ start_monitor_nodes_proc(Node) -> ok end, Pid. - + check_monitor_nodes_res(Pid, Node) -> Ref = make_ref(), Pid ! {monitor_nodes_result, Ref, self()}, receive {Ref, MNs} -> - ?line false = lists:keysearch(Node, 2, MNs) + false = lists:keysearch(Node, 2, MNs) end. -inet_dist_options_options(suite) -> []; -inet_dist_options_options(doc) -> - ["Check the kernel inet_dist_{listen,connect}_options options"]; +%% Check the kernel inet_dist_{listen,connect}_options options. inet_dist_options_options(Config) when is_list(Config) -> Prio = 1, case gen_udp:open(0, [{priority,Prio}]) of @@ -571,7 +816,7 @@ inet_dist_options_options(Config) when is_list(Config) -> {ok,[{priority,Prio}]} -> ok = gen_udp:close(Socket), do_inet_dist_options_options(Prio); - _ -> + _ -> ok = gen_udp:close(Socket), {skip, "Can not set priority "++integer_to_list(Prio)++ @@ -595,25 +840,25 @@ do_inet_dist_options_options(Prio) -> "-hidden " "-kernel inet_dist_connect_options "++PriorityString++" " "-kernel inet_dist_listen_options "++PriorityString, - ?line {ok,Node1} = + {ok,Node1} = start_node(inet_dist_options_1, InetDistOptions), - ?line {ok,Node2} = + {ok,Node2} = start_node(inet_dist_options_2, InetDistOptions), %% - ?line pong = + pong = rpc:call(Node1, net_adm, ping, [Node2]), - ?line PrioritiesNode1 = + PrioritiesNode1 = rpc:call(Node1, ?MODULE, get_socket_priorities, []), - ?line PrioritiesNode2 = + PrioritiesNode2 = rpc:call(Node2, ?MODULE, get_socket_priorities, []), - ?line ?t:format("PrioritiesNode1 = ~p", [PrioritiesNode1]), - ?line ?t:format("PrioritiesNode2 = ~p", [PrioritiesNode2]), - ?line Elevated = [P || P <- PrioritiesNode1, P =:= Prio], - ?line Elevated = [P || P <- PrioritiesNode2, P =:= Prio], - ?line [_|_] = Elevated, + io:format("PrioritiesNode1 = ~p", [PrioritiesNode1]), + io:format("PrioritiesNode2 = ~p", [PrioritiesNode2]), + Elevated = [P || P <- PrioritiesNode1, P =:= Prio], + Elevated = [P || P <- PrioritiesNode2, P =:= Prio], + [_|_] = Elevated, %% - ?line stop_node(Node2), - ?line stop_node(Node1), + stop_node(Node2), + stop_node(Node1), ok. get_socket_priorities() -> @@ -624,185 +869,178 @@ get_socket_priorities() -> element(2, erlang:port_info(Port, name)) =:= "tcp_inet"]]. - + %% %% Testcase: %% monitor_nodes_nodedown_reason %% -monitor_nodes_nodedown_reason(doc) -> []; -monitor_nodes_nodedown_reason(suite) -> []; monitor_nodes_nodedown_reason(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line ok = net_kernel:monitor_nodes(true), - ?line ok = net_kernel:monitor_nodes(true, [nodedown_reason]), - - ?line Names = get_numbered_nodenames(5, node), - ?line [NN1, NN2, NN3, NN4, NN5] = Names, - - ?line {ok, N1} = start_node(NN1), - ?line {ok, N2} = start_node(NN2), - ?line {ok, N3} = start_node(NN3), - ?line {ok, N4} = start_node(NN4, "-hidden"), - - ?line receive {nodeup, N1} -> ok end, - ?line receive {nodeup, N2} -> ok end, - ?line receive {nodeup, N3} -> ok end, - - ?line receive {nodeup, N1, []} -> ok end, - ?line receive {nodeup, N2, []} -> ok end, - ?line receive {nodeup, N3, []} -> ok end, - - ?line stop_node(N1), - ?line stop_node(N4), - ?line true = net_kernel:disconnect(N2), - ?line TickTime = net_kernel:get_net_ticktime(), - ?line SleepTime = TickTime + (TickTime div 4), - ?line spawn(N3, fun () -> - block_emu(SleepTime*1000), - halt() - end), - - ?line receive {nodedown, N1} -> ok end, - ?line receive {nodedown, N2} -> ok end, - ?line receive {nodedown, N3} -> ok end, - - ?line receive {nodedown, N1, [{nodedown_reason, R1}]} -> connection_closed = R1 end, - ?line receive {nodedown, N2, [{nodedown_reason, R2}]} -> disconnect = R2 end, - ?line receive {nodedown, N3, [{nodedown_reason, R3}]} -> net_tick_timeout = R3 end, - - ?line ok = net_kernel:monitor_nodes(false, [nodedown_reason]), - - ?line {ok, N5} = start_node(NN5), - ?line stop_node(N5), - - ?line receive {nodeup, N5} -> ok end, - ?line receive {nodedown, N5} -> ok end, - ?line print_my_messages(), - ?line ok = check_no_nodedown_nodeup(1000), - ?line ok = net_kernel:monitor_nodes(false), - ?line MonNodeState = monitor_node_state(), - ?line ok. - - -monitor_nodes_complex_nodedown_reason(doc) -> []; -monitor_nodes_complex_nodedown_reason(suite) -> []; + MonNodeState = monitor_node_state(), + ok = net_kernel:monitor_nodes(true), + ok = net_kernel:monitor_nodes(true, [nodedown_reason]), + + Names = get_numbered_nodenames(5, node), + [NN1, NN2, NN3, NN4, NN5] = Names, + + {ok, N1} = start_node(NN1), + {ok, N2} = start_node(NN2), + {ok, N3} = start_node(NN3), + {ok, N4} = start_node(NN4, "-hidden"), + + receive {nodeup, N1} -> ok end, + receive {nodeup, N2} -> ok end, + receive {nodeup, N3} -> ok end, + + receive {nodeup, N1, []} -> ok end, + receive {nodeup, N2, []} -> ok end, + receive {nodeup, N3, []} -> ok end, + + stop_node(N1), + stop_node(N4), + true = net_kernel:disconnect(N2), + TickTime = net_kernel:get_net_ticktime(), + SleepTime = TickTime + (TickTime div 2), + spawn(N3, fun () -> + block_emu(SleepTime*1000), + halt() + end), + + receive {nodedown, N1} -> ok end, + receive {nodedown, N2} -> ok end, + receive {nodedown, N3} -> ok end, + + receive {nodedown, N1, [{nodedown_reason, R1}]} -> connection_closed = R1 end, + receive {nodedown, N2, [{nodedown_reason, R2}]} -> disconnect = R2 end, + receive {nodedown, N3, [{nodedown_reason, R3}]} -> net_tick_timeout = R3 end, + + ok = net_kernel:monitor_nodes(false, [nodedown_reason]), + + {ok, N5} = start_node(NN5), + stop_node(N5), + + receive {nodeup, N5} -> ok end, + receive {nodedown, N5} -> ok end, + print_my_messages(), + ok = check_no_nodedown_nodeup(1000), + ok = net_kernel:monitor_nodes(false), + MonNodeState = monitor_node_state(), + ok. + + monitor_nodes_complex_nodedown_reason(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line Me = self(), - ?line ok = net_kernel:monitor_nodes(true, [nodedown_reason]), - ?line [Name] = get_nodenames(1, monitor_nodes_complex_nodedown_reason), - ?line {ok, Node} = start_node(Name, ""), - ?line Pid = spawn(Node, - fun() -> - Me ! {stuff, - self(), - [make_ref(), - {processes(), erlang:ports()}]} - end), - ?line receive {nodeup, Node, []} -> ok end, - ?line {ok, NodeInfo} = net_kernel:node_info(Node), - ?line {value,{owner, Owner}} = lists:keysearch(owner, 1, NodeInfo), - ?line ComplexTerm = receive {stuff, Pid, _} = Msg -> - {Msg, term_to_binary(Msg)} - end, - ?line exit(Owner, ComplexTerm), - ?line receive - {nodedown, Node, [{nodedown_reason, NodeDownReason}]} -> - ?line ok - end, + MonNodeState = monitor_node_state(), + Me = self(), + ok = net_kernel:monitor_nodes(true, [nodedown_reason]), + [Name] = get_nodenames(1, monitor_nodes_complex_nodedown_reason), + {ok, Node} = start_node(Name, ""), + Pid = spawn(Node, + fun() -> + Me ! {stuff, + self(), + [make_ref(), + {processes(), erlang:ports()}]} + end), + receive {nodeup, Node, []} -> ok end, + {ok, NodeInfo} = net_kernel:node_info(Node), + {value,{owner, Owner}} = lists:keysearch(owner, 1, NodeInfo), + ComplexTerm = receive {stuff, Pid, _} = Msg -> + {Msg, term_to_binary(Msg)} + end, + exit(Owner, ComplexTerm), + receive + {nodedown, Node, [{nodedown_reason, NodeDownReason}]} -> + ok + end, %% If the complex nodedown_reason messed something up garbage collections %% are likely to dump core - ?line garbage_collect(), - ?line garbage_collect(), - ?line garbage_collect(), - ?line ComplexTerm = NodeDownReason, - ?line ok = net_kernel:monitor_nodes(false, [nodedown_reason]), - ?line no_msgs(), - ?line MonNodeState = monitor_node_state(), - ?line ok. - - - + garbage_collect(), + garbage_collect(), + garbage_collect(), + ComplexTerm = NodeDownReason, + ok = net_kernel:monitor_nodes(false, [nodedown_reason]), + no_msgs(), + MonNodeState = monitor_node_state(), + ok. + + + %% %% Testcase: %% monitor_nodes_node_type %% -monitor_nodes_node_type(doc) -> []; -monitor_nodes_node_type(suite) -> []; monitor_nodes_node_type(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line ok = net_kernel:monitor_nodes(true), - ?line ok = net_kernel:monitor_nodes(true, [{node_type, all}]), - ?line Names = get_numbered_nodenames(9, node), -% ?line ?t:format("Names: ~p~n", [Names]), - ?line [NN1, NN2, NN3, NN4, NN5, NN6, NN7, NN8, NN9] = Names, - - ?line {ok, N1} = start_node(NN1), - ?line {ok, N2} = start_node(NN2), - ?line {ok, N3} = start_node(NN3, "-hidden"), - ?line {ok, N4} = start_node(NN4, "-hidden"), - - ?line receive {nodeup, N1} -> ok end, - ?line receive {nodeup, N2} -> ok end, - - ?line receive {nodeup, N1, [{node_type, visible}]} -> ok end, - ?line receive {nodeup, N2, [{node_type, visible}]} -> ok end, - ?line receive {nodeup, N3, [{node_type, hidden}]} -> ok end, - ?line receive {nodeup, N4, [{node_type, hidden}]} -> ok end, - - ?line stop_node(N1), - ?line stop_node(N2), - ?line stop_node(N3), - ?line stop_node(N4), - - ?line receive {nodedown, N1} -> ok end, - ?line receive {nodedown, N2} -> ok end, - - ?line receive {nodedown, N1, [{node_type, visible}]} -> ok end, - ?line receive {nodedown, N2, [{node_type, visible}]} -> ok end, - ?line receive {nodedown, N3, [{node_type, hidden}]} -> ok end, - ?line receive {nodedown, N4, [{node_type, hidden}]} -> ok end, - - ?line ok = net_kernel:monitor_nodes(false, [{node_type, all}]), - ?line {ok, N5} = start_node(NN5), - - ?line receive {nodeup, N5} -> ok end, - ?line stop_node(N5), - ?line receive {nodedown, N5} -> ok end, - - ?line ok = net_kernel:monitor_nodes(true, [{node_type, hidden}]), - ?line {ok, N6} = start_node(NN6), - ?line {ok, N7} = start_node(NN7, "-hidden"), - - - ?line receive {nodeup, N6} -> ok end, - ?line receive {nodeup, N7, [{node_type, hidden}]} -> ok end, - ?line stop_node(N6), - ?line stop_node(N7), - - ?line receive {nodedown, N6} -> ok end, - ?line receive {nodedown, N7, [{node_type, hidden}]} -> ok end, - - ?line ok = net_kernel:monitor_nodes(true, [{node_type, visible}]), - ?line ok = net_kernel:monitor_nodes(false, [{node_type, hidden}]), - ?line ok = net_kernel:monitor_nodes(false), - - ?line {ok, N8} = start_node(NN8), - ?line {ok, N9} = start_node(NN9, "-hidden"), - - ?line receive {nodeup, N8, [{node_type, visible}]} -> ok end, - ?line stop_node(N8), - ?line stop_node(N9), - - ?line receive {nodedown, N8, [{node_type, visible}]} -> ok end, - ?line print_my_messages(), - ?line ok = check_no_nodedown_nodeup(1000), - ?line ok = net_kernel:monitor_nodes(false, [{node_type, visible}]), - ?line MonNodeState = monitor_node_state(), - ?line ok. + MonNodeState = monitor_node_state(), + ok = net_kernel:monitor_nodes(true), + ok = net_kernel:monitor_nodes(true, [{node_type, all}]), + Names = get_numbered_nodenames(9, node), + [NN1, NN2, NN3, NN4, NN5, NN6, NN7, NN8, NN9] = Names, + + {ok, N1} = start_node(NN1), + {ok, N2} = start_node(NN2), + {ok, N3} = start_node(NN3, "-hidden"), + {ok, N4} = start_node(NN4, "-hidden"), + + receive {nodeup, N1} -> ok end, + receive {nodeup, N2} -> ok end, + + receive {nodeup, N1, [{node_type, visible}]} -> ok end, + receive {nodeup, N2, [{node_type, visible}]} -> ok end, + receive {nodeup, N3, [{node_type, hidden}]} -> ok end, + receive {nodeup, N4, [{node_type, hidden}]} -> ok end, + + stop_node(N1), + stop_node(N2), + stop_node(N3), + stop_node(N4), + + receive {nodedown, N1} -> ok end, + receive {nodedown, N2} -> ok end, + + receive {nodedown, N1, [{node_type, visible}]} -> ok end, + receive {nodedown, N2, [{node_type, visible}]} -> ok end, + receive {nodedown, N3, [{node_type, hidden}]} -> ok end, + receive {nodedown, N4, [{node_type, hidden}]} -> ok end, + + ok = net_kernel:monitor_nodes(false, [{node_type, all}]), + {ok, N5} = start_node(NN5), + + receive {nodeup, N5} -> ok end, + stop_node(N5), + receive {nodedown, N5} -> ok end, + + ok = net_kernel:monitor_nodes(true, [{node_type, hidden}]), + {ok, N6} = start_node(NN6), + {ok, N7} = start_node(NN7, "-hidden"), + + + receive {nodeup, N6} -> ok end, + receive {nodeup, N7, [{node_type, hidden}]} -> ok end, + stop_node(N6), + stop_node(N7), + + receive {nodedown, N6} -> ok end, + receive {nodedown, N7, [{node_type, hidden}]} -> ok end, + + ok = net_kernel:monitor_nodes(true, [{node_type, visible}]), + ok = net_kernel:monitor_nodes(false, [{node_type, hidden}]), + ok = net_kernel:monitor_nodes(false), + + {ok, N8} = start_node(NN8), + {ok, N9} = start_node(NN9, "-hidden"), + + receive {nodeup, N8, [{node_type, visible}]} -> ok end, + stop_node(N8), + stop_node(N9), + + receive {nodedown, N8, [{node_type, visible}]} -> ok end, + print_my_messages(), + ok = check_no_nodedown_nodeup(1000), + ok = net_kernel:monitor_nodes(false, [{node_type, visible}]), + MonNodeState = monitor_node_state(), + ok. %% @@ -810,95 +1048,89 @@ monitor_nodes_node_type(Config) when is_list(Config) -> %% monitor_nodes %% -monitor_nodes_misc(doc) -> []; -monitor_nodes_misc(suite) -> []; monitor_nodes_misc(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line ok = net_kernel:monitor_nodes(true), - ?line ok = net_kernel:monitor_nodes(true, [{node_type, all}, nodedown_reason]), - ?line ok = net_kernel:monitor_nodes(true, [nodedown_reason, {node_type, all}]), - ?line Names = get_numbered_nodenames(3, node), -% ?line ?t:format("Names: ~p~n", [Names]), - ?line [NN1, NN2, NN3] = Names, - - ?line {ok, N1} = start_node(NN1), - ?line {ok, N2} = start_node(NN2, "-hidden"), - - ?line receive {nodeup, N1} -> ok end, - - ?line receive {nodeup, N1, [{node_type, visible}]} -> ok end, - ?line receive {nodeup, N1, [{node_type, visible}]} -> ok end, - ?line receive {nodeup, N2, [{node_type, hidden}]} -> ok end, - ?line receive {nodeup, N2, [{node_type, hidden}]} -> ok end, - - ?line stop_node(N1), - ?line stop_node(N2), - - ?line VisbleDownInfo = lists:sort([{node_type, visible}, - {nodedown_reason, connection_closed}]), - ?line HiddenDownInfo = lists:sort([{node_type, hidden}, - {nodedown_reason, connection_closed}]), - - ?line receive {nodedown, N1} -> ok end, - - ?line receive {nodedown, N1, Info1A} -> VisbleDownInfo = lists:sort(Info1A) end, - ?line receive {nodedown, N1, Info1B} -> VisbleDownInfo = lists:sort(Info1B) end, - ?line receive {nodedown, N2, Info2A} -> HiddenDownInfo = lists:sort(Info2A) end, - ?line receive {nodedown, N2, Info2B} -> HiddenDownInfo = lists:sort(Info2B) end, - - ?line ok = net_kernel:monitor_nodes(false, [{node_type, all}, nodedown_reason]), - - ?line {ok, N3} = start_node(NN3), - ?line receive {nodeup, N3} -> ok end, - ?line stop_node(N3), - ?line receive {nodedown, N3} -> ok end, - ?line print_my_messages(), - ?line ok = check_no_nodedown_nodeup(1000), - ?line ok = net_kernel:monitor_nodes(false), - ?line MonNodeState = monitor_node_state(), - ?line ok. - - -monitor_nodes_otp_6481(doc) -> - ["Tests that {nodeup, Node} messages are received before " - "messages from Node and that {nodedown, Node} messages are" - "received after messages from Node"]; -monitor_nodes_otp_6481(suite) -> - []; + MonNodeState = monitor_node_state(), + ok = net_kernel:monitor_nodes(true), + ok = net_kernel:monitor_nodes(true, [{node_type, all}, nodedown_reason]), + ok = net_kernel:monitor_nodes(true, [nodedown_reason, {node_type, all}]), + Names = get_numbered_nodenames(3, node), + [NN1, NN2, NN3] = Names, + + {ok, N1} = start_node(NN1), + {ok, N2} = start_node(NN2, "-hidden"), + + receive {nodeup, N1} -> ok end, + + receive {nodeup, N1, [{node_type, visible}]} -> ok end, + receive {nodeup, N1, [{node_type, visible}]} -> ok end, + receive {nodeup, N2, [{node_type, hidden}]} -> ok end, + receive {nodeup, N2, [{node_type, hidden}]} -> ok end, + + stop_node(N1), + stop_node(N2), + + VisbleDownInfo = lists:sort([{node_type, visible}, + {nodedown_reason, connection_closed}]), + HiddenDownInfo = lists:sort([{node_type, hidden}, + {nodedown_reason, connection_closed}]), + + receive {nodedown, N1} -> ok end, + + receive {nodedown, N1, Info1A} -> VisbleDownInfo = lists:sort(Info1A) end, + receive {nodedown, N1, Info1B} -> VisbleDownInfo = lists:sort(Info1B) end, + receive {nodedown, N2, Info2A} -> HiddenDownInfo = lists:sort(Info2A) end, + receive {nodedown, N2, Info2B} -> HiddenDownInfo = lists:sort(Info2B) end, + + ok = net_kernel:monitor_nodes(false, [{node_type, all}, nodedown_reason]), + + {ok, N3} = start_node(NN3), + receive {nodeup, N3} -> ok end, + stop_node(N3), + receive {nodedown, N3} -> ok end, + print_my_messages(), + ok = check_no_nodedown_nodeup(1000), + ok = net_kernel:monitor_nodes(false), + MonNodeState = monitor_node_state(), + ok. + + +%% Tests that {nodeup, Node} messages are received before +%% messages from Node and that {nodedown, Node} messages are +%% received after messages from Node. monitor_nodes_otp_6481(Config) when is_list(Config) -> - ?line ?t:format("Testing nodedown...~n"), - ?line monitor_nodes_otp_6481_test(Config, nodedown), - ?line ?t:format("ok~n"), - ?line ?t:format("Testing nodeup...~n"), - ?line monitor_nodes_otp_6481_test(Config, nodeup), - ?line ?t:format("ok~n"), - ?line ok. + io:format("Testing nodedown...~n"), + monitor_nodes_otp_6481_test(Config, nodedown), + io:format("ok~n"), + io:format("Testing nodeup...~n"), + monitor_nodes_otp_6481_test(Config, nodeup), + io:format("ok~n"), + ok. monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line NodeMsg = make_ref(), - ?line Me = self(), - ?line [Name] = get_nodenames(1, monitor_nodes_otp_6481), - ?line case TestType of - nodedown -> ?line ok = net_kernel:monitor_nodes(true); - nodeup -> ?line ok - end, - ?line Seq = lists:seq(1,10000), - ?line MN = spawn_link( - fun () -> - ?line lists:foreach( - fun (_) -> - ?line ok = net_kernel:monitor_nodes(true) - end, - Seq), - ?line Me ! {mon_set, self()}, - ?line receive after infinity -> ok end - end), - ?line receive {mon_set, MN} -> ok end, - ?line case TestType of - nodedown -> ?line ok; - nodeup -> ?line ok = net_kernel:monitor_nodes(true) - end, + MonNodeState = monitor_node_state(), + NodeMsg = make_ref(), + Me = self(), + [Name] = get_nodenames(1, monitor_nodes_otp_6481), + case TestType of + nodedown -> ok = net_kernel:monitor_nodes(true); + nodeup -> ok + end, + Seq = lists:seq(1,10000), + MN = spawn_link( + fun () -> + lists:foreach( + fun (_) -> + ok = net_kernel:monitor_nodes(true) + end, + Seq), + Me ! {mon_set, self()}, + receive after infinity -> ok end + end), + receive {mon_set, MN} -> ok end, + case TestType of + nodedown -> ok; + nodeup -> ok = net_kernel:monitor_nodes(true) + end, %% Whitebox: %% nodedown test: Since this process was the first one monitoring @@ -909,170 +1141,163 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) -> %% on nodeup %% Verify the monitor_nodes order expected - ?line TestMonNodeState = monitor_node_state(), - %?line ?t:format("~p~n", [TestMonNodeState]), - ?line TestMonNodeState = + TestMonNodeState = monitor_node_state(), + %% io:format("~p~n", [TestMonNodeState]), + TestMonNodeState = MonNodeState ++ case TestType of - nodedown -> [{self(), []}]; - nodeup -> [] + nodedown -> [{self(), []}]; + nodeup -> [] end ++ lists:map(fun (_) -> {MN, []} end, Seq) ++ case TestType of - nodedown -> []; - nodeup -> [{self(), []}] + nodedown -> []; + nodeup -> [{self(), []}] end, - ?line {ok, Node} = start_node(Name, "", this), - ?line receive {nodeup, Node} -> ok end, - - ?line RemotePid = spawn(Node, - fun () -> - receive after 1500 -> ok end, - % infinit loop of msgs - % we want an endless stream of messages and the kill - % the node mercilessly. - % We then want to ensure that the nodedown message arrives - % last ... without garbage after it. - _ = spawn(fun() -> node_loop_send(Me, NodeMsg, 1) end), - receive {Me, kill_it} -> ok end, - halt() - end), + {ok, Node} = start_node(Name, "", this), + receive {nodeup, Node} -> ok end, + + RemotePid = spawn(Node, + fun () -> + receive after 1500 -> ok end, + %% infinite loop of msgs + %% we want an endless stream of messages and the kill + %% the node mercilessly. + %% We then want to ensure that the nodedown message arrives + %% last ... without garbage after it. + _ = spawn(fun() -> node_loop_send(Me, NodeMsg, 1) end), + receive {Me, kill_it} -> ok end, + halt() + end), - ?line net_kernel:disconnect(Node), - ?line receive {nodedown, Node} -> ok end, + net_kernel:disconnect(Node), + receive {nodedown, Node} -> ok end, %% Verify that '{nodeup, Node}' comes before '{NodeMsg, 1}' (the message %% bringing up the connection). - ?line no_msgs(500), - ?line {nodeup, Node} = receive Msg1 -> Msg1 end, - ?line {NodeMsg, 1} = receive Msg2 -> Msg2 end, - % msg stream has begun, kill the node - ?line RemotePid ! {self(), kill_it}, + {nodeup, Node} = receive Msg1 -> Msg1 end, + {NodeMsg, N} = receive Msg2 -> Msg2 end, + %% msg stream has begun, kill the node + RemotePid ! {self(), kill_it}, %% Verify that '{nodedown, Node}' comes after the last '{NodeMsg, N}' %% message. - ?line {nodedown, Node} = flush_node_msgs(NodeMsg, 2), - ?line no_msgs(500), - - ?line Mon = erlang:monitor(process, MN), - ?line unlink(MN), - ?line exit(MN, bang), - ?line receive {'DOWN', Mon, process, MN, bang} -> ok end, - ?line ok = net_kernel:monitor_nodes(false), - ?line MonNodeState = monitor_node_state(), - ?line ok. + {nodedown, Node} = flush_node_msgs(NodeMsg, N+1), + no_msgs(500), + + Mon = erlang:monitor(process, MN), + unlink(MN), + exit(MN, bang), + receive {'DOWN', Mon, process, MN, bang} -> ok end, + ok = net_kernel:monitor_nodes(false), + MonNodeState = monitor_node_state(), + ok. flush_node_msgs(NodeMsg, No) -> case receive Msg -> Msg end of - {NodeMsg, No} -> flush_node_msgs(NodeMsg, No+1); - OtherMsg -> OtherMsg + {NodeMsg, N} when N >= No -> + flush_node_msgs(NodeMsg, N+1); + OtherMsg -> + OtherMsg end. node_loop_send(Pid, Msg, No) -> Pid ! {Msg, No}, node_loop_send(Pid, Msg, No + 1). -monitor_nodes_errors(doc) -> - []; -monitor_nodes_errors(suite) -> - []; monitor_nodes_errors(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line error = net_kernel:monitor_nodes(asdf), - ?line {error, - {unknown_options, - [gurka]}} = net_kernel:monitor_nodes(true, - [gurka]), - ?line {error, - {options_not_a_list, - gurka}} = net_kernel:monitor_nodes(true, - gurka), - ?line {error, - {option_value_mismatch, - [{node_type,visible}, - {node_type,hidden}]}} + MonNodeState = monitor_node_state(), + error = net_kernel:monitor_nodes(asdf), + {error, + {unknown_options, + [gurka]}} = net_kernel:monitor_nodes(true, + [gurka]), + {error, + {options_not_a_list, + gurka}} = net_kernel:monitor_nodes(true, + gurka), + {error, + {option_value_mismatch, + [{node_type,visible}, + {node_type,hidden}]}} = net_kernel:monitor_nodes(true, [{node_type,hidden}, {node_type,visible}]), - ?line {error, - {option_value_mismatch, - [{node_type,visible}, - {node_type,all}]}} + {error, + {option_value_mismatch, + [{node_type,visible}, + {node_type,all}]}} = net_kernel:monitor_nodes(true, [{node_type,all}, {node_type,visible}]), - ?line {error, - {bad_option_value, - {node_type, - blaha}}} + {error, + {bad_option_value, + {node_type, + blaha}}} = net_kernel:monitor_nodes(true, [{node_type, blaha}]), - ?line MonNodeState = monitor_node_state(), - ?line ok. + MonNodeState = monitor_node_state(), + ok. -monitor_nodes_combinations(doc) -> - []; -monitor_nodes_combinations(suite) -> - []; monitor_nodes_combinations(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line monitor_nodes_all_comb(true), - ?line [VisibleName, HiddenName] = get_nodenames(2, - monitor_nodes_combinations), - ?line {ok, Visible} = start_node(VisibleName, ""), - ?line receive_all_comb_nodeup_msgs(visible, Visible), - ?line no_msgs(), - ?line stop_node(Visible), - ?line receive_all_comb_nodedown_msgs(visible, Visible, connection_closed), - ?line no_msgs(), - ?line {ok, Hidden} = start_node(HiddenName, "-hidden"), - ?line receive_all_comb_nodeup_msgs(hidden, Hidden), - ?line no_msgs(), - ?line stop_node(Hidden), - ?line receive_all_comb_nodedown_msgs(hidden, Hidden, connection_closed), - ?line no_msgs(), - ?line monitor_nodes_all_comb(false), - ?line MonNodeState = monitor_node_state(), - ?line no_msgs(), - ?line ok. + MonNodeState = monitor_node_state(), + monitor_nodes_all_comb(true), + [VisibleName, HiddenName] = get_nodenames(2, + monitor_nodes_combinations), + {ok, Visible} = start_node(VisibleName, ""), + receive_all_comb_nodeup_msgs(visible, Visible), + no_msgs(), + stop_node(Visible), + receive_all_comb_nodedown_msgs(visible, Visible, connection_closed), + no_msgs(), + {ok, Hidden} = start_node(HiddenName, "-hidden"), + receive_all_comb_nodeup_msgs(hidden, Hidden), + no_msgs(), + stop_node(Hidden), + receive_all_comb_nodedown_msgs(hidden, Hidden, connection_closed), + no_msgs(), + monitor_nodes_all_comb(false), + MonNodeState = monitor_node_state(), + no_msgs(), + ok. monitor_nodes_all_comb(Flag) -> - ?line ok = net_kernel:monitor_nodes(Flag), - ?line ok = net_kernel:monitor_nodes(Flag, - [nodedown_reason]), - ?line ok = net_kernel:monitor_nodes(Flag, - [{node_type, hidden}]), - ?line ok = net_kernel:monitor_nodes(Flag, - [{node_type, visible}]), - ?line ok = net_kernel:monitor_nodes(Flag, - [{node_type, all}]), - ?line ok = net_kernel:monitor_nodes(Flag, - [nodedown_reason, - {node_type, hidden}]), - ?line ok = net_kernel:monitor_nodes(Flag, - [nodedown_reason, - {node_type, visible}]), - ?line ok = net_kernel:monitor_nodes(Flag, - [nodedown_reason, - {node_type, all}]), + ok = net_kernel:monitor_nodes(Flag), + ok = net_kernel:monitor_nodes(Flag, + [nodedown_reason]), + ok = net_kernel:monitor_nodes(Flag, + [{node_type, hidden}]), + ok = net_kernel:monitor_nodes(Flag, + [{node_type, visible}]), + ok = net_kernel:monitor_nodes(Flag, + [{node_type, all}]), + ok = net_kernel:monitor_nodes(Flag, + [nodedown_reason, + {node_type, hidden}]), + ok = net_kernel:monitor_nodes(Flag, + [nodedown_reason, + {node_type, visible}]), + ok = net_kernel:monitor_nodes(Flag, + [nodedown_reason, + {node_type, all}]), %% There currently are 8 different combinations - ?line 8. + 8. receive_all_comb_nodeup_msgs(visible, Node) -> - ?t:format("Receive nodeup visible...~n"), + io:format("Receive nodeup visible...~n"), Exp = [{nodeup, Node}, {nodeup, Node, []}] ++ mk_exp_mn_all_comb_nodeup_msgs_common(visible, Node), receive_mn_msgs(Exp), - ?t:format("ok~n"), + io:format("ok~n"), ok; receive_all_comb_nodeup_msgs(hidden, Node) -> - ?t:format("Receive nodeup hidden...~n"), + io:format("Receive nodeup hidden...~n"), Exp = mk_exp_mn_all_comb_nodeup_msgs_common(hidden, Node), receive_mn_msgs(Exp), - ?t:format("ok~n"), + io:format("ok~n"), ok. mk_exp_mn_all_comb_nodeup_msgs_common(Type, Node) -> @@ -1083,20 +1308,20 @@ mk_exp_mn_all_comb_nodeup_msgs_common(Type, Node) -> {nodeup, Node, InfoNt}]. receive_all_comb_nodedown_msgs(visible, Node, Reason) -> - ?t:format("Receive nodedown visible...~n"), + io:format("Receive nodedown visible...~n"), Exp = [{nodedown, Node}, {nodedown, Node, [{nodedown_reason, Reason}]}] ++ mk_exp_mn_all_comb_nodedown_msgs_common(visible, Node, Reason), receive_mn_msgs(Exp), - ?t:format("ok~n"), + io:format("ok~n"), ok; receive_all_comb_nodedown_msgs(hidden, Node, Reason) -> - ?t:format("Receive nodedown hidden...~n"), + io:format("Receive nodedown hidden...~n"), Exp = mk_exp_mn_all_comb_nodedown_msgs_common(hidden, Node, Reason), receive_mn_msgs(Exp), - ?t:format("ok~n"), + io:format("ok~n"), ok. mk_exp_mn_all_comb_nodedown_msgs_common(Type, Node, Reason) -> @@ -1110,81 +1335,73 @@ mk_exp_mn_all_comb_nodedown_msgs_common(Type, Node, Reason) -> receive_mn_msgs([]) -> ok; receive_mn_msgs(Msgs) -> - ?t:format("Expecting msgs: ~p~n", [Msgs]), + io:format("Expecting msgs: ~p~n", [Msgs]), receive {_Dir, _Node} = Msg -> - ?t:format("received ~p~n", [Msg]), + io:format("received ~p~n", [Msg]), case lists:member(Msg, Msgs) of true -> receive_mn_msgs(lists:delete(Msg, Msgs)); - false -> ?t:fail({unexpected_message, Msg, + false -> ct:fail({unexpected_message, Msg, expected_messages, Msgs}) end; {Dir, Node, Info} -> Msg = {Dir, Node, lists:sort(Info)}, - ?t:format("received ~p~n", [Msg]), + io:format("received ~p~n", [Msg]), case lists:member(Msg, Msgs) of true -> receive_mn_msgs(lists:delete(Msg, Msgs)); - false -> ?t:fail({unexpected_message, Msg, + false -> ct:fail({unexpected_message, Msg, expected_messages, Msgs}) end; Msg -> - ?t:format("received ~p~n", [Msg]), - ?t:fail({unexpected_message, Msg, + io:format("received ~p~n", [Msg]), + ct:fail({unexpected_message, Msg, expected_messages, Msgs}) end. -monitor_nodes_cleanup(doc) -> - []; -monitor_nodes_cleanup(suite) -> - []; monitor_nodes_cleanup(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line Me = self(), - ?line No = monitor_nodes_all_comb(true), - ?line Inf = spawn(fun () -> - monitor_nodes_all_comb(true), - Me ! {mons_set, self()}, - receive after infinity -> ok end - end), - ?line TO = spawn(fun () -> - monitor_nodes_all_comb(true), - Me ! {mons_set, self()}, - receive after 500 -> ok end - end), - ?line receive {mons_set, Inf} -> ok end, - ?line receive {mons_set, TO} -> ok end, - ?line MNLen = length(MonNodeState) + No*3, - ?line MNLen = length(monitor_node_state()), - ?line MonInf = erlang:monitor(process, Inf), - ?line MonTO = erlang:monitor(process, TO), - ?line exit(Inf, bang), - ?line No = monitor_nodes_all_comb(false), - ?line receive {'DOWN', MonInf, process, Inf, bang} -> ok end, - ?line receive {'DOWN', MonTO, process, TO, normal} -> ok end, - ?line MonNodeState = monitor_node_state(), - ?line no_msgs(), - ?line ok. - -monitor_nodes_many(doc) -> - []; -monitor_nodes_many(suite) -> - []; + MonNodeState = monitor_node_state(), + Me = self(), + No = monitor_nodes_all_comb(true), + Inf = spawn(fun () -> + monitor_nodes_all_comb(true), + Me ! {mons_set, self()}, + receive after infinity -> ok end + end), + TO = spawn(fun () -> + monitor_nodes_all_comb(true), + Me ! {mons_set, self()}, + receive after 500 -> ok end + end), + receive {mons_set, Inf} -> ok end, + receive {mons_set, TO} -> ok end, + MNLen = length(MonNodeState) + No*3, + MNLen = length(monitor_node_state()), + MonInf = erlang:monitor(process, Inf), + MonTO = erlang:monitor(process, TO), + exit(Inf, bang), + No = monitor_nodes_all_comb(false), + receive {'DOWN', MonInf, process, Inf, bang} -> ok end, + receive {'DOWN', MonTO, process, TO, normal} -> ok end, + MonNodeState = monitor_node_state(), + no_msgs(), + ok. + monitor_nodes_many(Config) when is_list(Config) -> - ?line MonNodeState = monitor_node_state(), - ?line [Name] = get_nodenames(1, monitor_nodes_many), + MonNodeState = monitor_node_state(), + [Name] = get_nodenames(1, monitor_nodes_many), %% We want to perform more than 2^16 net_kernel:monitor_nodes %% since this will wrap an internal counter - ?line No = (1 bsl 16) + 17, - ?line repeat(fun () -> ok = net_kernel:monitor_nodes(true) end, No), - ?line No = length(monitor_node_state()) - length(MonNodeState), - ?line {ok, Node} = start_node(Name), - ?line repeat(fun () -> receive {nodeup, Node} -> ok end end, No), - ?line stop_node(Node), - ?line repeat(fun () -> receive {nodedown, Node} -> ok end end, No), - ?line ok = net_kernel:monitor_nodes(false), - ?line no_msgs(10), - ?line MonNodeState = monitor_node_state(), - ?line ok. + No = (1 bsl 16) + 17, + repeat(fun () -> ok = net_kernel:monitor_nodes(true) end, No), + No = length(monitor_node_state()) - length(MonNodeState), + {ok, Node} = start_node(Name), + repeat(fun () -> receive {nodeup, Node} -> ok end end, No), + stop_node(Node), + repeat(fun () -> receive {nodedown, Node} -> ok end end, No), + ok = net_kernel:monitor_nodes(false), + no_msgs(10), + MonNodeState = monitor_node_state(), + ok. %% Misc. functions @@ -1196,59 +1413,45 @@ monitor_node_state() -> check_no_nodedown_nodeup(TimeOut) -> - ?line receive - {nodeup, _, _} = Msg -> ?line ?t:fail({unexpected_nodeup, Msg}); - {nodeup, _} = Msg -> ?line ?t:fail({unexpected_nodeup, Msg}); - {nodedown, _, _} = Msg -> ?line ?t:fail({unexpected_nodedown, Msg}); - {nodedown, _} = Msg -> ?line ?t:fail({unexpected_nodedown, Msg}) - after TimeOut -> - ok - end. + receive + {nodeup, _, _} = Msg -> ct:fail({unexpected_nodeup, Msg}); + {nodeup, _} = Msg -> ct:fail({unexpected_nodeup, Msg}); + {nodedown, _, _} = Msg -> ct:fail({unexpected_nodedown, Msg}); + {nodedown, _} = Msg -> ct:fail({unexpected_nodedown, Msg}) + after TimeOut -> + ok + end. print_my_messages() -> - ?line {messages, Messages} = process_info(self(), messages), - ?line ?t:format("Messages: ~p~n", [Messages]), - ?line ok. + {messages, Messages} = process_info(self(), messages), + io:format("Messages: ~p~n", [Messages]), + ok. sleep(T) -> receive after T * 1000 -> ok end. start_node(Name, Param, this) -> NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)), - ?t:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]); + test_server:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]); start_node(Name, Param, "this") -> NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)), - ?t:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]); + test_server:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]); start_node(Name, Param, Rel) when is_atom(Rel) -> NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)), - ?t:start_node(Name, peer, [{args, NewParam}, {erl, [{release, atom_to_list(Rel)}]}]); + test_server:start_node(Name, peer, [{args, NewParam}, {erl, [{release, atom_to_list(Rel)}]}]); start_node(Name, Param, Rel) when is_list(Rel) -> NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)), - ?t:start_node(Name, peer, [{args, NewParam}, {erl, [{release, Rel}]}]). + test_server:start_node(Name, peer, [{args, NewParam}, {erl, [{release, Rel}]}]). start_node(Name, Param) -> NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)), - ?t:start_node(Name, slave, [{args, NewParam}]). -% M = list_to_atom(from($@, atom_to_list(node()))), -% slave:start_link(M, Name, Param). + test_server:start_node(Name, slave, [{args, NewParam}]). start_node(Name) -> start_node(Name, ""). stop_node(Node) -> - ?t:stop_node(Node). -% erlang:monitor_node(Node, true), -% rpc:cast(Node, init, stop, []), -% receive -% {nodedown, Node} -> -% ok -% after 10000 -> -% test_server:fail({stop_node, Node}) -% end. - -% from(H, [H | T]) -> T; -% from(H, [_ | T]) -> from(H, T); -% from(H, []) -> []. + test_server:stop_node(Node). get_nodenames(N, T) -> get_nodenames(N, T, []). diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl index c107e92fae..03aaee56b7 100644 --- a/lib/kernel/test/erl_distribution_wb_SUITE.erl +++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. 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. @@ -19,7 +19,7 @@ %% -module(erl_distribution_wb_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/inet.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -30,7 +30,7 @@ %% 1) %% -%% Connections are now always set up symetrically with respect to +%% Connections are now always set up symmetrically with respect to %% publication. If connecting node doesn't send DFLAG_PUBLISHED %% the other node wont send DFLAG_PUBLISHED. If the connecting %% node send DFLAG_PUBLISHED but the other node doesn't send @@ -56,10 +56,14 @@ -define(DFLAG_HIDDEN_ATOM_CACHE,16#40). -define(DFLAG_NEW_FUN_TAGS,16#80). -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). +-define(DFLAG_UTF8_ATOMS, 16#10000). %% From R9 and forward extended references is compulsory %% From R10 and forward extended pids and ports are compulsory --define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS)). +%% From R20 and forward UTF8 atoms are compulsory +-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor + ?DFLAG_EXTENDED_PIDS_PORTS bor + ?DFLAG_UTF8_ATOMS)). -define(shutdown(X), exit(X)). @@ -71,7 +75,7 @@ -define(i16(X1,X0), (?u16(X1,X0) - - (if (X1) > 127 -> 16#10000; true -> 0 end))). + (if (X1) > 127 -> 16#10000; true -> 0 end))). -define(u16(X1,X0), (((X1) bsl 8) bor (X0))). @@ -79,7 +83,9 @@ -define(u32(X3,X2,X1,X0), (((X3) bsl 24) bor ((X2) bsl 16) bor ((X1) bsl 8) bor (X0))). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [whitebox, switch_options, missing_compulsory_dflags]. @@ -101,39 +107,33 @@ end_per_group(_GroupName, Config) -> init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog=?t:timetrap(?t:minutes(1)), - [{watchdog, Dog}|Config]. - -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). - -switch_options(doc) -> - ["Tests switching of options for the tcp port, as this is done" - " when the distribution port is to be shortcut into the emulator." - " Maybe this should be in the inet test suite, but only the distribution" - " does such horrible things..."]; + Config. + +end_per_testcase(_Func, _Config) -> + ok. + +%% Tests switching of options for the tcp port, as this is done +%% when the distribution port is to be shortcut into the emulator. +%% Maybe this should be in the inet test suite, but only the distribution +%% does such horrible things... switch_options(Config) when is_list(Config) -> ok = test_switch_active(), ok = test_switch_active_partial() , ok = test_switch_active_and_packet(), ok. - -whitebox(doc) -> - ["Whitebox testing of distribution handshakes. Tests both BC with R5 and " - "the md5 version. Note that after R6B, this should be revised to " - "remove BC code."]; + +%% Whitebox testing of distribution handshakes. whitebox(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(?MODULE,""), - ?line Cookie = erlang:get_cookie(), - ?line {_,Host} = split(node()), - ?line ok = pending_up_md5(Node, join(ccc,Host), Cookie), - ?line ok = simultaneous_md5(Node, join('A',Host), Cookie), - ?line ok = simultaneous_md5(Node, join(zzzzzzzzzzzzzz,Host), Cookie), - ?line stop_node(Node), + {ok, Node} = start_node(?MODULE,""), + Cookie = erlang:get_cookie(), + {_,Host} = split(node()), + ok = pending_up_md5(Node, join(ccc,Host), Cookie), + ok = simultaneous_md5(Node, join('A',Host), Cookie), + ok = simultaneous_md5(Node, join(zzzzzzzzzzzzzz,Host), Cookie), + stop_node(Node), ok. - + %% %% The actual tests %% @@ -143,56 +143,56 @@ whitebox(Config) when is_list(Config) -> %% test_switch_active() -> - ?line {Client, Server} = socket_pair(0, 4), - ?line ok = write_packets_32(Client, 1, 5), + {Client, Server} = socket_pair(0, 4), + ok = write_packets_32(Client, 1, 5), receive after 2000 -> ok end, - ?line ok = read_packets(Server, 1, 1), + ok = read_packets(Server, 1, 1), receive after 2000 -> ok end, - ?line ok = read_packets(Server, 2, 2), - ?line inet:setopts(Server, [{active, true}]), - ?line ok = receive_packets(Server, 3, 5), + ok = read_packets(Server, 2, 2), + inet:setopts(Server, [{active, true}]), + ok = receive_packets(Server, 3, 5), close_pair({Client, Server}), ok. - + test_switch_active_partial() -> - ?line {Client, Server} = socket_pair(0, 4), - ?line ok = write_packets_32(Client, 1, 2), - ?line ok = gen_tcp:send(Client,[?int32(4), [0,0,0]]), + {Client, Server} = socket_pair(0, 4), + ok = write_packets_32(Client, 1, 2), + ok = gen_tcp:send(Client,[?int32(4), [0,0,0]]), receive after 2000 -> ok end, - ?line ok = read_packets(Server, 1, 1), + ok = read_packets(Server, 1, 1), receive after 2000 -> ok end, - ?line ok = read_packets(Server, 2, 2), - ?line inet:setopts(Server, [{active, true}]), - ?line ok = gen_tcp:send(Client,[3]), - ?line ok = write_packets_32(Client, 4, 5), - ?line ok = receive_packets(Server, 3, 5), + ok = read_packets(Server, 2, 2), + inet:setopts(Server, [{active, true}]), + ok = gen_tcp:send(Client,[3]), + ok = write_packets_32(Client, 4, 5), + ok = receive_packets(Server, 3, 5), close_pair({Client, Server}), ok. - + do_test_switch_active_and_packet(SendBefore, SendAfter) -> - ?line {Client, Server} = socket_pair(0, 2), - ?line ok = write_packets_16(Client, 1, 2), - ?line ok = gen_tcp:send(Client,SendBefore), + {Client, Server} = socket_pair(0, 2), + ok = write_packets_16(Client, 1, 2), + ok = gen_tcp:send(Client,SendBefore), receive after 2000 -> ok end, - ?line ok = read_packets(Server, 1, 1), + ok = read_packets(Server, 1, 1), receive after 2000 -> ok end, - ?line ok = read_packets(Server, 2, 2), - ?line inet:setopts(Server, [{packet,4}, {active, true}]), - ?line ok = gen_tcp:send(Client,SendAfter), - ?line ok = write_packets_32(Client, 4, 5), - ?line ok = receive_packets(Server, 3, 5), + ok = read_packets(Server, 2, 2), + inet:setopts(Server, [{packet,4}, {active, true}]), + ok = gen_tcp:send(Client,SendAfter), + ok = write_packets_32(Client, 4, 5), + ok = receive_packets(Server, 3, 5), close_pair({Client, Server}), ok. test_switch_active_and_packet() -> - ?line ok = do_test_switch_active_and_packet([0],[0,0,4,0,0,0,3]), - ?line ok = do_test_switch_active_and_packet([0,0],[0,4,0,0,0,3]), - ?line ok = do_test_switch_active_and_packet([0,0,0],[4,0,0,0,3]), - ?line ok = do_test_switch_active_and_packet([0,0,0,4],[0,0,0,3]), - ?line ok = do_test_switch_active_and_packet([0,0,0,4,0],[0,0,3]), - ?line ok = do_test_switch_active_and_packet([0,0,0,4,0,0],[0,3]), - ?line ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0],[3]), - ?line ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0,3],[]), + ok = do_test_switch_active_and_packet([0],[0,0,4,0,0,0,3]), + ok = do_test_switch_active_and_packet([0,0],[0,4,0,0,0,3]), + ok = do_test_switch_active_and_packet([0,0,0],[4,0,0,0,3]), + ok = do_test_switch_active_and_packet([0,0,0,4],[0,0,0,3]), + ok = do_test_switch_active_and_packet([0,0,0,4,0],[0,0,3]), + ok = do_test_switch_active_and_packet([0,0,0,4,0,0],[0,3]), + ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0],[3]), + ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0,3],[]), ok. @@ -200,181 +200,180 @@ test_switch_active_and_packet() -> %% Handshake tests %% pending_up_md5(Node,OurName,Cookie) -> - ?line {NA,NB} = split(Node), - ?line {port,PortNo,_} = erl_epmd:port_please(NA,NB), - ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, - [{active,false}, - {packet,2}]), - ?line send_name(SocketA,OurName,5), - ?line ok = recv_status(SocketA), - ?line {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1) - ?line OurChallengeA = gen_challenge(), - ?line OurDigestA = gen_digest(HisChallengeA, Cookie), - ?line send_challenge_reply(SocketA, OurChallengeA, OurDigestA), - ?line ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie), - %%% - %%% OK, one connection is up, now lets be nasty and try another up: - %%% - %%% But wait for a while, the other node might not have done setnode - %%% just yet... - ?line receive after 1000 -> ok end, - ?line {ok, SocketB} = gen_tcp:connect(atom_to_list(NB),PortNo, - [{active,false}, - {packet,2}]), - ?line send_name(SocketB,OurName,5), - ?line alive = recv_status(SocketB), - ?line send_status(SocketB, true), - ?line gen_tcp:close(SocketA), - ?line {hidden,Node,5,HisChallengeB} = recv_challenge(SocketB), % See 1) - ?line OurChallengeB = gen_challenge(), - ?line OurDigestB = gen_digest(HisChallengeB, Cookie), - ?line send_challenge_reply(SocketB, OurChallengeB, OurDigestB), - ?line ok = recv_challenge_ack(SocketB, OurChallengeB, Cookie), - %%% - %%% Well, are we happy? - %%% - - ?line inet:setopts(SocketB, [{active, false}, - {packet, 4}]), - ?line gen_tcp:send(SocketB,build_rex_message('',OurName)), - ?line {Header, Message} = recv_message(SocketB), - ?line io:format("Received header ~p, data ~p.~n", + {NA,NB} = split(Node), + {port,PortNo,_} = erl_epmd:port_please(NA,NB), + {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, + [{active,false}, + {packet,2}]), + send_name(SocketA,OurName,5), + ok = recv_status(SocketA), + {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1) + OurChallengeA = gen_challenge(), + OurDigestA = gen_digest(HisChallengeA, Cookie), + send_challenge_reply(SocketA, OurChallengeA, OurDigestA), + ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie), +%%% +%%% OK, one connection is up, now lets be nasty and try another up: +%%% +%%% But wait for a while, the other node might not have done setnode +%%% just yet... + receive after 1000 -> ok end, + {ok, SocketB} = gen_tcp:connect(atom_to_list(NB),PortNo, + [{active,false}, + {packet,2}]), + send_name(SocketB,OurName,5), + alive = recv_status(SocketB), + send_status(SocketB, true), + gen_tcp:close(SocketA), + {hidden,Node,5,HisChallengeB} = recv_challenge(SocketB), % See 1) + OurChallengeB = gen_challenge(), + OurDigestB = gen_digest(HisChallengeB, Cookie), + send_challenge_reply(SocketB, OurChallengeB, OurDigestB), + ok = recv_challenge_ack(SocketB, OurChallengeB, Cookie), +%%% +%%% Well, are we happy? +%%% + + inet:setopts(SocketB, [{active, false}, + {packet, 4}]), + gen_tcp:send(SocketB,build_rex_message('',OurName)), + {Header, Message} = recv_message(SocketB), + io:format("Received header ~p, data ~p.~n", [Header, Message]), - ?line gen_tcp:close(SocketB), + gen_tcp:close(SocketB), ok. simultaneous_md5(Node, OurName, Cookie) when OurName < Node -> - ?line pong = net_adm:ping(Node), - ?line LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of + pong = net_adm:ping(Node), + LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of {ok, Socket} -> Socket; Else -> exit(Else) end, - ?line EpmdSocket = register(OurName, LSocket, 1, 5), - ?line {NA, NB} = split(Node), - ?line rpc:cast(Node, net_adm, ping, [OurName]), - ?line receive after 1000 -> ok end, - ?line {port, PortNo, _} = erl_epmd:port_please(NA,NB), - ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, - [{active,false}, - {packet,2}]), - ?line send_name(SocketA,OurName,5), + EpmdSocket = register(OurName, LSocket, 1, 5), + {NA, NB} = split(Node), + rpc:cast(Node, net_adm, ping, [OurName]), + receive after 1000 -> ok end, + {port, PortNo, _} = erl_epmd:port_please(NA,NB), + {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, + [{active,false}, + {packet,2}]), + send_name(SocketA,OurName,5), %% We are still not marked up on the other side, as our first message %% is not sent. - ?line SocketB = case gen_tcp:accept(LSocket) of + SocketB = case gen_tcp:accept(LSocket) of {ok, Socket1} -> - ?line Socket1; + Socket1; Else2 -> - ?line exit(Else2) + exit(Else2) end, - ?line nok = recv_status(SocketA), - % Now we are expected to close A - ?line gen_tcp:close(SocketA), - % But still Socket B will continue - ?line {normal,Node,5} = recv_name(SocketB), % See 1) - ?line send_status(SocketB, ok_simultaneous), - ?line MyChallengeB = gen_challenge(), - ?line send_challenge(SocketB, OurName, MyChallengeB,5), - ?line HisChallengeB = recv_challenge_reply(SocketB, MyChallengeB, Cookie), - ?line DigestB = gen_digest(HisChallengeB,Cookie), - ?line send_challenge_ack(SocketB, DigestB), - ?line inet:setopts(SocketB, [{active, false}, - {packet, 4}]), - % This should be the ping message. - ?line {Header, Message} = recv_message(SocketB), - ?line io:format("Received header ~p, data ~p.~n", + nok = recv_status(SocketA), + %% Now we are expected to close A + gen_tcp:close(SocketA), + %% But still Socket B will continue + {normal,Node,5} = recv_name(SocketB), % See 1) + send_status(SocketB, ok_simultaneous), + MyChallengeB = gen_challenge(), + send_challenge(SocketB, OurName, MyChallengeB,5), + HisChallengeB = recv_challenge_reply(SocketB, MyChallengeB, Cookie), + DigestB = gen_digest(HisChallengeB,Cookie), + send_challenge_ack(SocketB, DigestB), + inet:setopts(SocketB, [{active, false}, + {packet, 4}]), + %% This should be the ping message. + {Header, Message} = recv_message(SocketB), + io:format("Received header ~p, data ~p.~n", [Header, Message]), - ?line gen_tcp:close(SocketB), - ?line gen_tcp:close(LSocket), - ?line gen_tcp:close(EpmdSocket), + gen_tcp:close(SocketB), + gen_tcp:close(LSocket), + gen_tcp:close(EpmdSocket), ok; - + simultaneous_md5(Node, OurName, Cookie) when OurName > Node -> - ?line pong = net_adm:ping(Node), - ?line LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of - {ok, Socket} -> - ?line Socket; - Else -> - ?line exit(Else) - end, - ?line EpmdSocket = register(OurName, LSocket, 1, 5), - ?line {NA, NB} = split(Node), - ?line rpc:cast(Node, net_adm, ping, [OurName]), - ?line receive after 1000 -> ok end, - ?line {port, PortNo, _} = erl_epmd:port_please(NA,NB), - ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, - [{active,false}, - {packet,2}]), - ?line SocketB = case gen_tcp:accept(LSocket) of + pong = net_adm:ping(Node), + LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of + {ok, Socket} -> + Socket; + Else -> + exit(Else) + end, + EpmdSocket = register(OurName, LSocket, 1, 5), + {NA, NB} = split(Node), + rpc:cast(Node, net_adm, ping, [OurName]), + receive after 1000 -> ok end, + {port, PortNo, _} = erl_epmd:port_please(NA,NB), + {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, + [{active,false}, + {packet,2}]), + SocketB = case gen_tcp:accept(LSocket) of {ok, Socket1} -> - ?line Socket1; + Socket1; Else2 -> - ?line exit(Else2) + exit(Else2) end, - ?line send_name(SocketA,OurName,5), - ?line ok_simultaneous = recv_status(SocketA), + send_name(SocketA,OurName,5), + ok_simultaneous = recv_status(SocketA), %% Socket B should die during this - ?line case catch begin - ?line {normal,Node,5} = recv_name(SocketB), % See 1) - ?line send_status(SocketB, ok_simultaneous), - ?line MyChallengeB = gen_challenge(), - ?line send_challenge(SocketB, OurName, MyChallengeB, - 5), - ?line HisChallengeB = recv_challenge_reply( - SocketB, - MyChallengeB, - Cookie), - ?line DigestB = gen_digest(HisChallengeB,Cookie), - ?line send_challenge_ack(SocketB, DigestB), - ?line inet:setopts(SocketB, [{active, false}, - {packet, 4}]), - ?line {HeaderB, MessageB} = recv_message(SocketB), - ?line io:format("Received header ~p, data ~p.~n", - [HeaderB, MessageB]) - end of - {'EXIT', Exitcode} -> - ?line io:format("Expected exitsignal caught: ~p.~n", - [Exitcode]); - Success -> - ?line io:format("Unexpected success: ~p~n", - [Success]), - ?line exit(unexpected_success) - end, - ?line gen_tcp:close(SocketB), + case catch begin + {normal,Node,5} = recv_name(SocketB), % See 1) + send_status(SocketB, ok_simultaneous), + MyChallengeB = gen_challenge(), + send_challenge(SocketB, OurName, MyChallengeB, + 5), + HisChallengeB = recv_challenge_reply( + SocketB, + MyChallengeB, + Cookie), + DigestB = gen_digest(HisChallengeB,Cookie), + send_challenge_ack(SocketB, DigestB), + inet:setopts(SocketB, [{active, false}, + {packet, 4}]), + {HeaderB, MessageB} = recv_message(SocketB), + io:format("Received header ~p, data ~p.~n", + [HeaderB, MessageB]) + end of + {'EXIT', Exitcode} -> + io:format("Expected exitsignal caught: ~p.~n", + [Exitcode]); + Success -> + io:format("Unexpected success: ~p~n", + [Success]), + exit(unexpected_success) + end, + gen_tcp:close(SocketB), %% But still Socket A will continue - ?line {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1) - ?line OurChallengeA = gen_challenge(), - ?line OurDigestA = gen_digest(HisChallengeA, Cookie), - ?line send_challenge_reply(SocketA, OurChallengeA, OurDigestA), - ?line ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie), - - ?line inet:setopts(SocketA, [{active, false}, - {packet, 4}]), - ?line gen_tcp:send(SocketA,build_rex_message('',OurName)), - ?line {Header, Message} = recv_message(SocketA), - ?line io:format("Received header ~p, data ~p.~n", + {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1) + OurChallengeA = gen_challenge(), + OurDigestA = gen_digest(HisChallengeA, Cookie), + send_challenge_reply(SocketA, OurChallengeA, OurDigestA), + ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie), + + inet:setopts(SocketA, [{active, false}, + {packet, 4}]), + gen_tcp:send(SocketA,build_rex_message('',OurName)), + {Header, Message} = recv_message(SocketA), + io:format("Received header ~p, data ~p.~n", [Header, Message]), - ?line gen_tcp:close(SocketA), - ?line gen_tcp:close(LSocket), - ?line gen_tcp:close(EpmdSocket), + gen_tcp:close(SocketA), + gen_tcp:close(LSocket), + gen_tcp:close(EpmdSocket), ok. -missing_compulsory_dflags(doc) -> []; missing_compulsory_dflags(Config) when is_list(Config) -> - ?line [Name1, Name2] = get_nodenames(2, missing_compulsory_dflags), - ?line {ok, Node} = start_node(Name1,""), - ?line {NA,NB} = split(Node), - ?line {port,PortNo,_} = erl_epmd:port_please(NA,NB), - ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, - [{active,false}, - {packet,2}]), - ?line BadNode = list_to_atom(atom_to_list(Name2)++"@"++atom_to_list(NB)), - ?line send_name(SocketA,BadNode,5,0), - ?line not_allowed = recv_status(SocketA), - ?line gen_tcp:close(SocketA), - ?line stop_node(Node), - ?line ok. + [Name1, Name2] = get_nodenames(2, missing_compulsory_dflags), + {ok, Node} = start_node(Name1,""), + {NA,NB} = split(Node), + {port,PortNo,_} = erl_epmd:port_please(NA,NB), + {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, + [{active,false}, + {packet,2}]), + BadNode = list_to_atom(atom_to_list(Name2)++"@"++atom_to_list(NB)), + send_name(SocketA,BadNode,5,0), + not_allowed = recv_status(SocketA), + gen_tcp:close(SocketA), + stop_node(Node), + ok. %% %% Here comes the utilities @@ -437,7 +436,7 @@ socket_pair(ClientPack, ServerPack) -> {ok, Server} = gen_tcp:accept(Listen), gen_tcp:close(Listen), {Client, Server}. - + close_pair({Client, Server}) -> gen_tcp:close(Client), gen_tcp:close(Server), @@ -454,7 +453,7 @@ close_pair({Client, Server}) -> gen_challenge() -> rand:uniform(1000000). - + %% Generate a message digest from Challenge number and Cookie gen_digest(Challenge, Cookie) when is_integer(Challenge), is_atom(Cookie) -> C0 = erlang:md5_init(), @@ -595,15 +594,15 @@ do_register_node(NodeName, TcpPort, VLow, VHigh) -> Elen = length(Extra), Len = 1+2+1+1+2+2+2+length(Name)+2+Elen, gen_tcp:send(Socket, [?int16(Len), $x, - ?int16(TcpPort), - $M, - 0, - ?int16(VHigh), - ?int16(VLow), - ?int16(length(Name)), - Name, - ?int16(Elen), - Extra]), + ?int16(TcpPort), + $M, + 0, + ?int16(VHigh), + ?int16(VLow), + ?int16(length(Name)), + Name, + ?int16(Elen), + Extra]), case wait_for_reg_reply(Socket, []) of {error, epmd_close} -> exit(epmd_broken); @@ -666,11 +665,11 @@ split(Atom) -> build_rex_message(Cookie,OurName) -> [$?,term_to_binary({6,self(),Cookie,rex}), term_to_binary({'$gen_cast', - {cast, - rpc, - cast, - [OurName, hello, world, []], - self()} })]. + {cast, + rpc, + cast, + [OurName, hello, world, []], + self()} })]. %% Receive a distribution message recv_message(Socket) -> @@ -698,10 +697,10 @@ join(Name,Host) -> %% start/stop slave. start_node(Name, Param) -> - ?t:start_node(Name, slave, [{args, Param}]). + test_server:start_node(Name, slave, [{args, Param}]). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). get_nodenames(N, T) -> diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index 0803cf428f..b6417210b9 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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,31 +20,35 @@ -module(erl_prim_loader_SUITE). -include_lib("kernel/include/file.hrl"). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, + init_per_testcase/2,end_per_testcase/2, init_per_group/2,end_per_group/2]). -export([get_path/1, set_path/1, get_file/1, normalize_and_backslash/1, inet_existing/1, inet_coming_up/1, inet_disconnects/1, multiple_slaves/1, file_requests/1, local_archive/1, remote_archive/1, - primary_archive/1, virtual_dir_in_archive/1]). + primary_archive/1, virtual_dir_in_archive/1, + get_modules/1]). --export([init_per_testcase/2, end_per_testcase/2]). %%----------------------------------------------------------------- %% Test suite for erl_prim_loader. (Most code is run during system start/stop.) %%----------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,3}}]. all() -> [get_path, set_path, get_file, normalize_and_backslash, inet_existing, inet_coming_up, inet_disconnects, multiple_slaves, file_requests, local_archive, remote_archive, - primary_archive, virtual_dir_in_archive]. + primary_archive, virtual_dir_in_archive, + get_modules]. groups() -> []. @@ -62,53 +66,102 @@ end_per_group(_GroupName, Config) -> Config. -init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog=?t:timetrap(?t:minutes(3)), - [{watchdog, Dog}|Config]. +init_per_testcase(_Func, Config) -> + Config. -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. -get_path(doc) -> []; get_path(Config) when is_list(Config) -> - ?line case erl_prim_loader:get_path() of - {ok, Path} when is_list(Path) -> - ok; - _ -> - test_server:fail(get_path) - end, + case erl_prim_loader:get_path() of + {ok, Path} when is_list(Path) -> + ok; + _ -> + ct:fail(get_path) + end, ok. -set_path(doc) -> []; set_path(Config) when is_list(Config) -> - ?line {ok, Path} = erl_prim_loader:get_path(), - ?line ok = erl_prim_loader:set_path(Path), - ?line {ok, Path} = erl_prim_loader:get_path(), + {ok, Path} = erl_prim_loader:get_path(), + ok = erl_prim_loader:set_path(Path), + {ok, Path} = erl_prim_loader:get_path(), NewPath = Path ++ ["dummy_dir","/dummy_dir/dummy_dir"], - ?line ok = erl_prim_loader:set_path(NewPath), - ?line {ok, NewPath} = erl_prim_loader:get_path(), + ok = erl_prim_loader:set_path(NewPath), + {ok, NewPath} = erl_prim_loader:get_path(), - ?line ok = erl_prim_loader:set_path(Path), % Reset path. - ?line {ok, Path} = erl_prim_loader:get_path(), + ok = erl_prim_loader:set_path(Path), % Reset path. + {ok, Path} = erl_prim_loader:get_path(), - ?line {'EXIT',_} = (catch erl_prim_loader:set_path(not_a_list)), - ?line {ok, Path} = erl_prim_loader:get_path(), + {'EXIT',_} = (catch erl_prim_loader:set_path(not_a_list)), + {ok, Path} = erl_prim_loader:get_path(), ok. -get_file(doc) -> []; get_file(Config) when is_list(Config) -> - ?line case erl_prim_loader:get_file("lists" ++ code:objfile_extension()) of - {ok,Bin,File} when is_binary(Bin), is_list(File) -> - ok; - _ -> - test_server:fail(get_valid_file) - end, - ?line error = erl_prim_loader:get_file("duuuuuuummmy_file"), - ?line error = erl_prim_loader:get_file(duuuuuuummmy_file), - ?line error = erl_prim_loader:get_file({dummy}), + case erl_prim_loader:get_file("lists" ++ code:objfile_extension()) of + {ok,Bin,File} when is_binary(Bin), is_list(File) -> + ok; + _ -> + ct:fail(get_valid_file) + end, + error = erl_prim_loader:get_file("duuuuuuummmy_file"), + error = erl_prim_loader:get_file(duuuuuuummmy_file), + error = erl_prim_loader:get_file({dummy}), + ok. + +get_modules(Config) -> + case test_server:is_cover() of + false -> do_get_modules(Config); + true -> {skip,"Cover"} + end. + +do_get_modules(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + NotADir = atom_to_list(?FUNCTION_NAME) ++ "_not_a_dir", + ok = file:write_file(filename:join(PrivDir, NotADir), <<>>), + ok = file:set_cwd(PrivDir), + + MsGood = lists:sort([lists,gen_server,gb_trees,code_server]), + Ms = [certainly_not_existing|MsGood], + SuccExp = [begin + F = code:which(M), + {ok,Code} = file:read_file(F), + {M,{F,erlang:md5(Code)}} + end || M <- MsGood], + FailExp = [{certainly_not_existing,enoent}], + + io:format("SuccExp = ~p\n", [SuccExp]), + io:format("FailExp = ~p\n", [FailExp]), + + Path = code:get_path(), + Process = fun(_, F, Code) -> {ok,{F,erlang:md5(Code)}} end, + {ok,{SuccExp,FailExp}} = get_modules_sorted(Ms, Process, Path), + + %% Test that an 'enotdir' error can be handled. + {ok,{SuccExp,FailExp}} = get_modules_sorted(Ms, Process, [NotADir|Path]), + + Name = inet_get_modules, + {ok, Node, BootPid} = complete_start_node(Name), + ThisDir = filename:dirname(code:which(?MODULE)), + true = rpc:call(Node, code, add_patha, [ThisDir]), + _ = rpc:call(Node, code, ensure_loaded, [?MODULE]), + {ok,{InetSucc,FailExp}} = rpc:call(Node, erl_prim_loader, + get_modules, [Ms,Process,Path]), + SuccExp = lists:sort(InetSucc), + + stop_node(Node), + unlink(BootPid), + exit(BootPid, kill), + ok. +get_modules_sorted(Ms, Process, Path) -> + case erl_prim_loader:get_modules(Ms, Process, Path) of + {ok,{Succ,FailExp}} -> + {ok,{lists:sort(Succ),lists:sort(FailExp)}}; + Other -> + Other + end. + normalize_and_backslash(Config) -> %% Test OTP-11170 case os:type() of @@ -118,7 +171,7 @@ normalize_and_backslash(Config) -> test_normalize_and_backslash(Config) end. test_normalize_and_backslash(Config) -> - PrivDir = ?config(priv_dir,Config), + PrivDir = proplists:get_value(priv_dir,Config), Dir = filename:join(PrivDir,"\\"), File = filename:join(Dir,"file-OTP-11170"), ok = file:make_dir(Dir), @@ -129,41 +182,27 @@ test_normalize_and_backslash(Config) -> ok = file:del_dir(Dir), ok. -inet_existing(doc) -> ["Start a node using the 'inet' loading method, ", - "from an already started boot server."]; +%% Start a node using the 'inet' loading method, +%% from an already started boot server. inet_existing(Config) when is_list(Config) -> Name = erl_prim_test_inet_existing, - Host = host(), - Cookie = atom_to_list(erlang:get_cookie()), - IpStr = ip_str(Host), - LFlag = get_loader_flag(os:type()), - Args = LFlag ++ " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - {ok, BootPid} = erl_boot_server:start_link([Host]), - {ok, Node} = start_node(Name, Args), + BootPid = start_boot_server(), + Node = start_node_using_inet(Name), {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), stop_node(Node), unlink(BootPid), exit(BootPid, kill), ok. -inet_coming_up(doc) -> ["Start a node using the 'inet' loading method, ", - "but start the boot server afterwards."]; +%% Start a node using the 'inet' loading method, +%% but start the boot server afterwards. inet_coming_up(Config) when is_list(Config) -> Name = erl_prim_test_inet_coming_up, - Cookie = atom_to_list(erlang:get_cookie()), - Host = host(), - IpStr = ip_str(Host), - LFlag = get_loader_flag(os:type()), - Args = LFlag ++ - " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - {ok, Node} = start_node(Name, Args, [{wait, false}]), + Node = start_node_using_inet(Name, [{wait,false}]), %% Wait a while, then start boot server, and wait for node to start. - test_server:sleep(test_server:seconds(6)), - io:format("erl_boot_server:start_link([~p]).", [Host]), - {ok, BootPid} = erl_boot_server:start_link([Host]), + ct:sleep({seconds,6}), + BootPid = start_boot_server(), wait_really_started(Node, 25), %% Check loader argument, then cleanup. @@ -174,41 +213,36 @@ inet_coming_up(Config) when is_list(Config) -> ok. wait_really_started(Node, 0) -> - test_server:fail({not_booted,Node}); + ct:fail({not_booted,Node}); wait_really_started(Node, N) -> case rpc:call(Node, init, get_status, []) of {started, _} -> ok; _ -> - test_server:sleep(1000), + ct:sleep(1000), wait_really_started(Node, N - 1) end. -inet_disconnects(doc) -> ["Start a node using the 'inet' loading method, ", - "then lose the connection."]; +%% Start a node using the 'inet' loading method, +%% then lose the connection. inet_disconnects(Config) when is_list(Config) -> case test_server:is_native(erl_boot_server) of true -> {skip,"erl_boot_server is native"}; false -> - ?line Name = erl_prim_test_inet_disconnects, - ?line Host = host(), - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line IpStr = ip_str(Host), - ?line LFlag = get_loader_flag(os:type()), - ?line Args = LFlag ++ " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - - ?line {ok, BootPid} = erl_boot_server:start([Host]), + Name = erl_prim_test_inet_disconnects, + + BootPid = start_boot_server(), + unlink(BootPid), Self = self(), %% This process shuts down the boot server during loading. - ?line Stopper = spawn_link(fun() -> stop_boot(BootPid, Self) end), - ?line receive - {Stopper,ready} -> ok - end, + Stopper = spawn_link(fun() -> stop_boot(BootPid, Self) end), + receive + {Stopper,ready} -> ok + end, %% Let the loading begin... - ?line {ok, Node} = start_node(Name, Args, [{wait, false}]), + Node = start_node_using_inet(Name, [{wait,false}]), %% When the stopper is ready, the slave node should be %% looking for a boot server again. @@ -216,18 +250,18 @@ inet_disconnects(Config) when is_list(Config) -> {Stopper,ok} -> ok; {Stopper,{error,Reason}} -> - ?line ?t:fail(Reason) + ct:fail(Reason) after 60000 -> - ?line ?t:fail(stopper_died) + ct:fail(stopper_died) end, %% Start new boot server to see that loading is continued. - ?line {ok, BootPid2} = erl_boot_server:start_link([Host]), - ?line wait_really_started(Node, 25), - ?line {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), - ?line stop_node(Node), - ?line unlink(BootPid2), - ?line exit(BootPid2, kill), + BootPid2 = start_boot_server(), + wait_really_started(Node, 25), + {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), + stop_node(Node), + unlink(BootPid2), + exit(BootPid2, kill), ok end. @@ -256,81 +290,72 @@ get_calls(Count, Pid) -> {error,{trace_msg_timeout,Count}} end. -multiple_slaves(doc) -> - ["Start nodes in parallell, all using the 'inet' loading method, ", - "verify that the boot server manages"]; +%% Start nodes in parallel, all using the 'inet' loading method; +%% verify that the boot server manages. multiple_slaves(Config) when is_list(Config) -> - case os:type() of - {ose,_} -> - {comment, "OSE: multiple nodes not supported"}; - _ -> - ?line Name = erl_prim_test_multiple_slaves, - ?line Host = host(), - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line IpStr = ip_str(Host), - ?line LFlag = get_loader_flag(os:type()), - ?line Args = LFlag ++ " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - - NoOfNodes = 10, % no of slave nodes to be started - - NamesAndNodes = - lists:map(fun(N) -> - NameN = atom_to_list(Name) ++ - integer_to_list(N), - NodeN = NameN ++ "@" ++ Host, - {list_to_atom(NameN),list_to_atom(NodeN)} - end, lists:seq(1, NoOfNodes)), - - ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []), - - %% "queue up" the nodes to wait for the boot server to respond - %% (note: test_server supervises each node start by accept() - %% on a socket, the timeout value for the accept has to be quite - %% long for this test to work). - ?line test_server:sleep(test_server:seconds(5)), - %% start the code loading circus! - ?line {ok,BootPid} = erl_boot_server:start_link([Host]), - %% give the nodes a chance to boot up before attempting to stop them - ?line test_server:sleep(test_server:seconds(10)), - - ?line wait_and_shutdown(lists:reverse(Nodes), 30), - - ?line unlink(BootPid), - ?line exit(BootPid, kill), - ok - end. + Name = erl_prim_test_multiple_slaves, + Host = host(), + IpStr = ip_str(Host), + Args = " -loader inet -hosts " ++ IpStr, + + NoOfNodes = 10, % no of slave nodes to be started + + NamesAndNodes = + lists:map(fun(N) -> + NameN = atom_to_list(Name) ++ + integer_to_list(N), + NodeN = NameN ++ "@" ++ Host, + {list_to_atom(NameN),list_to_atom(NodeN)} + end, lists:seq(1, NoOfNodes)), + + Nodes = start_multiple_nodes(NamesAndNodes, Args, []), + + %% "queue up" the nodes to wait for the boot server to respond + %% (note: test_server supervises each node start by accept() + %% on a socket, the timeout value for the accept has to be quite + %% long for this test to work). + ct:sleep({seconds,5}), + %% start the code loading circus! + BootPid = start_boot_server(), + %% give the nodes a chance to boot up before attempting to stop them + ct:sleep({seconds,10}), + + wait_and_shutdown(lists:reverse(Nodes), 30), + + unlink(BootPid), + exit(BootPid, kill), + ok. start_multiple_nodes([{Name,Node} | NNs], Args, Started) -> - ?line {ok,Node} = start_node(Name, Args, [{wait, false}]), + {ok,Node} = start_node(Name, Args, [{wait, false}]), start_multiple_nodes(NNs, Args, [Node | Started]); start_multiple_nodes([], _, Nodes) -> Nodes. wait_and_shutdown([Node | Nodes], Tries) -> - ?line wait_really_started(Node, Tries), - ?line {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), - ?line stop_node(Node), + wait_really_started(Node, Tries), + {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), + stop_node(Node), wait_and_shutdown(Nodes, Tries); wait_and_shutdown([], _) -> ok. -file_requests(doc) -> ["Start a node using the 'inet' loading method, ", - "verify that the boot server responds to file requests."]; +%% Start a node using the 'inet' loading method, +%% verify that the boot server responds to file requests. file_requests(Config) when is_list(Config) -> - ?line {ok, Node, BootPid} = complete_start_node(erl_prim_test_file_req), + {ok, Node, BootPid} = complete_start_node(erl_prim_test_file_req), %% compare with results from file server calls (the %% boot server uses the same file sys and cwd) {ok,Files} = file:list_dir("."), io:format("Files: ~p~n",[Files]), - ?line {ok,Files} = rpc:call(Node, erl_prim_loader, list_dir, ["."]), + {ok,Files} = rpc:call(Node, erl_prim_loader, list_dir, ["."]), {ok,Info} = file:read_file_info(code:which(test_server)), - ?line {ok,Info} = rpc:call(Node, erl_prim_loader, read_file_info, - [code:which(test_server)]), + {ok,Info} = rpc:call(Node, erl_prim_loader, read_file_info, + [code:which(test_server)]), - PrivDir = ?config(priv_dir,Config), + PrivDir = proplists:get_value(priv_dir,Config), Dir = filename:join(PrivDir,?MODULE_STRING++"_file_requests"), ok = file:make_dir(Dir), Alias = filename:join(Dir,"symlink"), @@ -354,163 +379,140 @@ file_requests(Config) when is_list(Config) -> end, {ok,Cwd} = file:get_cwd(), - ?line {ok,Cwd} = rpc:call(Node, erl_prim_loader, get_cwd, []), + {ok,Cwd} = rpc:call(Node, erl_prim_loader, get_cwd, []), case file:get_cwd("C:") of {error,enotsup} -> ok; {ok,DCwd} -> - ?line {ok,DCwd} = rpc:call(Node, erl_prim_loader, get_cwd, ["C:"]) + {ok,DCwd} = rpc:call(Node, erl_prim_loader, get_cwd, ["C:"]) end, - ?line stop_node(Node), - ?line unlink(BootPid), - ?line exit(BootPid, kill), + stop_node(Node), + unlink(BootPid), + exit(BootPid, kill), ok. -complete_start_node(Name) -> - ?line Host = host(), - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line IpStr = ip_str(Host), - ?line LFlag = get_loader_flag(os:type()), - ?line Args = LFlag ++ " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - - ?line {ok,BootPid} = erl_boot_server:start_link([Host]), - - ?line {ok,Node} = start_node(Name, Args), - ?line wait_really_started(Node, 25), - {ok, Node, BootPid}. - -local_archive(suite) -> - []; -local_archive(doc) -> - ["Read files from local archive."]; +%% Read files from local archive. local_archive(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), KernelDir = filename:basename(code:lib_dir(kernel)), Archive = filename:join([PrivDir, KernelDir ++ init:archive_extension()]), file:delete(Archive), - ?line {ok, Archive} = create_archive(Archive, [KernelDir]), + {ok, Archive} = create_archive(Archive, [KernelDir]), Node = node(), BeamName = "inet.beam", - ?line ok = test_archive(Node, Archive, KernelDir, BeamName), + ok = test_archive(Node, Archive, KernelDir, BeamName), %% Cleanup - ?line ok = rpc:call(Node, erl_prim_loader, release_archives, []), - ?line ok = file:delete(Archive), + ok = rpc:call(Node, erl_prim_loader, purge_archive_cache, []), + ok = file:delete(Archive), ok. -remote_archive(suite) -> - {req, [{local_slave_nodes, 1}, {time, 10}]}; -remote_archive(doc) -> - ["Read files from remote archive."]; +%% Read files from remote archive. remote_archive(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), KernelDir = filename:basename(code:lib_dir(kernel)), Archive = filename:join([PrivDir, KernelDir ++ init:archive_extension()]), file:delete(Archive), - ?line {ok, Archive} = create_archive(Archive, [KernelDir]), + {ok, Archive} = create_archive(Archive, [KernelDir]), - ?line {ok, Node, BootPid} = complete_start_node(remote_archive), + {ok, Node, BootPid} = complete_start_node(remote_archive), BeamName = "inet.beam", - ?line ok = test_archive(Node, Archive, KernelDir, BeamName), + ok = test_archive(Node, Archive, KernelDir, BeamName), %% Cleanup - ?line stop_node(Node), - ?line unlink(BootPid), - ?line exit(BootPid, kill), + stop_node(Node), + unlink(BootPid), + exit(BootPid, kill), ok. -primary_archive(suite) -> - {req, [{local_slave_nodes, 1}, {time, 10}]}; -primary_archive(doc) -> - ["Read files from primary archive."]; +%% Read files from primary archive. primary_archive(Config) when is_list(Config) -> %% Copy the orig files to priv_dir - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Archive = filename:join([PrivDir, "primary_archive.zip"]), file:delete(Archive), - DataDir = ?config(data_dir, Config), - ?line {ok, _} = zip:create(Archive, ["primary_archive"], - [{compress, []}, {cwd, DataDir}]), - ?line {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]), + DataDir = proplists:get_value(data_dir, Config), + {ok, _} = zip:create(Archive, ["primary_archive"], + [{compress, []}, {cwd, DataDir}]), + {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]), TopDir = filename:join([PrivDir, "primary_archive"]), %% Compile the code DictDir = "primary_archive_dict-1.0", DummyDir = "primary_archive_dummy", - ?line ok = compile_app(TopDir, DictDir), - ?line ok = compile_app(TopDir, DummyDir), - + ok = compile_app(TopDir, DictDir), + ok = compile_app(TopDir, DummyDir), + %% Create the archive {ok, TopFiles} = file:list_dir(TopDir), - ?line {ok, {_, ArchiveBin}} = zip:create(Archive, TopFiles, - [memory, {compress, []}, {cwd, TopDir}]), - + {ok, {_, ArchiveBin}} = zip:create(Archive, TopFiles, + [memory, {compress, []}, {cwd, TopDir}]), + %% Use temporary node to simplify cleanup - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line Args = " -setcookie " ++ Cookie, - ?line {ok,Node} = start_node(primary_archive, Args), - ?line wait_really_started(Node, 25), - ?line {_,_,_} = rpc:call(Node, erlang, date, []), + Cookie = atom_to_list(erlang:get_cookie()), + Args = " -setcookie " ++ Cookie, + {ok,Node} = start_node(primary_archive, Args), + wait_really_started(Node, 25), + {_,_,_} = rpc:call(Node, erlang, date, []), %% Set primary archive ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"], io:format("ExpectedEbins: ~p\n", [ExpectedEbins]), - ?line {ok, FileInfo} = prim_file:read_file_info(Archive), - ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, - [Archive, ArchiveBin, FileInfo, - fun escript:parse_file/1]), - ?line ExpectedEbins = lists:sort(Ebins), % assert - - ?line {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]), - ?line [DictDir, DummyDir] = lists:sort(TopFiles2), + {ok, FileInfo} = prim_file:read_file_info(Archive), + {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, + [Archive, ArchiveBin, FileInfo, + fun escript:parse_file/1]), + ExpectedEbins = lists:sort(Ebins), % assert + + {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]), + [DictDir, DummyDir] = lists:sort(TopFiles2), BeamName = "primary_archive_dict_app.beam", - ?line ok = test_archive(Node, Archive, DictDir, BeamName), - + ok = test_archive(Node, Archive, DictDir, BeamName), + %% Cleanup - ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, - [undefined, undefined, undefined, - fun escript:parse_file/1]), - ?line stop_node(Node), - ?line ok = file:delete(Archive), + {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, + [undefined, undefined, undefined, + fun escript:parse_file/1]), + stop_node(Node), + ok = file:delete(Archive), ok. test_archive(Node, TopDir, AppDir, BeamName) -> %% List dir io:format("test_archive: ~p\n", [rpc:call(Node, erl_prim_loader, list_dir, [TopDir])]), - ?line {ok, TopFiles} = rpc:call(Node, erl_prim_loader, list_dir, [TopDir]), - ?line true = lists:member(AppDir, TopFiles), + {ok, TopFiles} = rpc:call(Node, erl_prim_loader, list_dir, [TopDir]), + true = lists:member(AppDir, TopFiles), AbsAppDir = TopDir ++ "/" ++ AppDir, - ?line {ok, AppFiles} = rpc:call(Node, erl_prim_loader, list_dir, [AbsAppDir]), - ?line true = lists:member("ebin", AppFiles), + {ok, AppFiles} = rpc:call(Node, erl_prim_loader, list_dir, [AbsAppDir]), + true = lists:member("ebin", AppFiles), Ebin = AbsAppDir ++ "/ebin", - ?line {ok, EbinFiles} = rpc:call(Node, erl_prim_loader, list_dir, [Ebin]), + {ok, EbinFiles} = rpc:call(Node, erl_prim_loader, list_dir, [Ebin]), Beam = Ebin ++ "/" ++ BeamName, - ?line true = lists:member(BeamName, EbinFiles), - ?line error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/no_such_file"]), - ?line error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/ebin/no_such_file"]), - + true = lists:member(BeamName, EbinFiles), + error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/no_such_file"]), + error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/ebin/no_such_file"]), + %% File info - ?line {ok, #file_info{type = directory}} = + {ok, #file_info{type = directory}} = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir]), - ?line {ok, #file_info{type = directory}} = + {ok, #file_info{type = directory}} = rpc:call(Node, erl_prim_loader, read_file_info, [Ebin]), - ?line {ok, #file_info{type = regular} = FI} = + {ok, #file_info{type = regular} = FI} = rpc:call(Node, erl_prim_loader, read_file_info, [Beam]), - ?line error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/no_such_file"]), - ?line error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/ebin/no_such_file"]), - + error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/no_such_file"]), + error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/ebin/no_such_file"]), + %% Get file - ?line {ok, Bin, Beam} = rpc:call(Node, erl_prim_loader, get_file, [Beam]), - ?line if - FI#file_info.size =:= byte_size(Bin) -> ok; - true -> exit({FI#file_info.size, byte_size(Bin)}) - end, - ?line error = rpc:call(Node, erl_prim_loader, get_file, ["/no_such_file"]), - ?line error = rpc:call(Node, erl_prim_loader, get_file, ["/ebin/no_such_file"]), + {ok, Bin, Beam} = rpc:call(Node, erl_prim_loader, get_file, [Beam]), + if + FI#file_info.size =:= byte_size(Bin) -> ok; + true -> exit({FI#file_info.size, byte_size(Bin)}) + end, + error = rpc:call(Node, erl_prim_loader, get_file, ["/no_such_file"]), + error = rpc:call(Node, erl_prim_loader, get_file, ["/ebin/no_such_file"]), ok. create_archive(Archive, AppDirs) -> @@ -520,12 +522,9 @@ create_archive(Archive, AppDirs) -> zip:create(Archive, AppDirs, Opts). -virtual_dir_in_archive(suite) -> - []; -virtual_dir_in_archive(doc) -> - ["Read virtual directories from archive."]; +%% Read virtual directories from archive. virtual_dir_in_archive(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Data = <<"A little piece of data.">>, ArchiveBase = "archive_with_virtual_dirs", Archive = filename:join([PrivDir, ArchiveBase ++ init:archive_extension()]), @@ -534,32 +533,62 @@ virtual_dir_in_archive(Config) when is_list(Config) -> FileInArchive = filename:join([ArchiveBase, EbinBase, FileBase]), BinFiles = [{FileInArchive, Data}], Opts = [{compress, []}], - ?line file:delete(Archive), + file:delete(Archive), io:format("zip:create(~p,\n\t~p,\n\t~p).\n", [Archive, BinFiles, Opts]), - ?line {ok, Archive} = zip:create(Archive, BinFiles, Opts), + {ok, Archive} = zip:create(Archive, BinFiles, Opts), %% Verify that there is no directories - ?line {ok, BinFiles} = zip:unzip(Archive, [memory]), + {ok, BinFiles} = zip:unzip(Archive, [memory]), FullPath = filename:join([Archive, FileInArchive]), - ?line {ok, _} = erl_prim_loader:read_file_info(FullPath), + {ok, _} = erl_prim_loader:read_file_info(FullPath), %% Read one virtual dir EbinDir = filename:dirname(FullPath), - ?line {ok, _} = erl_prim_loader:read_file_info(EbinDir), - ?line {ok, [FileBase]} = erl_prim_loader:list_dir(EbinDir), + {ok, _} = erl_prim_loader:read_file_info(EbinDir), + {ok, [FileBase]} = erl_prim_loader:list_dir(EbinDir), %% Read another virtual dir AppDir = filename:dirname(EbinDir), - ?line {ok, _} = erl_prim_loader:read_file_info(AppDir), - ?line {ok, [EbinBase]} = erl_prim_loader:list_dir(AppDir), - + {ok, _} = erl_prim_loader:read_file_info(AppDir), + {ok, [EbinBase]} = erl_prim_loader:list_dir(AppDir), + %% Cleanup - ?line ok = erl_prim_loader:release_archives(), - ?line ok = file:delete(Archive), + ok = erl_prim_loader:purge_archive_cache(), + ok = file:delete(Archive), ok. -%% Misc. functions +%%% +%%% Helper functions. +%%% + +complete_start_node(Name) -> + BootPid = start_boot_server(), + Node = start_node_using_inet(Name), + wait_really_started(Node, 25), + {ok, Node, BootPid}. + +start_boot_server() -> + %% Many linux systems define: + %% 127.0.0.1 localhost + %% 127.0.1.1 somehostname + %% Therefore, to allow the tests to work on those kind of systems, + %% also include "localhost" in the list of allowed hosts. + + Hosts = [host(),ip_str("localhost")], + {ok,BootPid} = erl_boot_server:start_link(Hosts), + BootPid. + +start_node_using_inet(Name) -> + start_node_using_inet(Name, []). + +start_node_using_inet(Name, Opts) -> + Host = host(), + IpStr = ip_str(Host), + Args = " -loader inet -hosts " ++ IpStr, + {ok,Node} = start_node(Name, Args, Opts), + Node. + ip_str({A, B, C, D}) -> lists:concat([A, ".", B, ".", C, ".", D]); @@ -585,14 +614,11 @@ host() -> stop_node(Node) -> test_server:stop_node(Node). -get_loader_flag(_) -> - " -loader inet ". - compile_app(TopDir, AppName) -> AppDir = filename:join([TopDir, AppName]), SrcDir = filename:join([AppDir, "src"]), OutDir = filename:join([AppDir, "ebin"]), - ?line {ok, Files} = file:list_dir(SrcDir), + {ok, Files} = file:list_dir(SrcDir), compile_files(Files, SrcDir, OutDir). compile_files([File | Files], SrcDir, OutDir) -> diff --git a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict.erl b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict.erl index 7d8167f575..57aeb7fd64 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_app.erl b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_app.erl index bf66179e00..78e4f61579 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_app.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_app.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_sup.erl b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_sup.erl index e57d8c5a00..e63e958daf 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_sup.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dict-1.0/src/primary_archive_dict_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy.erl b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy.erl index e1c7655331..4adbec3c81 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_app.erl b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_app.erl index e9db18c47e..e90776ce73 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_app.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_app.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_sup.erl b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_sup.erl index 7bab86be68..145de8167f 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_sup.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE_data/primary_archive/primary_archive_dummy/src/primary_archive_dummy_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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/kernel/test/error_handler_SUITE.erl b/lib/kernel/test/error_handler_SUITE.erl index d93ec643ce..c6d457f314 100644 --- a/lib/kernel/test/error_handler_SUITE.erl +++ b/lib/kernel/test/error_handler_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013. All Rights Reserved. +%% Copyright Ericsson AB 2013-2016. 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. @@ -26,7 +26,9 @@ %% Callback from error_handler. -export(['$handle_undefined_function'/2]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [undefined_function_handler]. diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl index f1988b68d9..2d26a7246c 100644 --- a/lib/kernel/test/error_logger_SUITE.erl +++ b/lib/kernel/test/error_logger_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -19,7 +19,7 @@ %% -module(error_logger_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %%----------------------------------------------------------------- %% We don't have to test the normal behaviour here, i.e. the tty @@ -30,6 +30,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, + off_heap/1, error_report/1, info_report/1, error/1, info/1, emulator/1, tty/1, logfile/1, add/1, delete/1]). @@ -40,10 +41,12 @@ terminate/2]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> - [error_report, info_report, error, info, emulator, tty, + [off_heap, error_report, info_report, error, info, emulator, tty, logfile, add, delete]. groups() -> @@ -64,159 +67,159 @@ end_per_group(_GroupName, Config) -> %%----------------------------------------------------------------- -error_report(suite) -> []; -error_report(doc) -> []; +off_heap(_Config) -> + %% The error_logger process may receive a huge amount of + %% messages. Make sure that they are stored off heap to + %% avoid exessive GCs. + MQD = message_queue_data, + {MQD,off_heap} = process_info(whereis(error_logger), MQD), + ok. + +%%----------------------------------------------------------------- + error_report(Config) when is_list(Config) -> - ?line error_logger:add_report_handler(?MODULE, self()), + error_logger:add_report_handler(?MODULE, self()), Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}], Rep2 = [testing,"testing",{tag1,"tag1"}], Rep3 = "This is a string !", Rep4 = {this,is,a,tuple}, - ?line ok = error_logger:error_report(Rep1), + ok = error_logger:error_report(Rep1), reported(error_report, std_error, Rep1), - ?line ok = error_logger:error_report(Rep2), + ok = error_logger:error_report(Rep2), reported(error_report, std_error, Rep2), - ?line ok = error_logger:error_report(Rep3), + ok = error_logger:error_report(Rep3), reported(error_report, std_error, Rep3), - ?line ok = error_logger:error_report(Rep4), + ok = error_logger:error_report(Rep4), reported(error_report, std_error, Rep4), - ?line ok = error_logger:error_report(test_type, Rep1), + ok = error_logger:error_report(test_type, Rep1), reported(error_report, test_type, Rep1), - ?line ok = error_logger:error_report(test_type, Rep2), + ok = error_logger:error_report(test_type, Rep2), reported(error_report, test_type, Rep2), - ?line ok = error_logger:error_report(test_type, Rep3), + ok = error_logger:error_report(test_type, Rep3), reported(error_report, test_type, Rep3), - ?line ok = error_logger:error_report(test_type, Rep4), + ok = error_logger:error_report(test_type, Rep4), reported(error_report, test_type, Rep4), - ?line ok = error_logger:error_report("test_type", Rep1), + ok = error_logger:error_report("test_type", Rep1), reported(error_report, "test_type", Rep1), - ?line ok = error_logger:error_report({test,type}, Rep2), + ok = error_logger:error_report({test,type}, Rep2), reported(error_report, {test,type}, Rep2), - ?line ok = error_logger:error_report([test,type], Rep3), + ok = error_logger:error_report([test,type], Rep3), reported(error_report, [test,type], Rep3), - ?line ok = error_logger:error_report(1, Rep4), + ok = error_logger:error_report(1, Rep4), reported(error_report, 1, Rep4), - ?line my_yes = error_logger:delete_report_handler(?MODULE), + my_yes = error_logger:delete_report_handler(?MODULE), ok. %%----------------------------------------------------------------- -info_report(suite) -> []; -info_report(doc) -> []; info_report(Config) when is_list(Config) -> - ?line error_logger:add_report_handler(?MODULE, self()), + error_logger:add_report_handler(?MODULE, self()), Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}], Rep2 = [testing,"testing",{tag1,"tag1"}], Rep3 = "This is a string !", Rep4 = {this,is,a,tuple}, - ?line ok = error_logger:info_report(Rep1), + ok = error_logger:info_report(Rep1), reported(info_report, std_info, Rep1), - ?line ok = error_logger:info_report(Rep2), + ok = error_logger:info_report(Rep2), reported(info_report, std_info, Rep2), - ?line ok = error_logger:info_report(Rep3), + ok = error_logger:info_report(Rep3), reported(info_report, std_info, Rep3), - ?line ok = error_logger:info_report(Rep4), + ok = error_logger:info_report(Rep4), reported(info_report, std_info, Rep4), - ?line ok = error_logger:info_report(test_type, Rep1), + ok = error_logger:info_report(test_type, Rep1), reported(info_report, test_type, Rep1), - ?line ok = error_logger:info_report(test_type, Rep2), + ok = error_logger:info_report(test_type, Rep2), reported(info_report, test_type, Rep2), - ?line ok = error_logger:info_report(test_type, Rep3), + ok = error_logger:info_report(test_type, Rep3), reported(info_report, test_type, Rep3), - ?line ok = error_logger:info_report(test_type, Rep4), + ok = error_logger:info_report(test_type, Rep4), reported(info_report, test_type, Rep4), - ?line ok = error_logger:info_report("test_type", Rep1), + ok = error_logger:info_report("test_type", Rep1), reported(info_report, "test_type", Rep1), - ?line ok = error_logger:info_report({test,type}, Rep2), + ok = error_logger:info_report({test,type}, Rep2), reported(info_report, {test,type}, Rep2), - ?line ok = error_logger:info_report([test,type], Rep3), + ok = error_logger:info_report([test,type], Rep3), reported(info_report, [test,type], Rep3), - ?line ok = error_logger:info_report(1, Rep4), + ok = error_logger:info_report(1, Rep4), reported(info_report, 1, Rep4), - ?line my_yes = error_logger:delete_report_handler(?MODULE), + my_yes = error_logger:delete_report_handler(?MODULE), ok. %%----------------------------------------------------------------- -error(suite) -> []; -error(doc) -> []; error(Config) when is_list(Config) -> - ?line error_logger:add_report_handler(?MODULE, self()), + error_logger:add_report_handler(?MODULE, self()), Msg1 = "This is a plain text string~n", Msg2 = "This is a text with arguments ~p~n", Arg2 = "This is the argument", Msg3 = {erroneous,msg}, - ?line ok = error_logger:error_msg(Msg1), + ok = error_logger:error_msg(Msg1), reported(error, Msg1, []), - ?line ok = error_logger:error_msg(Msg2, Arg2), + ok = error_logger:error_msg(Msg2, Arg2), reported(error, Msg2, Arg2), - ?line ok = error_logger:error_msg(Msg3), + ok = error_logger:error_msg(Msg3), reported(error, Msg3, []), - ?line ok = error_logger:error_msg(Msg1, []), + ok = error_logger:error_msg(Msg1, []), reported(error, Msg1, []), - ?line ok = error_logger:error_msg(Msg2, Arg2), + ok = error_logger:error_msg(Msg2, Arg2), reported(error, Msg2, Arg2), - ?line ok = error_logger:error_msg(Msg3, []), + ok = error_logger:error_msg(Msg3, []), reported(error, Msg3, []), - ?line ok = error_logger:format(Msg1, []), + ok = error_logger:format(Msg1, []), reported(error, Msg1, []), - ?line ok = error_logger:format(Msg2, Arg2), + ok = error_logger:format(Msg2, Arg2), reported(error, Msg2, Arg2), - ?line ok = error_logger:format(Msg3, []), + ok = error_logger:format(Msg3, []), reported(error, Msg3, []), - ?line my_yes = error_logger:delete_report_handler(?MODULE), + my_yes = error_logger:delete_report_handler(?MODULE), ok. %%----------------------------------------------------------------- -info(suite) -> []; -info(doc) -> []; info(Config) when is_list(Config) -> - ?line error_logger:add_report_handler(?MODULE, self()), + error_logger:add_report_handler(?MODULE, self()), Msg1 = "This is a plain text string~n", Msg2 = "This is a text with arguments ~p~n", Arg2 = "This is the argument", Msg3 = {erroneous,msg}, - ?line ok = error_logger:info_msg(Msg1), + ok = error_logger:info_msg(Msg1), reported(info_msg, Msg1, []), - ?line ok = error_logger:info_msg(Msg2, Arg2), + ok = error_logger:info_msg(Msg2, Arg2), reported(info_msg, Msg2, Arg2), - ?line ok = error_logger:info_msg(Msg3), + ok = error_logger:info_msg(Msg3), reported(info_msg, Msg3, []), - ?line ok = error_logger:info_msg(Msg1, []), + ok = error_logger:info_msg(Msg1, []), reported(info_msg, Msg1, []), - ?line ok = error_logger:info_msg(Msg2, Arg2), + ok = error_logger:info_msg(Msg2, Arg2), reported(info_msg, Msg2, Arg2), - ?line ok = error_logger:info_msg(Msg3, []), + ok = error_logger:info_msg(Msg3, []), reported(info_msg, Msg3, []), - ?line my_yes = error_logger:delete_report_handler(?MODULE), + my_yes = error_logger:delete_report_handler(?MODULE), ok. %%----------------------------------------------------------------- -emulator(suite) -> []; -emulator(doc) -> []; emulator(Config) when is_list(Config) -> - ?line error_logger:add_report_handler(?MODULE, self()), + error_logger:add_report_handler(?MODULE, self()), Msg = "Error in process ~p on node ~p with exit value:~n~p~n", Error = {badmatch,4}, Stack = [{module, function, 2, []}], Pid = spawn(?MODULE, generate_error, [Error, Stack]), reported(error, Msg, [Pid, node(), {Error, Stack}]), - ?line my_yes = error_logger:delete_report_handler(?MODULE), + my_yes = error_logger:delete_report_handler(?MODULE), ok. generate_error(Error, Stack) -> @@ -227,52 +230,44 @@ generate_error(Error, Stack) -> %% want to interact with the test run. %%----------------------------------------------------------------- -tty(suite) -> []; -tty(doc) -> []; tty(Config) when is_list(Config) -> - ?line {'EXIT', _Reason} = (catch error_logger:tty(dummy)), + {'EXIT', _Reason} = (catch error_logger:tty(dummy)), ok. %%----------------------------------------------------------------- %% If where already exists a logfile we skip this test case !! %%----------------------------------------------------------------- -logfile(suite) -> []; -logfile(doc) -> []; logfile(Config) when is_list(Config) -> - ?line case error_logger:logfile(filename) of - {error, no_log_file} -> % Ok, we continues. - do_logfile(); - _ -> - ok - end. + case error_logger:logfile(filename) of + {error, no_log_file} -> % Ok, we continues. + do_logfile(); + _ -> + ok + end. do_logfile() -> - ?line {error, _} = error_logger:logfile(close), - ?line {error, _} = error_logger:logfile({open,{error}}), - ?line ok = error_logger:logfile({open, "dummy_logfile.log"}), - ?line "dummy_logfile.log" = error_logger:logfile(filename), - ?line ok = error_logger:logfile(close), - ?line {'EXIT',_} = (catch error_logger:logfile(dummy)), + {error, _} = error_logger:logfile(close), + {error, _} = error_logger:logfile({open,{error}}), + ok = error_logger:logfile({open, "dummy_logfile.log"}), + "dummy_logfile.log" = error_logger:logfile(filename), + ok = error_logger:logfile(close), + {'EXIT',_} = (catch error_logger:logfile(dummy)), ok. %%----------------------------------------------------------------- -add(suite) -> []; -add(doc) -> []; add(Config) when is_list(Config) -> - ?line {'EXIT',_} = (catch error_logger:add_report_handler("dummy")), - ?line {'EXIT',_} = error_logger:add_report_handler(non_existing), - ?line my_error = error_logger:add_report_handler(?MODULE, [error]), + {'EXIT',_} = (catch error_logger:add_report_handler("dummy")), + {'EXIT',_} = error_logger:add_report_handler(non_existing), + my_error = error_logger:add_report_handler(?MODULE, [error]), ok. %%----------------------------------------------------------------- -delete(suite) -> []; -delete(doc) -> []; delete(Config) when is_list(Config) -> - ?line {'EXIT',_} = (catch error_logger:delete_report_handler("dummy")), - ?line {error,_} = error_logger:delete_report_handler(non_existing), + {'EXIT',_} = (catch error_logger:delete_report_handler("dummy")), + {error,_} = error_logger:delete_report_handler(non_existing), ok. %%----------------------------------------------------------------- @@ -284,7 +279,7 @@ reported(Tag, Type, Report) -> test_server:messages_get(), ok after 1000 -> - test_server:fail(no_report_received) + ct:fail(no_report_received) end. %%----------------------------------------------------------------- diff --git a/lib/kernel/test/error_logger_warn_SUITE.erl b/lib/kernel/test/error_logger_warn_SUITE.erl index a3a3b2f8c6..a8087e11f9 100644 --- a/lib/kernel/test/error_logger_warn_SUITE.erl +++ b/lib/kernel/test/error_logger_warn_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2016. 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,7 +29,7 @@ %% Internal exports. -export([init/1,handle_event/2,handle_info/2,handle_call/2]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(EXPECT(Pattern), (fun() -> @@ -42,11 +42,10 @@ end end)()). -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(1)). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [basic, warnings_info, warnings_errors, rb_basic, @@ -70,69 +69,58 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), + Config. + +end_per_testcase(_Case, _Config) -> ok. -basic(doc) -> - ["Tests basic error logger functionality"]; +%% Tests basic error logger functionality. basic(Config) when is_list(Config) -> put(elw_config,Config), basic(). -warnings_info(doc) -> - ["Tests mapping warnings to info functionality"]; +%% Tests mapping warnings to info functionality. warnings_info(Config) when is_list(Config) -> put(elw_config,Config), warnings_info(). -warnings_errors(doc) -> - ["Tests mapping warnings to errors functionality"]; +%% Tests mapping warnings to errors functionality. warnings_errors(Config) when is_list(Config) -> put(elw_config,Config), warnings_errors(). -rb_basic(doc) -> - ["Tests basic rb functionality"]; +%% Tests basic rb functionality. rb_basic(Config) when is_list(Config) -> put(elw_config,Config), rb_basic(). -rb_warnings_info(doc) -> - ["Tests warnings as info rb functionality"]; +%% Tests warnings as info rb functionality. rb_warnings_info(Config) when is_list(Config) -> put(elw_config,Config), rb_warnings_info(). -rb_warnings_errors(doc) -> - ["Tests warnings as errors rb functionality"]; +%% Tests warnings as errors rb functionality. rb_warnings_errors(Config) when is_list(Config) -> put(elw_config,Config), rb_warnings_errors(). -rb_trunc(doc) -> - ["Tests rb functionality on truncated data"]; +%% Tests rb functionality on truncated data. rb_trunc(Config) when is_list(Config) -> put(elw_config,Config), rb_trunc(). -rb_utc(doc) -> - ["Tests UTC mapping in rb (-sasl utc_log true)"]; +%% Tests UTC mapping in rb (-sasl utc_log true). rb_utc(Config) when is_list(Config) -> put(elw_config,Config), rb_utc(). -file_utc(doc) -> - ["Tests UTC mapping in file logger (-stdlib utc_log true)"]; +%% Tests UTC mapping in file logger (-stdlib utc_log true). file_utc(Config) when is_list(Config) -> put(elw_config,Config), file_utc(). -% a small gen_event +%% a small gen_event init([Pid]) -> {ok, Pid}. @@ -236,7 +224,7 @@ warnings_errors() -> stop_node(Node), ok. -% RB... +%% RB... quote(String) -> case os:type() of @@ -283,7 +271,7 @@ findstrc(String,File) -> 0 end. -% Doesn't count empty lines +%% Doesn't count empty lines lines(File) -> length( string:tokens( @@ -291,17 +279,17 @@ lines(File) -> element(2,file:read_file(File))), "\n")). -%directories anf filenames +%% Directories and filenames ld() -> Config = get(elw_config), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), filename:absname(PrivDir). lf() -> filename:join([ld(),"logfile.txt"]). rd() -> Config = get(elw_config), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), LogDir = filename:join(PrivDir,"log"), file:make_dir(LogDir), filename:absname(LogDir). @@ -315,7 +303,7 @@ nice_stop_node(Name) -> {nodedown,Name} -> ok end. -%clean out rd() before each report test in order to get only one file... +%% Clean out rd() before each report test in order to get only one file... clean_rd() -> {ok,L} = file:list_dir(rd()), lists:foreach(fun(F) -> @@ -352,10 +340,10 @@ one_rb_findstr(Param,String) -> rb:stop_log(), findstr(String,lf()). -% Tests +%% Tests rb_basic() -> clean_rd(), - % Behold, the magic parameters to activate rb logging... + %% Behold, the magic parameters to activate rb logging... Node = start_node(nn(),"-boot start_sasl -sasl error_logger_mf_dir "++ quote(rd())++" error_logger_mf_maxbytes 5000 " "error_logger_mf_maxfiles 5"), @@ -378,7 +366,7 @@ rb_basic() -> 0 = one_rb_findstr([info_msg],pid_to_list(Self)), 0 = one_rb_findstr([info_report],pid_to_list(Self)), 2 = one_rb_findstr([],pid_to_list(Self)), - true = (one_rb_findstr([progress],"===") > 4), + true = (one_rb_findstr([progress],"===") > 3), rb:stop(), application:stop(sasl), stop_node(Node), @@ -408,7 +396,7 @@ rb_warnings_info() -> 1 = one_rb_findstr([info_msg],pid_to_list(Self)), 1 = one_rb_findstr([info_report],pid_to_list(Self)), 2 = one_rb_findstr([],pid_to_list(Self)), - true = (one_rb_findstr([progress],"===") > 4), + true = (one_rb_findstr([progress],"===") > 3), rb:stop(), application:stop(sasl), stop_node(Node), @@ -438,7 +426,7 @@ rb_warnings_errors() -> 0 = one_rb_findstr([info_msg],pid_to_list(Self)), 0 = one_rb_findstr([info_report],pid_to_list(Self)), 2 = one_rb_findstr([],pid_to_list(Self)), - true = (one_rb_findstr([progress],"===") > 4), + true = (one_rb_findstr([progress],"===") > 3), rb:stop(), application:stop(sasl), stop_node(Node), @@ -471,7 +459,7 @@ rb_trunc() -> 0 = one_rb_findstr([info_msg],pid_to_list(Self)), 0 = one_rb_findstr([info_report],pid_to_list(Self)), 1 = one_rb_findstr([],pid_to_list(Self)), - true = (one_rb_findstr([progress],"===") > 4), + true = (one_rb_findstr([progress],"===") > 3), rb:stop(), application:stop(sasl), stop_node(Node), @@ -513,9 +501,7 @@ rb_utc() -> file_utc() -> file:delete(lf()), SS="-stdlib utc_log true -kernel error_logger "++ oquote("{file,"++iquote(lf())++"}"), - %erlang:display(SS), Node = start_node(nn(),SS), - %erlang:display(rpc:call(Node,application,get_env,[kernel,error_logger])), Self = self(), GL = group_leader(), fake_gl(Node,error_msg,"~p~n",[Self]), diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 8856be31c2..119e1f24bb 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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,7 +18,7 @@ %% %CopyrightEnd% %% -%% This is a developement feature when developing a new file module, +%% This is a development feature when developing a new file module, %% ugly but practical. -ifndef(FILE_MODULE). -define(FILE_MODULE, file). @@ -48,23 +48,23 @@ -export([cur_dir_0/1, cur_dir_1/1, make_del_dir/1, list_dir/1,list_dir_error/1, untranslatable_names/1, untranslatable_names_error/1, - pos1/1, pos2/1]). + pos1/1, pos2/1, pos3/1]). -export([close/1, consult1/1, path_consult/1, delete/1]). -export([ eval1/1, path_eval/1, script1/1, path_script/1, - open1/1, - old_modes/1, new_modes/1, path_open/1, open_errors/1]). + open1/1, + old_modes/1, new_modes/1, path_open/1, open_errors/1]). -export([ file_info_basic_file/1, file_info_basic_directory/1, - file_info_bad/1, file_info_times/1, file_write_file_info/1]). + file_info_bad/1, file_info_times/1, file_write_file_info/1]). -export([rename/1, access/1, truncate/1, datasync/1, sync/1, read_write/1, pread_write/1, append/1, exclusive/1]). -export([ e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]). -export([otp_5814/1, otp_10852/1]). -export([ read_not_really_compressed/1, - read_compressed_cooked/1, read_compressed_cooked_binary/1, - read_cooked_tar_problem/1, - write_compressed/1, compress_errors/1, catenated_gzips/1, - compress_async_crash/1]). + read_compressed_cooked/1, read_compressed_cooked_binary/1, + read_cooked_tar_problem/1, + write_compressed/1, compress_errors/1, catenated_gzips/1, + compress_async_crash/1]). -export([ make_link/1, read_link_info_for_non_link/1, symlinks/1]). @@ -80,9 +80,10 @@ -export([interleaved_read_write/1]). +-export([unicode/1]). -export([altname/1]). --export([large_file/1, large_write/1]). +-export([large_file/0, large_file/1, large_write/0, large_write/1]). -export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]). @@ -105,16 +106,18 @@ %% System probe functions that might be handy to check from the shell -export([disc_free/1, memsize/0]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/file.hrl"). -define(THROW_ERROR(RES), throw({fail, ?LINE, RES})). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> - [altname, read_write_file, {group, dirs}, + [unicode, altname, read_write_file, {group, dirs}, {group, files}, delete, rename, names, {group, errors}, {group, compression}, {group, links}, copy, delayed_write, read_ahead, segment_read, segment_write, @@ -136,7 +139,7 @@ groups() -> [open1, old_modes, new_modes, path_open, close, access, read_write, pread_write, append, open_errors, exclusive]}, - {pos, [], [pos1, pos2]}, + {pos, [], [pos1, pos2, pos3]}, {file_info, [], [file_info_basic_file, file_info_basic_directory, file_info_bad, file_info_times, file_write_file_info]}, @@ -167,16 +170,11 @@ init_per_suite(Config) when is_list(Config) -> ok -> [{sasl,started}] end, - ok = case os:type() of - {ose,_} -> - ok; - _ -> - application:start(os_mon) - end, + application:start(os_mon), case os:type() of {win32, _} -> - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), HasAccessTime = case ?FILE_MODULE:read_file_info(Priv) of {ok, #file_info{atime={_, {0, 0, 0}}}} -> @@ -198,12 +196,7 @@ end_per_suite(Config) when is_list(Config) -> ok end, - case os:type() of - {ose,_} -> - ok; - _ -> - application:stop(os_mon) - end, + application:stop(os_mon), case proplists:get_value(sasl, Config) of started -> application:stop(sasl); @@ -270,73 +263,66 @@ mini_server(Parent) -> mini_server(Parent) end. -standard_io(suite) -> - []; -standard_io(doc) -> - ["Test that standard i/o-servers work with file module"]; +%% Test that standard i/o-servers work with file module. standard_io(Config) when is_list(Config) -> %% Really just a smoke test - ?line Pid = spawn(?MODULE,mini_server,[self()]), - ?line register(mini_server,Pid), - ?line ok = file:write(mini_server,<<"hej\n">>), - ?line receive - {io_request,_,_,{put_chars,<<"hej\n">>}} -> - ok - after 1000 -> - exit(noreply) - end, - ?line {ok,"aaaaa"} = file:read(mini_server,5), - ?line receive - {io_request,_,_,{get_chars,'',5}} -> - ok - after 1000 -> - exit(noreply) - end, - ?line {ok,"hej\n"} = file:read_line(mini_server), - ?line receive - {io_request,_,_,{get_line,''}} -> - ok - after 1000 -> - exit(noreply) - end, - ?line OldGL = group_leader(), - ?line group_leader(Pid,self()), - ?line ok = file:write(standard_io,<<"hej\n">>), - ?line group_leader(OldGL,self()), - ?line receive - {io_request,_,_,{put_chars,<<"hej\n">>}} -> - ok - after 1000 -> - exit(noreply) - end, - ?line group_leader(Pid,self()), - ?line {ok,"aaaaa"} = file:read(standard_io,5), - ?line group_leader(OldGL,self()), - ?line receive - {io_request,_,_,{get_chars,'',5}} -> - ok - after 1000 -> - exit(noreply) - end, - ?line group_leader(Pid,self()), - ?line {ok,"hej\n"} = file:read_line(standard_io), - ?line group_leader(OldGL,self()), - ?line receive - {io_request,_,_,{get_line,''}} -> - ok - after 1000 -> - exit(noreply) - end, + Pid = spawn(?MODULE,mini_server,[self()]), + register(mini_server,Pid), + ok = file:write(mini_server,<<"hej\n">>), + receive + {io_request,_,_,{put_chars,<<"hej\n">>}} -> + ok + after 1000 -> + exit(noreply) + end, + {ok,"aaaaa"} = file:read(mini_server,5), + receive + {io_request,_,_,{get_chars,'',5}} -> + ok + after 1000 -> + exit(noreply) + end, + {ok,"hej\n"} = file:read_line(mini_server), + receive + {io_request,_,_,{get_line,''}} -> + ok + after 1000 -> + exit(noreply) + end, + OldGL = group_leader(), + group_leader(Pid,self()), + ok = file:write(standard_io,<<"hej\n">>), + group_leader(OldGL,self()), + receive + {io_request,_,_,{put_chars,<<"hej\n">>}} -> + ok + after 1000 -> + exit(noreply) + end, + group_leader(Pid,self()), + {ok,"aaaaa"} = file:read(standard_io,5), + group_leader(OldGL,self()), + receive + {io_request,_,_,{get_chars,'',5}} -> + ok + after 1000 -> + exit(noreply) + end, + group_leader(Pid,self()), + {ok,"hej\n"} = file:read_line(standard_io), + group_leader(OldGL,self()), + receive + {io_request,_,_,{get_line,''}} -> + ok + after 1000 -> + exit(noreply) + end, Pid ! die, receive after 1000 -> ok end. -old_io_protocol(suite) -> - []; -old_io_protocol(doc) -> - ["Test that the old file IO protocol =< R16B still works"]; +%% Test that the old file IO protocol =< R16B still works. old_io_protocol(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(5)), - RootDir = ?config(priv_dir,Config), + RootDir = proplists:get_value(priv_dir,Config), Name = filename:join(RootDir, atom_to_list(?MODULE) ++"old_io_protocol.fil"), @@ -349,14 +335,11 @@ old_io_protocol(Config) when is_list(Config) -> end, ok = ?FILE_MODULE:close(Fd), {ok, <<>>} = ?FILE_MODULE:read_file(Name), - test_server:timetrap_cancel(Dog), [] = flush(), ok. -unicode_mode(suite) -> []; -unicode_mode(doc) -> [""]; unicode_mode(Config) -> - Dir = {dir, ?config(priv_dir,Config)}, + Dir = {dir, proplists:get_value(priv_dir,Config)}, OptVariants = [[Dir], [Dir, {encoding, utf8}], [Dir, binary], @@ -502,105 +485,106 @@ um_filename(Str = [_|_], Dir, Options) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -read_write_file(suite) -> []; -read_write_file(doc) -> []; read_write_file(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_read_write_file"), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_read_write_file"), %% Try writing and reading back some term - ?line SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]}, - ?line ok = ?FILE_MODULE:write_file(Name,term_to_binary(SomeTerm)), - ?line {ok,Bin1} = ?FILE_MODULE:read_file(Name), - ?line SomeTerm = binary_to_term(Bin1), - + SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]}, + Bin1 = term_to_binary(SomeTerm), + ok = do_read_write_file(Name, Bin1), + %% Try a "null" term - ?line NullTerm = [], - ?line ok = ?FILE_MODULE:write_file(Name,term_to_binary(NullTerm)), - ?line {ok,Bin2} = ?FILE_MODULE:read_file(Name), - ?line NullTerm = binary_to_term(Bin2), - - %% Try some "complicated" types - ?line BigNum = 123456789012345678901234567890, - ?line ComplTerm = {self(),make_ref(),BigNum,3.14159}, - ?line ok = ?FILE_MODULE:write_file(Name,term_to_binary(ComplTerm)), - ?line {ok,Bin3} = ?FILE_MODULE:read_file(Name), - ?line ComplTerm = binary_to_term(Bin3), + NullTerm = [], + Bin2 = term_to_binary(NullTerm), + ok = do_read_write_file(Name, Bin2), %% Try reading a nonexistent file - ?line Name2 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_nonexistent_file"), - ?line {error, enoent} = ?FILE_MODULE:read_file(Name2), - ?line {error, enoent} = ?FILE_MODULE:read_file(""), - ?line {error, enoent} = ?FILE_MODULE:read_file(''), + Name2 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_nonexistent_file"), + {error, enoent} = ?FILE_MODULE:read_file(Name2), + {error, enoent} = ?FILE_MODULE:read_file(""), + {error, enoent} = ?FILE_MODULE:read_file(''), - % Try writing to a bad filename - ?line {error, enoent} = - ?FILE_MODULE:write_file("",term_to_binary(NullTerm)), + %% Try writing to a bad filename + {error, enoent} = do_read_write_file("", Bin2), - % Try writing something else than a binary - ?line {error, badarg} = ?FILE_MODULE:write_file(Name,{1,2,3}), - ?line {error, badarg} = ?FILE_MODULE:write_file(Name,self()), + %% Try writing something else than a binary + {error, badarg} = do_read_write_file(Name, {1,2,3}), + {error, badarg} = do_read_write_file(Name, self()), %% Some non-term binaries - ?line ok = ?FILE_MODULE:write_file(Name,[]), - ?line {ok,Bin4} = ?FILE_MODULE:read_file(Name), - ?line 0 = byte_size(Bin4), + ok = do_read_write_file(Name, []), - ?line ok = ?FILE_MODULE:write_file(Name,[Bin1,[],[[Bin2]]]), - ?line {ok,Bin5} = ?FILE_MODULE:read_file(Name), - ?line {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)), + %% Write some iolists + ok = do_read_write_file(Name, [Bin1,[],[[Bin2]]]), + ok = do_read_write_file(Name, ["string",<<"binary">>]), + ok = do_read_write_file(Name, "pure string"), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. +do_read_write_file(Name, Data) -> + case ?FILE_MODULE:write_file(Name, Data) of + ok -> + BinData = iolist_to_binary(Data), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok = ?FILE_MODULE:write_file(Name, Data, []), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok = ?FILE_MODULE:write_file(Name, Data, [raw]), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok; + {error,_}=Res -> + Res = ?FILE_MODULE:write_file(Name, Data, []), + Res = ?FILE_MODULE:write_file(Name, Data, [raw]), + Res + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -make_del_dir(suite) -> []; -make_del_dir(doc) -> []; make_del_dir(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_mk-dir"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line {error, eexist} = ?FILE_MODULE:make_dir(NewDir), - ?line ok = ?FILE_MODULE:del_dir(NewDir), - ?line {error, enoent} = ?FILE_MODULE:del_dir(NewDir), - % Make sure we are not in a directory directly under test_server - % as that would result in eacces errors when trying to delete '..', - % because there are processes having that directory as current. - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line {ok,CurrentDir} = file:get_cwd(), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_mk-dir"), + ok = ?FILE_MODULE:make_dir(NewDir), + {error, eexist} = ?FILE_MODULE:make_dir(NewDir), + ok = ?FILE_MODULE:del_dir(NewDir), + {error, enoent} = ?FILE_MODULE:del_dir(NewDir), + %% Make sure we are not in a directory directly under test_server + %% as that would result in eacces errors when trying to delete '..', + %% because there are processes having that directory as current. + ok = ?FILE_MODULE:make_dir(NewDir), + {ok,CurrentDir} = file:get_cwd(), case {os:type(), length(NewDir) >= 260 } of {{win32,_}, true} -> io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH)\n", []), io:format("\nNewDir = ~p\n", [NewDir]); _ -> - ?line ok = ?FILE_MODULE:set_cwd(NewDir) + ok = ?FILE_MODULE:set_cwd(NewDir) end, try %% Check that we get an error when trying to create... %% a deep directory - ?line NewDir2 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_mk-dir-noexist/foo"), - ?line {error, enoent} = ?FILE_MODULE:make_dir(NewDir2), + NewDir2 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_mk-dir-noexist/foo"), + {error, enoent} = ?FILE_MODULE:make_dir(NewDir2), %% a nameless directory - ?line {error, enoent} = ?FILE_MODULE:make_dir(""), + {error, enoent} = ?FILE_MODULE:make_dir(""), %% a directory with illegal name - ?line {error, badarg} = ?FILE_MODULE:make_dir({1,2,3}), - + {error, badarg} = ?FILE_MODULE:make_dir({1,2,3}), + %% a directory with illegal name, even if it's a (bad) list - ?line {error, badarg} = ?FILE_MODULE:make_dir([1,2,3,{}]), - + {error, badarg} = ?FILE_MODULE:make_dir([1,2,3,{}]), + %% Maybe this isn't an error, exactly, but worth mentioning anyway: %% ok = ?FILE_MODULE:make_dir([$f,$o,$o,0,$b,$a,$r])), %% The above line works, and created a directory "./foo" @@ -608,40 +592,36 @@ make_del_dir(Config) when is_list(Config) -> %% a directory, but with a name that incorporates the "bar" part of %% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same %% dir. But this would slow it down. - + %% Try deleting some bad directories %% Deleting the parent directory to the current, sounds dangerous, huh? %% Don't worry ;-) the parent directory should never be empty, right? - ?line case ?FILE_MODULE:del_dir('..') of - {error, eexist} -> ok; - {error, eacces} -> ok; %OpenBSD - {error, einval} -> ok %FreeBSD - end, - ?line {error, enoent} = ?FILE_MODULE:del_dir(""), - ?line {error, badarg} = ?FILE_MODULE:del_dir([3,2,1,{}]), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog) + case ?FILE_MODULE:del_dir('..') of + {error, eexist} -> ok; + {error, eacces} -> ok; %OpenBSD + {error, einval} -> ok %FreeBSD + end, + {error, enoent} = ?FILE_MODULE:del_dir(""), + {error, badarg} = ?FILE_MODULE:del_dir([3,2,1,{}]), + + [] = flush() after - ?FILE_MODULE:set_cwd(CurrentDir) + ?FILE_MODULE:set_cwd(CurrentDir) end, ok. -cur_dir_0(suite) -> []; -cur_dir_0(doc) -> []; cur_dir_0(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), %% Find out the current dir, and cd to it ;-) - ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd(), - ?line Dir1 = BaseDir ++ "", %% Check that it's a string - ?line ok = ?FILE_MODULE:set_cwd(Dir1), + {ok,BaseDir} = ?FILE_MODULE:get_cwd(), + Dir1 = BaseDir ++ "", %% Check that it's a string + ok = ?FILE_MODULE:set_cwd(Dir1), %% Make a new dir, and cd to that - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_curdir"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_curdir"), + ok = ?FILE_MODULE:make_dir(NewDir), case {os:type(), length(NewDir) >= 260} of {{win32,_}, true} -> io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH):\n"), @@ -674,50 +654,44 @@ cur_dir_0(Config) when is_list(Config) -> {ok,OldDirFiles} = ?FILE_MODULE:list_dir("."), false = lists:member(UncommonName,OldDirFiles) end, - + %% Try doing some bad things - ?line {error, badarg} = ?FILE_MODULE:set_cwd({foo,bar}), - ?line {error, enoent} = ?FILE_MODULE:set_cwd(""), - ?line {error, enoent} = ?FILE_MODULE:set_cwd(".......a......"), - ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd(), %% Still there? + {error, badarg} = ?FILE_MODULE:set_cwd({foo,bar}), + {error, enoent} = ?FILE_MODULE:set_cwd(""), + {error, enoent} = ?FILE_MODULE:set_cwd(".......a......"), + {ok,BaseDir} = ?FILE_MODULE:get_cwd(), %% Still there? %% On Windows, there should only be slashes, no backslashes, %% in the return value of get_cwd(). %% (The test is harmless on Unix, because filenames usually %% don't contain backslashes.) - ?line {ok, BaseDir} = ?FILE_MODULE:get_cwd(), - ?line false = lists:member($\\, BaseDir), + {ok, BaseDir} = ?FILE_MODULE:get_cwd(), + false = lists:member($\\, BaseDir), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %% Tests ?FILE_MODULE:get_cwd/1. -cur_dir_1(suite) -> []; -cur_dir_1(doc) -> []; cur_dir_1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - - ?line case os:type() of - {win32, _} -> - win_cur_dir_1(Config); - _ -> - ?line {error, enotsup} = ?FILE_MODULE:get_cwd("d:") - end, - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + case os:type() of + {win32, _} -> + win_cur_dir_1(Config); + _ -> + {error, enotsup} = ?FILE_MODULE:get_cwd("d:") + end, + [] = flush(), ok. - + win_cur_dir_1(_Config) -> - ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd(), + {ok,BaseDir} = ?FILE_MODULE:get_cwd(), %% Get the drive letter from the current directory, %% and try to get current directory for that drive. - ?line [Drive,$:|_] = BaseDir, - ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd([Drive,$:]), + [Drive,$:|_] = BaseDir, + {ok,BaseDir} = ?FILE_MODULE:get_cwd([Drive,$:]), io:format("BaseDir = ~s\n", [BaseDir]), %% Unfortunately, there is no way to move away from the @@ -732,7 +706,7 @@ win_cur_dir_1(_Config) -> %%% list_dir_error(Config) -> - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), NonExisting = filename:join(Priv, "non-existing-dir"), {error,enoent} = ?FILE_MODULE:list_dir(NonExisting), ok. @@ -742,7 +716,7 @@ list_dir_error(Config) -> %%% list_dir(Config) -> - RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"), ?FILE_MODULE:make_dir(TestDir), list_dir_1(TestDir, 42, []). @@ -772,7 +746,7 @@ untranslatable_names(Config) -> untranslatable_names_1(Config) -> {ok,OldCwd} = file:get_cwd(), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Dir = filename:join(PrivDir, "untranslatable_names"), ok = file:make_dir(Dir), Node = start_node(untranslatable_names, "+fnu"), @@ -813,7 +787,7 @@ untranslatable_names_error(Config) -> untranslatable_names_error_1(Config) -> {ok,OldCwd} = file:get_cwd(), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Dir = filename:join(PrivDir, "untranslatable_names_error"), ok = file:make_dir(Dir), Node = start_node(untranslatable_names, "+fnue"), @@ -861,7 +835,7 @@ start_node(Name, Args) -> ct:log("Trying to start ~w@~s~n", [Name,Host]), case test_server:start_node(Name, peer, [{args,Args}]) of {error,Reason} -> - test_server:fail(Reason); + ct:fail(Reason); {ok,Node} -> ct:log("Node ~p started~n", [Node]), Node @@ -872,547 +846,504 @@ start_node(Name, Args) -> -open1(suite) -> []; -open1(doc) -> []; open1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_files"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line Name = filename:join(NewDir, "foo1.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,read_write), - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read), - ?line Str = "{a,tuple}.\n", - ?line io:format(Fd1,Str,[]), - ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), - ?line Str = io:get_line(Fd1,''), - ?line case io:get_line(Fd2,'') of - Str -> Str; - eof -> Str - end, - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), - ?line ok = ?FILE_MODULE:truncate(Fd1), - ?line eof = io:get_line(Fd1,''), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line {ok,Fd3} = ?FILE_MODULE:open(Name,read), - ?line eof = io:get_line(Fd3,''), - ?line ok = ?FILE_MODULE:close(Fd3), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_files"), + ok = ?FILE_MODULE:make_dir(NewDir), + Name = filename:join(NewDir, "foo1.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,read_write), + {ok,Fd2} = ?FILE_MODULE:open(Name,read), + Str = "{a,tuple}.\n", + io:format(Fd1,Str,[]), + {ok,0} = ?FILE_MODULE:position(Fd1,bof), + Str = io:get_line(Fd1,''), + Str = io:get_line(Fd2,''), + ok = ?FILE_MODULE:close(Fd2), + {ok,0} = ?FILE_MODULE:position(Fd1,bof), + ok = ?FILE_MODULE:truncate(Fd1), + eof = io:get_line(Fd1,''), + ok = ?FILE_MODULE:close(Fd1), + {ok,Fd3} = ?FILE_MODULE:open(Name,read), + eof = io:get_line(Fd3,''), + ok = ?FILE_MODULE:close(Fd3), + [] = flush(), ok. %% Tests all open modes. -old_modes(suite) -> []; -old_modes(doc) -> []; old_modes(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_old_open_modes"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line Name1 = filename:join(NewDir, "foo1.fil"), - ?line Marker = "hello, world", + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_old_open_modes"), + ok = ?FILE_MODULE:make_dir(NewDir), + Name1 = filename:join(NewDir, "foo1.fil"), + Marker = "hello, world", %% write - ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, write), - ?line ok = io:write(Fd1, Marker), - ?line ok = io:put_chars(Fd1, ".\n"), - ?line ok = ?FILE_MODULE:close(Fd1), + {ok, Fd1} = ?FILE_MODULE:open(Name1, write), + ok = io:write(Fd1, Marker), + ok = io:put_chars(Fd1, ".\n"), + ok = ?FILE_MODULE:close(Fd1), %% read - ?line {ok, Fd2} = ?FILE_MODULE:open(Name1, read), - ?line {ok, Marker} = io:read(Fd2, prompt), - ?line ok = ?FILE_MODULE:close(Fd2), + {ok, Fd2} = ?FILE_MODULE:open(Name1, read), + {ok, Marker} = io:read(Fd2, prompt), + ok = ?FILE_MODULE:close(Fd2), %% read_write - ?line {ok, Fd3} = ?FILE_MODULE:open(Name1, read_write), - ?line {ok, Marker} = io:read(Fd3, prompt), - ?line ok = io:write(Fd3, Marker), - ?line ok = ?FILE_MODULE:close(Fd3), + {ok, Fd3} = ?FILE_MODULE:open(Name1, read_write), + {ok, Marker} = io:read(Fd3, prompt), + ok = io:write(Fd3, Marker), + ok = ?FILE_MODULE:close(Fd3), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -new_modes(suite) -> []; -new_modes(doc) -> []; new_modes(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_new_open_modes"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line Name1 = filename:join(NewDir, "foo1.fil"), - ?line Marker = "hello, world", + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_new_open_modes"), + ok = ?FILE_MODULE:make_dir(NewDir), + Name1 = filename:join(NewDir, "foo1.fil"), + Marker = "hello, world", %% write - ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]), - ?line ok = io:write(Fd1, Marker), - ?line ok = io:put_chars(Fd1, ".\n"), - ?line ok = ?FILE_MODULE:close(Fd1), + {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]), + ok = io:write(Fd1, Marker), + ok = io:put_chars(Fd1, ".\n"), + ok = ?FILE_MODULE:close(Fd1), %% read - ?line {ok, Fd2} = ?FILE_MODULE:open(Name1, [read]), - ?line {ok, Marker} = io:read(Fd2, prompt), - ?line ok = ?FILE_MODULE:close(Fd2), + {ok, Fd2} = ?FILE_MODULE:open(Name1, [read]), + {ok, Marker} = io:read(Fd2, prompt), + ok = ?FILE_MODULE:close(Fd2), %% read and write - ?line {ok, Fd3} = ?FILE_MODULE:open(Name1, [read, write]), - ?line {ok, Marker} = io:read(Fd3, prompt), - ?line ok = io:write(Fd3, Marker), - ?line ok = ?FILE_MODULE:close(Fd3), + {ok, Fd3} = ?FILE_MODULE:open(Name1, [read, write]), + {ok, Marker} = io:read(Fd3, prompt), + ok = io:write(Fd3, Marker), + ok = ?FILE_MODULE:close(Fd3), %% read by default - ?line {ok, Fd4} = ?FILE_MODULE:open(Name1, []), - ?line {ok, Marker} = io:read(Fd4, prompt), - ?line ok = ?FILE_MODULE:close(Fd4), + {ok, Fd4} = ?FILE_MODULE:open(Name1, []), + {ok, Marker} = io:read(Fd4, prompt), + ok = ?FILE_MODULE:close(Fd4), %% read and binary - ?line {ok, Fd5} = ?FILE_MODULE:open(Name1, [read, binary]), - ?line {ok, Marker} = io:read(Fd5, prompt), - ?line ok = ?FILE_MODULE:close(Fd5), + {ok, Fd5} = ?FILE_MODULE:open(Name1, [read, binary]), + {ok, Marker} = io:read(Fd5, prompt), + ok = ?FILE_MODULE:close(Fd5), %% read, raw - ?line {ok, Fd6} = ?FILE_MODULE:open(Name1, [read, raw]), - ?line {ok, [$\[]} = ?FILE_MODULE:read(Fd6, 1), - ?line ok = ?FILE_MODULE:close(Fd6), - - %% write and sync - case ?FILE_MODULE:open(Name1, [write, sync]) of - {ok, Fd7} -> - ok = io:write(Fd7, Marker), - ok = io:put_chars(Fd7, ".\n"), - ok = ?FILE_MODULE:close(Fd7), - {ok, Fd8} = ?FILE_MODULE:open(Name1, [read]), - {ok, Marker} = io:read(Fd8, prompt), - ok = ?FILE_MODULE:close(Fd8); - {error, enotsup} -> - %% for platforms that don't support the sync option - ok - end, - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), - ok. + {ok, Fd6} = ?FILE_MODULE:open(Name1, [read, raw]), + {ok, [$\[]} = ?FILE_MODULE:read(Fd6, 1), + ok = ?FILE_MODULE:close(Fd6), + + %% write and sync + case ?FILE_MODULE:open(Name1, [write, sync]) of + {ok, Fd7} -> + ok = io:write(Fd7, Marker), + ok = io:put_chars(Fd7, ".\n"), + ok = ?FILE_MODULE:close(Fd7), + {ok, Fd8} = ?FILE_MODULE:open(Name1, [read]), + {ok, Marker} = io:read(Fd8, prompt), + ok = ?FILE_MODULE:close(Fd8); + {error, enotsup} -> + %% for platforms that don't support the sync option + ok + end, + + [] = flush(), + ok. -path_open(suite) -> []; -path_open(doc) -> []; path_open(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_path_open"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line FileName = "path_open.fil", - ?line Name = filename:join(RootDir, FileName), - ?line {ok,Fd1,_FullName1} = + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_path_open"), + ok = ?FILE_MODULE:make_dir(NewDir), + FileName = "path_open.fil", + Name = filename:join(RootDir, FileName), + {ok,Fd1,_FullName1} = ?FILE_MODULE:path_open( - [RootDir, - "nosuch1", - NewDir],FileName,write), - ?line io:format(Fd1,"ABCDEFGH",[]), - ?line ok = ?FILE_MODULE:close(Fd1), + [RootDir, + "nosuch1", + NewDir],FileName,write), + io:format(Fd1,"ABCDEFGH",[]), + ok = ?FILE_MODULE:close(Fd1), %% locate it in the last dir - ?line {ok,Fd2,_FullName2} = + {ok,Fd2,_FullName2} = ?FILE_MODULE:path_open( - ["nosuch1", - NewDir, - RootDir],FileName,read), - ?line {ok,2} = + ["nosuch1", + NewDir, + RootDir],FileName,read), + {ok,2} = ?FILE_MODULE:position(Fd2,2), "C" = io:get_chars(Fd2,'',1), - ?line ok = ?FILE_MODULE:close(Fd2), + ok = ?FILE_MODULE:close(Fd2), %% Try a failing path - ?line {error, enoent} = ?FILE_MODULE:path_open( - ["nosuch1", - NewDir],FileName,read), + {error, enoent} = ?FILE_MODULE:path_open( + ["nosuch1", + NewDir],FileName,read), %% Check that it's found regardless of path, if an absolute name given - ?line {ok,Fd3,_FullPath3} = + {ok,Fd3,_FullPath3} = ?FILE_MODULE:path_open( - ["nosuch1", - NewDir],Name,read), - ?line {ok,2} = + ["nosuch1", + NewDir],Name,read), + {ok,2} = ?FILE_MODULE:position(Fd3,2), "C" = io:get_chars(Fd3,'',1), - ?line ok = ?FILE_MODULE:close(Fd3), + ok = ?FILE_MODULE:close(Fd3), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -close(suite) -> []; -close(doc) -> []; close(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_close.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,read_write), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_close.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,read_write), %% Just closing it is no fun, we did that a million times already %% This is a common error, for code written before Erlang 4.3 %% bacause then ?FILE_MODULE:open just returned a Pid, and not everyone %% really checked what they got. - ?line {'EXIT',_Msg} = (catch ok = ?FILE_MODULE:close({ok,Fd1})), - ?line ok = ?FILE_MODULE:close(Fd1), + {'EXIT',_Msg} = (catch ok = ?FILE_MODULE:close({ok,Fd1})), + ok = ?FILE_MODULE:close(Fd1), %% Try closing one more time - ?line Val = ?FILE_MODULE:close(Fd1), - ?line io:format("Second close gave: ~p",[Val]), + Val = ?FILE_MODULE:close(Fd1), + io:format("Second close gave: ~p",[Val]), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -access(suite) -> []; -access(doc) -> []; access(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_access.fil"), - ?line Str = "ABCDEFGH", - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd1,Str,[]), - ?line ok = ?FILE_MODULE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_access.fil"), + Str = "ABCDEFGH", + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,Str,[]), + ok = ?FILE_MODULE:close(Fd1), %% Check that we can't write when in read only mode - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read), - ?line case catch io:format(Fd2,"XXXX",[]) of - ok -> - test_server:fail({format,write}); - _ -> - ok - end, - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok,Fd3} = ?FILE_MODULE:open(Name,read), - ?line Str = io:get_line(Fd3,''), - ?line ok = ?FILE_MODULE:close(Fd3), + {ok,Fd2} = ?FILE_MODULE:open(Name,read), + case catch io:format(Fd2,"XXXX",[]) of + ok -> + ct:fail({format,write}); + _ -> + ok + end, + ok = ?FILE_MODULE:close(Fd2), + {ok,Fd3} = ?FILE_MODULE:open(Name,read), + Str = io:get_line(Fd3,''), + ok = ?FILE_MODULE:close(Fd3), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %% Tests ?FILE_MODULE:read/2 and ?FILE_MODULE:write/2. -read_write(suite) -> []; -read_write(doc) -> []; read_write(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_read_write"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line Marker = "hello, world", - ?line MarkerB = list_to_binary(Marker), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_read_write"), + ok = ?FILE_MODULE:make_dir(NewDir), + Marker = "hello, world", + MarkerB = list_to_binary(Marker), %% Plain file. - ?line Name1 = filename:join(NewDir, "plain.fil"), - ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]), - ?line read_write_test(Fd1, Marker, []), + Name1 = filename:join(NewDir, "plain.fil"), + {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]), + read_write_test(Fd1, Marker, []), %% Raw file. - ?line Name2 = filename:join(NewDir, "raw.fil"), - ?line {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]), - ?line read_write_test(Fd2, Marker, []), + Name2 = filename:join(NewDir, "raw.fil"), + {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]), + read_write_test(Fd2, Marker, []), %% Plain binary file. - ?line Name3 = filename:join(NewDir, "plain-b.fil"), - ?line {ok, Fd3} = ?FILE_MODULE:open(Name3, [read, write, binary]), - ?line read_write_test(Fd3, MarkerB, <<>>), + Name3 = filename:join(NewDir, "plain-b.fil"), + {ok, Fd3} = ?FILE_MODULE:open(Name3, [read, write, binary]), + read_write_test(Fd3, MarkerB, <<>>), %% Raw binary file. - ?line Name4 = filename:join(NewDir, "raw-b.fil"), - ?line {ok, Fd4} = ?FILE_MODULE:open(Name4, [read, write, raw, binary]), - ?line read_write_test(Fd4, MarkerB, <<>>), + Name4 = filename:join(NewDir, "raw-b.fil"), + {ok, Fd4} = ?FILE_MODULE:open(Name4, [read, write, raw, binary]), + read_write_test(Fd4, MarkerB, <<>>), - ?line test_server:timetrap_cancel(Dog), ok. read_write_test(File, Marker, Empty) -> - ?line ok = ?FILE_MODULE:write(File, Marker), - ?line {ok, 0} = ?FILE_MODULE:position(File, 0), - ?line {ok, Empty} = ?FILE_MODULE:read(File, 0), - ?line {ok, Marker} = ?FILE_MODULE:read(File, 100), - ?line eof = ?FILE_MODULE:read(File, 100), - ?line {ok, Empty} = ?FILE_MODULE:read(File, 0), - ?line ok = ?FILE_MODULE:close(File), - ?line [] = flush(), + ok = ?FILE_MODULE:write(File, Marker), + {ok, 0} = ?FILE_MODULE:position(File, 0), + {ok, Empty} = ?FILE_MODULE:read(File, 0), + {ok, Marker} = ?FILE_MODULE:read(File, 100), + eof = ?FILE_MODULE:read(File, 100), + {ok, Empty} = ?FILE_MODULE:read(File, 0), + ok = ?FILE_MODULE:close(File), + [] = flush(), ok. %% Tests ?FILE_MODULE:pread/2 and ?FILE_MODULE:pwrite/2. -pread_write(suite) -> []; -pread_write(doc) -> []; pread_write(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_pread_write"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line List = "hello, world", - ?line Bin = list_to_binary(List), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_pread_write"), + ok = ?FILE_MODULE:make_dir(NewDir), + List = "hello, world", + Bin = list_to_binary(List), %% Plain file. - ?line Name1 = filename:join(NewDir, "plain.fil"), - ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]), - ?line pread_write_test(Fd1, List), + Name1 = filename:join(NewDir, "plain.fil"), + {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]), + pread_write_test(Fd1, List), %% Raw file. - ?line Name2 = filename:join(NewDir, "raw.fil"), - ?line {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]), - ?line pread_write_test(Fd2, List), + Name2 = filename:join(NewDir, "raw.fil"), + {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]), + pread_write_test(Fd2, List), %% Plain file. Binary mode. - ?line Name3 = filename:join(NewDir, "plain-binary.fil"), - ?line {ok, Fd3} = ?FILE_MODULE:open(Name3, [binary, read, write]), - ?line pread_write_test(Fd3, Bin), + Name3 = filename:join(NewDir, "plain-binary.fil"), + {ok, Fd3} = ?FILE_MODULE:open(Name3, [binary, read, write]), + pread_write_test(Fd3, Bin), %% Raw file. Binary mode. - ?line Name4 = filename:join(NewDir, "raw-binary.fil"), - ?line {ok, Fd4} = ?FILE_MODULE:open(Name4, [binary, read, write, raw]), - ?line pread_write_test(Fd4, Bin), + Name4 = filename:join(NewDir, "raw-binary.fil"), + {ok, Fd4} = ?FILE_MODULE:open(Name4, [binary, read, write, raw]), + pread_write_test(Fd4, Bin), - ?line test_server:timetrap_cancel(Dog), ok. pread_write_test(File, Data) -> - ?line io:format("~p:pread_write_test(~p,~p)~n", [?MODULE, File, Data]), - ?line Size = if is_binary(Data) -> byte_size(Data); - is_list(Data) -> length(Data) - end, - ?line I = Size + 17, - ?line ok = ?FILE_MODULE:pwrite(File, 0, Data), + io:format("~p:pread_write_test(~p,~p)~n", [?MODULE, File, Data]), + Size = if is_binary(Data) -> byte_size(Data); + is_list(Data) -> length(Data) + end, + I = Size + 17, + ok = ?FILE_MODULE:pwrite(File, 0, Data), Res = ?FILE_MODULE:pread(File, 0, I), - ?line {ok, Data} = Res, - ?line eof = ?FILE_MODULE:pread(File, I, 1), - ?line ok = ?FILE_MODULE:pwrite(File, [{0, Data}, {I, Data}]), - ?line {ok, [Data, eof, Data]} = + {ok, Data} = Res, + eof = ?FILE_MODULE:pread(File, I, 1), + ok = ?FILE_MODULE:pwrite(File, [{0, Data}, {I, Data}]), + {ok, [Data, eof, Data]} = ?FILE_MODULE:pread(File, [{0, Size}, {2*I, 1}, {I, Size}]), - ?line Plist = lists:seq(21*I, 0, -I), - ?line Pwrite = lists:map(fun(P)->{P,Data}end, Plist), - ?line Pread = [{22*I,Size} | lists:map(fun(P)->{P,Size}end, Plist)], - ?line Presult = [eof | lists:map(fun(_)->Data end, Plist)], - ?line ok = ?FILE_MODULE:pwrite(File, Pwrite), - ?line {ok, Presult} = ?FILE_MODULE:pread(File, Pread), - ?line ok = ?FILE_MODULE:close(File), - ?line [] = flush(), + Plist = lists:seq(21*I, 0, -I), + Pwrite = lists:map(fun(P)->{P,Data}end, Plist), + Pread = [{22*I,Size} | lists:map(fun(P)->{P,Size}end, Plist)], + Presult = [eof | lists:map(fun(_)->Data end, Plist)], + ok = ?FILE_MODULE:pwrite(File, Pwrite), + {ok, Presult} = ?FILE_MODULE:pread(File, Pread), + ok = ?FILE_MODULE:close(File), + [] = flush(), ok. -append(doc) -> "Test appending to a file."; -append(suite) -> []; +%% Test appending to a file. append(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_append"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_append"), + ok = ?FILE_MODULE:make_dir(NewDir), - ?line First = "First line\n", - ?line Second = "Seond lines comes here\n", - ?line Third = "And here is the third line\n", + First = "First line\n", + Second = "Seond lines comes here\n", + Third = "And here is the third line\n", %% Write a small text file. - ?line Name1 = filename:join(NewDir, "a_file.txt"), - ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]), - ?line ok = io:format(Fd1, First, []), - ?line ok = io:format(Fd1, Second, []), - ?line ok = ?FILE_MODULE:close(Fd1), + Name1 = filename:join(NewDir, "a_file.txt"), + {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]), + ok = io:format(Fd1, First, []), + ok = io:format(Fd1, Second, []), + ok = ?FILE_MODULE:close(Fd1), %% Open it a again and a append a line to it. - ?line {ok, Fd2} = ?FILE_MODULE:open(Name1, [append]), - ?line ok = io:format(Fd2, Third, []), - ?line ok = ?FILE_MODULE:close(Fd2), + {ok, Fd2} = ?FILE_MODULE:open(Name1, [append]), + ok = io:format(Fd2, Third, []), + ok = ?FILE_MODULE:close(Fd2), %% Read it back and verify. - ?line Expected = list_to_binary([First, Second, Third]), - ?line {ok, Expected} = ?FILE_MODULE:read_file(Name1), + Expected = list_to_binary([First, Second, Third]), + {ok, Expected} = ?FILE_MODULE:read_file(Name1), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -open_errors(suite) -> []; -open_errors(doc) -> []; open_errors(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line DataDir = + DataDir = filename:dirname( - filename:join(?config(data_dir, Config), "x")), - ?line DataDirSlash = DataDir++"/", - ?line {error, E1} = ?FILE_MODULE:open(DataDir, [read]), - ?line {error, E2} = ?FILE_MODULE:open(DataDirSlash, [read]), - ?line {error, E3} = ?FILE_MODULE:open(DataDir, [write]), - ?line {error, E4} = ?FILE_MODULE:open(DataDirSlash, [write]), - ?line {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4}, - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + filename:join(proplists:get_value(data_dir, Config), "x")), + DataDirSlash = DataDir++"/", + {error, E1} = ?FILE_MODULE:open(DataDir, [read]), + {error, E2} = ?FILE_MODULE:open(DataDirSlash, [read]), + {error, E3} = ?FILE_MODULE:open(DataDir, [write]), + {error, E4} = ?FILE_MODULE:open(DataDirSlash, [write]), + {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4}, + + [] = flush(), ok. -exclusive(suite) -> []; -exclusive(doc) -> "Test exclusive access to a file."; +%% Test exclusive access to a file. exclusive(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_exclusive"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line Name = filename:join(NewDir, "ex_file.txt"), - ?line {ok, Fd} = ?FILE_MODULE:open(Name, [write, exclusive]), - ?line {error, eexist} = ?FILE_MODULE:open(Name, [write, exclusive]), - ?line ok = ?FILE_MODULE:close(Fd), - ?line test_server:timetrap_cancel(Dog), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_exclusive"), + ok = ?FILE_MODULE:make_dir(NewDir), + Name = filename:join(NewDir, "ex_file.txt"), + {ok, Fd} = ?FILE_MODULE:open(Name, [write, exclusive]), + {error, eexist} = ?FILE_MODULE:open(Name, [write, exclusive]), + ok = ?FILE_MODULE:close(Fd), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -pos1(suite) -> []; -pos1(doc) -> []; pos1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_pos1.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd1,"ABCDEFGH",[]), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_pos1.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"ABCDEFGH",[]), + ok = ?FILE_MODULE:close(Fd1), + {ok,Fd2} = ?FILE_MODULE:open(Name,read), %% Start pos is first char - ?line io:format("Relative positions"), - ?line "A" = io:get_chars(Fd2,'',1), - ?line {ok,2} = ?FILE_MODULE:position(Fd2,{cur,1}), - ?line "C" = io:get_chars(Fd2,'',1), - ?line {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-3}), - ?line "A" = io:get_chars(Fd2,'',1), + io:format("Relative positions"), + "A" = io:get_chars(Fd2,'',1), + {ok,2} = ?FILE_MODULE:position(Fd2,{cur,1}), + "C" = io:get_chars(Fd2,'',1), + {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-3}), + "A" = io:get_chars(Fd2,'',1), %% Backwards from first char should be an error - ?line {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-1}), - ?line {error, einval} = ?FILE_MODULE:position(Fd2,{cur,-1}), + {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-1}), + {error, einval} = ?FILE_MODULE:position(Fd2,{cur,-1}), %% Reset position and move again - ?line {ok,0} = ?FILE_MODULE:position(Fd2,0), - ?line {ok,2} = ?FILE_MODULE:position(Fd2,{cur,2}), - ?line "C" = io:get_chars(Fd2,'',1), + {ok,0} = ?FILE_MODULE:position(Fd2,0), + {ok,2} = ?FILE_MODULE:position(Fd2,{cur,2}), + "C" = io:get_chars(Fd2,'',1), %% Go a lot forwards - ?line {ok,13} = ?FILE_MODULE:position(Fd2,{cur,10}), - ?line eof = io:get_chars(Fd2,'',1), + {ok,13} = ?FILE_MODULE:position(Fd2,{cur,10}), + eof = io:get_chars(Fd2,'',1), %% Try some fixed positions - ?line io:format("Fixed positions"), - ?line {ok,8} = + io:format("Fixed positions"), + {ok,8} = ?FILE_MODULE:position(Fd2,8), eof = io:get_chars(Fd2,'',1), - ?line {ok,8} = + {ok,8} = ?FILE_MODULE:position(Fd2,cur), eof = io:get_chars(Fd2,'',1), - ?line {ok,7} = + {ok,7} = ?FILE_MODULE:position(Fd2,7), "H" = io:get_chars(Fd2,'',1), - ?line {ok,0} = + {ok,0} = ?FILE_MODULE:position(Fd2,0), "A" = io:get_chars(Fd2,'',1), - ?line {ok,3} = + {ok,3} = ?FILE_MODULE:position(Fd2,3), "D" = io:get_chars(Fd2,'',1), - ?line {ok,12} = + {ok,12} = ?FILE_MODULE:position(Fd2,12), eof = io:get_chars(Fd2,'',1), - ?line {ok,3} = + {ok,3} = ?FILE_MODULE:position(Fd2,3), "D" = io:get_chars(Fd2,'',1), %% Try the {bof,X} notation - ?line {ok,3} = ?FILE_MODULE:position(Fd2,{bof,3}), - ?line "D" = io:get_chars(Fd2,'',1), + {ok,3} = ?FILE_MODULE:position(Fd2,{bof,3}), + "D" = io:get_chars(Fd2,'',1), %% Try eof positions - ?line io:format("EOF positions"), - ?line {ok,8} = + io:format("EOF positions"), + {ok,8} = ?FILE_MODULE:position(Fd2,{eof,0}), eof=io:get_chars(Fd2,'',1), - ?line {ok,7} = + {ok,7} = ?FILE_MODULE:position(Fd2,{eof,-1}), - ?line "H" = io:get_chars(Fd2,'',1), - ?line {ok,0} = + "H" = io:get_chars(Fd2,'',1), + {ok,0} = ?FILE_MODULE:position(Fd2,{eof,-8}), "A"=io:get_chars(Fd2,'',1), - ?line {error, einval} = ?FILE_MODULE:position(Fd2,{eof,-9}), + {error, einval} = ?FILE_MODULE:position(Fd2,{eof,-9}), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -pos2(suite) -> []; -pos2(doc) -> []; pos2(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_pos2.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd1,"ABCDEFGH",[]), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read), - ?line {error, einval} = ?FILE_MODULE:position(Fd2,-1), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_pos2.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"ABCDEFGH",[]), + ok = ?FILE_MODULE:close(Fd1), + {ok,Fd2} = ?FILE_MODULE:open(Name,read), + {error, einval} = ?FILE_MODULE:position(Fd2,-1), %% Make sure that we still can search after an error. - ?line {ok,0} = ?FILE_MODULE:position(Fd2, 0), - ?line {ok,3} = ?FILE_MODULE:position(Fd2, {bof,3}), - ?line "D" = io:get_chars(Fd2,'',1), + {ok,0} = ?FILE_MODULE:position(Fd2, 0), + {ok,3} = ?FILE_MODULE:position(Fd2, {bof,3}), + "D" = io:get_chars(Fd2,'',1), - ?line [] = flush(), - ?line io:format("DONE"), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), + io:format("DONE"), ok. +%% When it does not use raw mode, file:position had a bug. +pos3(Config) when is_list(Config) -> + RootDir = proplists:get_value(data_dir, Config), + Name = filename:join(RootDir, "realmen.html.gz"), + + {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]), + {ok, _} = ?FILE_MODULE:read(Fd, 5), + {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}), + + %% Here ok had returned =( + {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}), + %% That test is actually questionable since file:position/2 + %% is documented to leave the file position undefined after + %% it has returned an error. But on Posix systems the position + %% is guaranteed to be unchanged after an error return. On e.g + %% Windows there is nothing stated about this in the documentation. + + ok. -file_info_basic_file(suite) -> []; -file_info_basic_file(doc) -> []; file_info_basic_file(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), %% Create a short file. - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_basic_test.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name, write), - ?line io:put_chars(Fd1, "foo bar"), - ?line ok = ?FILE_MODULE:close(Fd1), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_basic_test.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name, write), + io:put_chars(Fd1, "foo bar"), + ok = ?FILE_MODULE:close(Fd1), %% Test that the file has the expected attributes. %% The times are tricky, so we will save them to a separate test case. {ok,FileInfo} = ?FILE_MODULE:read_file_info(Name), {ok,FileInfo} = ?FILE_MODULE:read_file_info(Name, [raw]), #file_info{size=Size,type=Type,access=Access, - atime=AccessTime,mtime=ModifyTime} = FileInfo, - ?line io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]), - ?line Size = 7, - ?line Type = regular, - ?line read_write = Access, - ?line true = abs(time_dist(filter_atime(AccessTime, Config), - filter_atime(ModifyTime, - Config))) < 2, - ?line all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + atime=AccessTime,mtime=ModifyTime} = FileInfo, + io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]), + Size = 7, + Type = regular, + read_write = Access, + true = abs(time_dist(filter_atime(AccessTime, Config), + filter_atime(ModifyTime, + Config))) < 2, + all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)), + + [] = flush(), ok. -file_info_basic_directory(suite) -> []; -file_info_basic_directory(doc) -> []; file_info_basic_directory(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(5)), - %% Note: filename:join/1 removes any trailing slash, %% which is essential for ?FILE_MODULE:file_info/1 to work on %% platforms such as Windows95. - RootDir = filename:join([?config(priv_dir, Config)]), + RootDir = filename:join([proplists:get_value(priv_dir, Config)]), %% Test that the RootDir directory has the expected attributes. test_directory(RootDir, read_write), @@ -1423,65 +1354,57 @@ file_info_basic_directory(Config) when is_list(Config) -> %% directories. case os:type() of {win32, _} -> - ?line test_directory("/", read_write), - ?line test_directory("c:/", read_write), - ?line test_directory("c:\\", read_write); + test_directory("/", read_write), + test_directory("c:/", read_write), + test_directory("c:\\", read_write); _ -> - ?line test_directory("/", read) + test_directory("/", read) end, - test_server:timetrap_cancel(Dog). + ok. test_directory(Name, ExpectedAccess) -> {ok,FileInfo} = ?FILE_MODULE:read_file_info(Name), {ok,FileInfo} = ?FILE_MODULE:read_file_info(Name, [raw]), #file_info{size=Size,type=Type,access=Access, atime=AccessTime,mtime=ModifyTime} = FileInfo, - ?line io:format("Testing directory ~s", [Name]), - ?line io:format("Directory size is ~p", [Size]), - ?line io:format("Access ~p", [Access]), - ?line io:format("Access time ~p; Modify time~p", - [AccessTime, ModifyTime]), - ?line Type = directory, - ?line Access = ExpectedAccess, - ?line all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)), - ?line [] = flush(), + io:format("Testing directory ~s", [Name]), + io:format("Directory size is ~p", [Size]), + io:format("Access ~p", [Access]), + io:format("Access time ~p; Modify time~p", + [AccessTime, ModifyTime]), + Type = directory, + Access = ExpectedAccess, + all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)), + [] = flush(), ok. all_integers([{A,B,C}|T]) -> all_integers([A,B,C|T]); all_integers([Int|Rest]) when is_integer(Int) -> - ?line all_integers(Rest); + all_integers(Rest); all_integers([]) -> ok. %% Try something nonexistent. -file_info_bad(suite) -> []; -file_info_bad(doc) -> []; file_info_bad(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = filename:join([?config(priv_dir, Config)]), + RootDir = filename:join([proplists:get_value(priv_dir, Config)]), FileName = filename:join(RootDir, atom_to_list(?MODULE) ++ "_nonexistent"), {error,enoent} = ?FILE_MODULE:read_file_info(FileName), {error,enoent} = ?FILE_MODULE:read_file_info(FileName, [raw]), - ?line {error, enoent} = ?FILE_MODULE:read_file_info(""), + {error, enoent} = ?FILE_MODULE:read_file_info(""), {error, enoent} = ?FILE_MODULE:read_file_info("", [raw]), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %% Test that the file times behave as they should. -file_info_times(suite) -> []; -file_info_times(doc) -> []; file_info_times(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(60)), %% We have to try this twice, since if the test runs across the change %% of a month the time diff calculations will fail. But it won't happen %% if you run it twice in succession. - ?line test_server:m_out_of_n( - 1,2, - fun() -> ?line file_info_int(Config) end), - ?line test_server:timetrap_cancel(Dog), + test_server:m_out_of_n( + 1,2, + fun() -> file_info_int(Config) end), ok. file_info_int(Config) -> @@ -1489,14 +1412,14 @@ file_info_int(Config) -> %% which is essential for ?FILE_MODULE:file_info/1 to work on %% platforms such as Windows95. - ?line RootDir = filename:join([?config(priv_dir, Config)]), - ?line test_server:format("RootDir = ~p", [RootDir]), + RootDir = filename:join([proplists:get_value(priv_dir, Config)]), + io:format("RootDir = ~p", [RootDir]), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_file_info.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:put_chars(Fd1,"foo"), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_file_info.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:put_chars(Fd1,"foo"), %% check that the file got a modify date max a few seconds away from now {ok,FileInfo1} = ?FILE_MODULE:read_file_info(Name), @@ -1509,31 +1432,31 @@ file_info_int(Config) -> #file_info{type=regular,atime=AccTime1,mtime=ModTime1} = FileInfo1, - ?line Now = erlang:localtime(), %??? - ?line io:format("Now ~p",[Now]), - ?line io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]), - ?line true = abs(time_dist(filter_atime(Now, Config), - filter_atime(AccTime1, - Config))) < 8, - ?line true = abs(time_dist(Now,ModTime1)) < 8, + Now = erlang:localtime(), %??? + io:format("Now ~p",[Now]), + io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]), + true = abs(time_dist(filter_atime(Now, Config), + filter_atime(AccTime1, + Config))) < 8, + true = abs(time_dist(Now,ModTime1)) < 8, %% Sleep until we can be sure the seconds value has changed. %% Note: FAT-based filesystem (like on Windows 95) have %% a resolution of 2 seconds. - ?line test_server:sleep(test_server:seconds(2.2)), + timer:sleep(2200), %% close the file, and watch the modify date change - ?line ok = ?FILE_MODULE:close(Fd1), + ok = ?FILE_MODULE:close(Fd1), {ok,FileInfo2} = ?FILE_MODULE:read_file_info(Name), {ok,FileInfo2} = ?FILE_MODULE:read_file_info(Name, [raw]), #file_info{size=Size,type=regular,access=Access, atime=AccTime2,mtime=ModTime2} = FileInfo2, - ?line io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]), - ?line true = time_dist(ModTime1,ModTime2) >= 0, + io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]), + true = time_dist(ModTime1,ModTime2) >= 0, %% this file is supposed to be binary, so it'd better keep it's size - ?line Size = 3, - ?line Access = read_write, + Size = 3, + Access = read_write, %% Do some directory checking {ok,FileInfo3} = ?FILE_MODULE:read_file_info(RootDir), @@ -1541,12 +1464,12 @@ file_info_int(Config) -> #file_info{size=DSize,type=directory,access=DAccess, atime=AccTime3,mtime=ModTime3} = FileInfo3, %% this dir was modified only a few secs ago - ?line io:format("Dir Acc ~p; Mod ~p; Now ~p", [AccTime3, ModTime3, Now]), - ?line true = abs(time_dist(Now,ModTime3)) < 5, - ?line DAccess = read_write, - ?line io:format("Dir size is ~p",[DSize]), + io:format("Dir Acc ~p; Mod ~p; Now ~p", [AccTime3, ModTime3, Now]), + true = abs(time_dist(Now,ModTime3)) < 5, + DAccess = read_write, + io:format("Dir size is ~p",[DSize]), - ?line [] = flush(), + [] = flush(), ok. %% Filter access times, to copy with a deficiency of FAT file systems @@ -1557,9 +1480,9 @@ filter_atime(Atime, Config) -> true -> case Atime of {Date, _} -> - {Date, {0, 0, 0}}; + {Date, {0, 0, 0}}; {Y, M, D, _, _, _} -> - {Y, M, D, 0, 0, 0} + {Y, M, D, 0, 0, 0} end; false -> Atime @@ -1567,50 +1490,47 @@ filter_atime(Atime, Config) -> %% Test the write_file_info/2 function. -file_write_file_info(suite) -> []; -file_write_file_info(doc) -> []; file_write_file_info(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = get_good_directory(Config), - ?line test_server:format("RootDir = ~p", [RootDir]), + RootDir = get_good_directory(Config), + io:format("RootDir = ~p", [RootDir]), %% Set the file to read only AND update the file times at the same time. %% (This used to fail on Windows NT/95 for a local filesystem.) %% Note: Seconds must be even; see note in file_info_times/1. - ?line Name1 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_write_file_info_ro"), - ?line ok = ?FILE_MODULE:write_file(Name1, "hello"), - ?line Time = {{1997, 01, 02}, {12, 35, 42}}, - ?line Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time}, - ?line ok = ?FILE_MODULE:write_file_info(Name1, Info), + Name1 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_write_file_info_ro"), + ok = ?FILE_MODULE:write_file(Name1, "hello"), + Time = {{1997, 01, 02}, {12, 35, 42}}, + Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time}, + ok = ?FILE_MODULE:write_file_info(Name1, Info), %% Read back the times. - ?line {ok, ActualInfo} = ?FILE_MODULE:read_file_info(Name1), - ?line #file_info{mode=_Mode, atime=ActAtime, mtime=Time, - ctime=ActCtime} = ActualInfo, - ?line FilteredAtime = filter_atime(Time, Config), - ?line FilteredAtime = filter_atime(ActAtime, Config), - ?line case os:type() of - {win32, _} -> - %% On Windows, "ctime" means creation time and it can - %% be set. - ActCtime = Time; - _ -> - ok - end, - ?line {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"), + {ok, ActualInfo} = ?FILE_MODULE:read_file_info(Name1), + #file_info{mode=_Mode, atime=ActAtime, mtime=Time, + ctime=ActCtime} = ActualInfo, + FilteredAtime = filter_atime(Time, Config), + FilteredAtime = filter_atime(ActAtime, Config), + case os:type() of + {win32, _} -> + %% On Windows, "ctime" means creation time and it can + %% be set. + ActCtime = Time; + _ -> + ok + end, + {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"), %% Make the file writable again. - ?line ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}), - ?line ok = ?FILE_MODULE:write_file(Name1, "hello again"), + ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}), + ok = ?FILE_MODULE:write_file(Name1, "hello again"), %% And unwritable. - ?line ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#400}), - ?line {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"), + ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#400}), + {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"), %% Same with raw. ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}, [raw]), @@ -1621,634 +1541,577 @@ file_write_file_info(Config) when is_list(Config) -> %% Write the times again. %% Note: Seconds must be even; see note in file_info_times/1. - ?line NewTime = {{1997, 02, 15}, {13, 18, 20}}, - ?line NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime}, - ?line ok = ?FILE_MODULE:write_file_info(Name1, NewInfo), - ?line {ok, ActualInfo2} = ?FILE_MODULE:read_file_info(Name1), - ?line #file_info{atime=NewActAtime, mtime=NewTime, - ctime=NewActCtime} = ActualInfo2, - ?line NewFilteredAtime = filter_atime(NewTime, Config), - ?line NewFilteredAtime = filter_atime(NewActAtime, Config), - ?line case os:type() of - {win32, _} -> NewActCtime = NewTime; - _ -> ok - end, + NewTime = {{1997, 02, 15}, {13, 18, 20}}, + NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime}, + ok = ?FILE_MODULE:write_file_info(Name1, NewInfo), + {ok, ActualInfo2} = ?FILE_MODULE:read_file_info(Name1), + #file_info{atime=NewActAtime, mtime=NewTime, + ctime=NewActCtime} = ActualInfo2, + NewFilteredAtime = filter_atime(NewTime, Config), + NewFilteredAtime = filter_atime(NewActAtime, Config), + case os:type() of + {win32, _} -> NewActCtime = NewTime; + _ -> ok + end, %% The file should still be unwritable. - ?line {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"), + {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"), %% Make the file writeable again, so that we can remove the %% test suites ... :-) - ?line ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}), + ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %% Returns a directory on a file system that has correct file times. get_good_directory(Config) -> - ?line ?config(priv_dir, Config). + proplists:get_value(priv_dir, Config). -consult1(suite) -> []; -consult1(doc) -> []; consult1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_consult.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_consult.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), %% note that there is no final \n (only a space) - ?line io:format(Fd1, - "{this,[is,1.0],'journey'}.\n\"into\". (sound). ", - []), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line {ok,[{this,[is,1.0],journey},"into",sound]} = + io:format(Fd1, + "{this,[is,1.0],'journey'}.\n\"into\". (sound). ", + []), + ok = ?FILE_MODULE:close(Fd1), + {ok,[{this,[is,1.0],journey},"into",sound]} = ?FILE_MODULE:consult(Name), - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write), + {ok,Fd2} = ?FILE_MODULE:open(Name,write), %% note the missing double quote - ?line io:format( - Fd2,"{this,[is,1.0],'journey'}.\n \"into. (sound). ",[]), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {error, {_, _, _} = Msg} = ?FILE_MODULE:consult(Name), - ?line io:format("Errmsg: ~p",[Msg]), + io:format( + Fd2,"{this,[is,1.0],'journey'}.\n \"into. (sound). ",[]), + ok = ?FILE_MODULE:close(Fd2), + {error, {_, _, _} = Msg} = ?FILE_MODULE:consult(Name), + io:format("Errmsg: ~p",[Msg]), - ?line {error, enoent} = ?FILE_MODULE:consult(Name ++ ".nonexistent"), + {error, enoent} = ?FILE_MODULE:consult(Name ++ ".nonexistent"), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -path_consult(suite) -> []; -path_consult(doc) -> []; path_consult(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line FileName = atom_to_list(?MODULE)++"_path_consult.fil", - ?line Name = filename:join(RootDir, FileName), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd1,"{this,is,a,journey,into,sound}.\n",[]), - ?line ok = ?FILE_MODULE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + FileName = atom_to_list(?MODULE)++"_path_consult.fil", + Name = filename:join(RootDir, FileName), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"{this,is,a,journey,into,sound}.\n",[]), + ok = ?FILE_MODULE:close(Fd1), %% File last in path - ?line {ok,[{this,is,a,journey,into,sound}],Dir} = + {ok,[{this,is,a,journey,into,sound}],Dir} = ?FILE_MODULE:path_consult( - [filename:join(RootDir, "dir1"), - filename:join(RootDir, ".."), - filename:join(RootDir, "dir2"), - RootDir], FileName), - ?line true = lists:prefix(RootDir,Dir), + [filename:join(RootDir, "dir1"), + filename:join(RootDir, ".."), + filename:join(RootDir, "dir2"), + RootDir], FileName), + true = lists:prefix(RootDir,Dir), %% While maybe not an error, it may be worth noting that %% when the full path to a file is given, it's always found %% regardless of the contents of the path - ?line {ok,_,_} = ?FILE_MODULE:path_consult(["nosuch1","nosuch2"],Name), + {ok,_,_} = ?FILE_MODULE:path_consult(["nosuch1","nosuch2"],Name), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -eval1(suite) -> []; -eval1(doc) -> []; eval1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE)++"_eval.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE)++"_eval.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), %% note that there is no final \n (only a space) - ?line io:format(Fd1,"put(evaluated_ok,\ntrue). ",[]), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line ok = ?FILE_MODULE:eval(Name), - ?line true = get(evaluated_ok), - - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"put(evaluated_ok,\ntrue). ",[]), + ok = ?FILE_MODULE:close(Fd1), + ok = ?FILE_MODULE:eval(Name), + true = get(evaluated_ok), + + {ok,Fd2} = ?FILE_MODULE:open(Name,write), %% note that there is no final \n (only a space) - ?line io:format(Fd2,"put(evaluated_ok,\nR). ",[]), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line ok = ?FILE_MODULE:eval( - Name, - erl_eval:add_binding('R', true, erl_eval:new_bindings())), - ?line true = get(evaluated_ok), - - ?line {ok,Fd3} = ?FILE_MODULE:open(Name,write), + io:format(Fd2,"put(evaluated_ok,\nR). ",[]), + ok = ?FILE_MODULE:close(Fd2), + ok = ?FILE_MODULE:eval( + Name, + erl_eval:add_binding('R', true, erl_eval:new_bindings())), + true = get(evaluated_ok), + + {ok,Fd3} = ?FILE_MODULE:open(Name,write), %% garbled - ?line io:format(Fd3,"puGARBLED-GARBLED\ntrue). ",[]), - ?line ok = ?FILE_MODULE:close(Fd3), - ?line {error, {_, _, _} = Msg} = ?FILE_MODULE:eval(Name), - ?line io:format("Errmsg1: ~p",[Msg]), - - ?line {error, enoent} = ?FILE_MODULE:eval(Name ++ ".nonexistent"), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + io:format(Fd3,"puGARBLED-GARBLED\ntrue). ",[]), + ok = ?FILE_MODULE:close(Fd3), + {error, {_, _, _} = Msg} = ?FILE_MODULE:eval(Name), + io:format("Errmsg1: ~p",[Msg]), + + {error, enoent} = ?FILE_MODULE:eval(Name ++ ".nonexistent"), + + [] = flush(), ok. -path_eval(suite) -> []; -path_eval(doc) -> []; path_eval(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line FileName = atom_to_list(?MODULE)++"_path_eval.fil", - ?line Name = filename:join(RootDir, FileName), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd1,"put(evaluated_ok,true).\n",[]), - ?line ok = ?FILE_MODULE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + FileName = atom_to_list(?MODULE)++"_path_eval.fil", + Name = filename:join(RootDir, FileName), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"put(evaluated_ok,true).\n",[]), + ok = ?FILE_MODULE:close(Fd1), %% File last in path - ?line {ok,Dir} = + {ok,Dir} = ?FILE_MODULE:path_eval( - [filename:join(RootDir, "dir1"), - filename:join(RootDir, ".."), - filename:join(RootDir, "dir2"), - RootDir],FileName), - ?line true = get(evaluated_ok), - ?line true = lists:prefix(RootDir,Dir), - + [filename:join(RootDir, "dir1"), + filename:join(RootDir, ".."), + filename:join(RootDir, "dir2"), + RootDir],FileName), + true = get(evaluated_ok), + true = lists:prefix(RootDir,Dir), + %% While maybe not an error, it may be worth noting that %% when the full path to a file is given, it's always found %% regardless of the contents of the path - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd2,"put(evaluated_ok,R).\n",[]), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok,_} = ?FILE_MODULE:path_eval( - ["nosuch1","nosuch2"], - Name, - erl_eval:add_binding('R', true, erl_eval:new_bindings())), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + {ok,Fd2} = ?FILE_MODULE:open(Name,write), + io:format(Fd2,"put(evaluated_ok,R).\n",[]), + ok = ?FILE_MODULE:close(Fd2), + {ok,_} = ?FILE_MODULE:path_eval( + ["nosuch1","nosuch2"], + Name, + erl_eval:add_binding('R', true, erl_eval:new_bindings())), + + [] = flush(), ok. -script1(suite) -> []; -script1(doc) -> ""; script1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE)++"_script.fil"), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE)++"_script.fil"), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), %% note that there is no final \n (only a space) - ?line io:format(Fd1,"A = 11,\nB = 6,\nA+B. ",[]), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line {ok,17} = ?FILE_MODULE:script(Name), - - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"A = 11,\nB = 6,\nA+B. ",[]), + ok = ?FILE_MODULE:close(Fd1), + {ok,17} = ?FILE_MODULE:script(Name), + + {ok,Fd2} = ?FILE_MODULE:open(Name,write), %% note that there is no final \n (only a space) - ?line io:format(Fd2,"A = 11,\nA+B. ",[]), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok,17} = ?FILE_MODULE:script( - Name, - erl_eval:add_binding('B', 6, erl_eval:new_bindings())), - - ?line {ok,Fd3} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd3,"A = 11,\nB = six,\nA+B. ",[]), - ?line ok = ?FILE_MODULE:close(Fd3), - ?line {error, {_, _, _} = Msg} = ?FILE_MODULE:script(Name), - ?line io:format("Errmsg1: ~p",[Msg]), - - ?line {error, enoent} = ?FILE_MODULE:script(Name ++ ".nonexistent"), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + io:format(Fd2,"A = 11,\nA+B. ",[]), + ok = ?FILE_MODULE:close(Fd2), + {ok,17} = ?FILE_MODULE:script( + Name, + erl_eval:add_binding('B', 6, erl_eval:new_bindings())), + + {ok,Fd3} = ?FILE_MODULE:open(Name,write), + io:format(Fd3,"A = 11,\nB = six,\nA+B. ",[]), + ok = ?FILE_MODULE:close(Fd3), + {error, {_, _, _} = Msg} = ?FILE_MODULE:script(Name), + io:format("Errmsg1: ~p",[Msg]), + + {error, enoent} = ?FILE_MODULE:script(Name ++ ".nonexistent"), + + [] = flush(), ok. - -path_script(suite) -> []; -path_script(doc) -> []; + path_script(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line FileName = atom_to_list(?MODULE)++"_path_script.fil", - ?line Name = filename:join(RootDir, FileName), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd1,"A = 11,\nB = 6,\nA+B.\n",[]), - ?line ok = ?FILE_MODULE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + FileName = atom_to_list(?MODULE)++"_path_script.fil", + Name = filename:join(RootDir, FileName), + {ok,Fd1} = ?FILE_MODULE:open(Name,write), + io:format(Fd1,"A = 11,\nB = 6,\nA+B.\n",[]), + ok = ?FILE_MODULE:close(Fd1), %% File last in path - ?line {ok, 17, Dir} = + {ok, 17, Dir} = ?FILE_MODULE:path_script( [filename:join(RootDir, "dir1"), filename:join(RootDir, ".."), filename:join(RootDir, "dir2"), RootDir],FileName), - ?line true = lists:prefix(RootDir,Dir), - + true = lists:prefix(RootDir,Dir), + %% While maybe not an error, it may be worth noting that %% when the full path to a file is given, it's always found %% regardless of the contents of the path - ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write), - ?line io:format(Fd2,"A = 11,\nA+B.",[]), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok, 17, Dir} = + {ok,Fd2} = ?FILE_MODULE:open(Name,write), + io:format(Fd2,"A = 11,\nA+B.",[]), + ok = ?FILE_MODULE:close(Fd2), + {ok, 17, Dir} = ?FILE_MODULE:path_script( ["nosuch1","nosuch2"], Name, erl_eval:add_binding('B', 6, erl_eval:new_bindings())), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + + [] = flush(), ok. - -truncate(suite) -> []; -truncate(doc) -> []; + truncate(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_truncate.fil"), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_truncate.fil"), %% Create a file with some data. - ?line MyData = "0123456789abcdefghijklmnopqrstuvxyz", - ?line ok = ?FILE_MODULE:write_file(Name, MyData), + MyData = "0123456789abcdefghijklmnopqrstuvxyz", + ok = ?FILE_MODULE:write_file(Name, MyData), %% Truncate the file to 10 characters. - ?line {ok, Fd} = ?FILE_MODULE:open(Name, read_write), - ?line {ok, 10} = ?FILE_MODULE:position(Fd, 10), - ?line ok = ?FILE_MODULE:truncate(Fd), - ?line ok = ?FILE_MODULE:close(Fd), + {ok, Fd} = ?FILE_MODULE:open(Name, read_write), + {ok, 10} = ?FILE_MODULE:position(Fd, 10), + ok = ?FILE_MODULE:truncate(Fd), + ok = ?FILE_MODULE:close(Fd), %% Read back the file and check that it has been truncated. - ?line Expected = list_to_binary("0123456789"), - ?line {ok, Expected} = ?FILE_MODULE:read_file(Name), + Expected = list_to_binary("0123456789"), + {ok, Expected} = ?FILE_MODULE:read_file(Name), %% Open the file read only and verify that it is not possible to %% truncate it, OTP-1960 - ?line {ok, Fd2} = ?FILE_MODULE:open(Name, read), - ?line {ok, 5} = ?FILE_MODULE:position(Fd2, 5), - ?line {error, _} = ?FILE_MODULE:truncate(Fd2), + {ok, Fd2} = ?FILE_MODULE:open(Name, read), + {ok, 5} = ?FILE_MODULE:position(Fd2, 5), + {error, _} = ?FILE_MODULE:truncate(Fd2), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -datasync(suite) -> []; -datasync(doc) -> "Tests that ?FILE_MODULE:datasync/1 at least doesn't crash."; +%% Tests that ?FILE_MODULE:datasync/1 at least doesn't crash. datasync(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line PrivDir = ?config(priv_dir, Config), - ?line Sync = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_sync.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Sync = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_sync.fil"), %% Raw open. - ?line {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]), - ?line ok = ?FILE_MODULE:datasync(Fd), - ?line ok = ?FILE_MODULE:close(Fd), + {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]), + ok = ?FILE_MODULE:datasync(Fd), + ok = ?FILE_MODULE:close(Fd), %% Ordinary open. - ?line {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]), - ?line ok = ?FILE_MODULE:datasync(Fd2), - ?line ok = ?FILE_MODULE:close(Fd2), + {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]), + ok = ?FILE_MODULE:datasync(Fd2), + ok = ?FILE_MODULE:close(Fd2), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -sync(suite) -> []; -sync(doc) -> "Tests that ?FILE_MODULE:sync/1 at least doesn't crash."; +%% Tests that ?FILE_MODULE:sync/1 at least doesn't crash. sync(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line PrivDir = ?config(priv_dir, Config), - ?line Sync = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_sync.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Sync = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_sync.fil"), %% Raw open. - ?line {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]), - ?line ok = ?FILE_MODULE:sync(Fd), - ?line ok = ?FILE_MODULE:close(Fd), + {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]), + ok = ?FILE_MODULE:sync(Fd), + ok = ?FILE_MODULE:close(Fd), %% Ordinary open. - ?line {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]), - ?line ok = ?FILE_MODULE:sync(Fd2), - ?line ok = ?FILE_MODULE:close(Fd2), + {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]), + ok = ?FILE_MODULE:sync(Fd2), + ok = ?FILE_MODULE:close(Fd2), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. -advise(suite) -> []; -advise(doc) -> "Tests that ?FILE_MODULE:advise/4 at least doesn't crash."; +%% Tests that ?FILE_MODULE:advise/4 at least doesn't crash. advise(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line PrivDir = ?config(priv_dir, Config), - ?line Advise = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_advise.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Advise = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_advise.fil"), Line1 = "Hello\n", Line2 = "World!\n", - ?line {ok, Fd} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = ?FILE_MODULE:advise(Fd, 0, 0, normal), - ?line ok = io:format(Fd, "~s", [Line1]), - ?line ok = io:format(Fd, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd), - - ?line {ok, Fd2} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = ?FILE_MODULE:advise(Fd2, 0, 0, random), - ?line ok = io:format(Fd2, "~s", [Line1]), - ?line ok = io:format(Fd2, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd2), - - ?line {ok, Fd3} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = ?FILE_MODULE:advise(Fd3, 0, 0, sequential), - ?line ok = io:format(Fd3, "~s", [Line1]), - ?line ok = io:format(Fd3, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd3), - - ?line {ok, Fd4} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = ?FILE_MODULE:advise(Fd4, 0, 0, will_need), - ?line ok = io:format(Fd4, "~s", [Line1]), - ?line ok = io:format(Fd4, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd4), - - ?line {ok, Fd5} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = ?FILE_MODULE:advise(Fd5, 0, 0, dont_need), - ?line ok = io:format(Fd5, "~s", [Line1]), - ?line ok = io:format(Fd5, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd5), - - ?line {ok, Fd6} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = ?FILE_MODULE:advise(Fd6, 0, 0, no_reuse), - ?line ok = io:format(Fd6, "~s", [Line1]), - ?line ok = io:format(Fd6, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd6), - - ?line {ok, Fd7} = ?FILE_MODULE:open(Advise, [write]), - ?line {error, einval} = ?FILE_MODULE:advise(Fd7, 0, 0, bad_advise), - ?line ok = ?FILE_MODULE:close(Fd7), + {ok, Fd} = ?FILE_MODULE:open(Advise, [write]), + ok = ?FILE_MODULE:advise(Fd, 0, 0, normal), + ok = io:format(Fd, "~s", [Line1]), + ok = io:format(Fd, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd), + + {ok, Fd2} = ?FILE_MODULE:open(Advise, [write]), + ok = ?FILE_MODULE:advise(Fd2, 0, 0, random), + ok = io:format(Fd2, "~s", [Line1]), + ok = io:format(Fd2, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd2), + + {ok, Fd3} = ?FILE_MODULE:open(Advise, [write]), + ok = ?FILE_MODULE:advise(Fd3, 0, 0, sequential), + ok = io:format(Fd3, "~s", [Line1]), + ok = io:format(Fd3, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd3), + + {ok, Fd4} = ?FILE_MODULE:open(Advise, [write]), + ok = ?FILE_MODULE:advise(Fd4, 0, 0, will_need), + ok = io:format(Fd4, "~s", [Line1]), + ok = io:format(Fd4, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd4), + + {ok, Fd5} = ?FILE_MODULE:open(Advise, [write]), + ok = ?FILE_MODULE:advise(Fd5, 0, 0, dont_need), + ok = io:format(Fd5, "~s", [Line1]), + ok = io:format(Fd5, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd5), + + {ok, Fd6} = ?FILE_MODULE:open(Advise, [write]), + ok = ?FILE_MODULE:advise(Fd6, 0, 0, no_reuse), + ok = io:format(Fd6, "~s", [Line1]), + ok = io:format(Fd6, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd6), + + {ok, Fd7} = ?FILE_MODULE:open(Advise, [write]), + {error, einval} = ?FILE_MODULE:advise(Fd7, 0, 0, bad_advise), + ok = ?FILE_MODULE:close(Fd7), %% test write without advise, then a read after an advise - ?line {ok, Fd8} = ?FILE_MODULE:open(Advise, [write]), - ?line ok = io:format(Fd8, "~s", [Line1]), - ?line ok = io:format(Fd8, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd8), - ?line {ok, Fd9} = ?FILE_MODULE:open(Advise, [read]), + {ok, Fd8} = ?FILE_MODULE:open(Advise, [write]), + ok = io:format(Fd8, "~s", [Line1]), + ok = io:format(Fd8, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd8), + {ok, Fd9} = ?FILE_MODULE:open(Advise, [read]), Offset = 0, %% same as a 0 length in some implementations Length = length(Line1) + length(Line2), - ?line ok = ?FILE_MODULE:advise(Fd9, Offset, Length, sequential), - ?line {ok, Line1} = ?FILE_MODULE:read_line(Fd9), - ?line {ok, Line2} = ?FILE_MODULE:read_line(Fd9), - ?line eof = ?FILE_MODULE:read_line(Fd9), - ?line ok = ?FILE_MODULE:close(Fd9), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + ok = ?FILE_MODULE:advise(Fd9, Offset, Length, sequential), + {ok, Line1} = ?FILE_MODULE:read_line(Fd9), + {ok, Line2} = ?FILE_MODULE:read_line(Fd9), + eof = ?FILE_MODULE:read_line(Fd9), + ok = ?FILE_MODULE:close(Fd9), + + [] = flush(), ok. -allocate(suite) -> []; -allocate(doc) -> "Tests that ?FILE_MODULE:allocate/3 at least doesn't crash."; +%% Tests that ?FILE_MODULE:allocate/3 at least doesn't crash. allocate(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line PrivDir = ?config(priv_dir, Config), - ?line Allocate = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_allocate.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Allocate = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_allocate.fil"), Line1 = "Hello\n", Line2 = "World!\n", - ?line {ok, Fd} = ?FILE_MODULE:open(Allocate, [write, binary]), + {ok, Fd} = ?FILE_MODULE:open(Allocate, [write, binary]), allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])), - ?line ok = io:format(Fd, "~s", [Line1]), - ?line ok = io:format(Fd, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd), + ok = io:format(Fd, "~s", [Line1]), + ok = io:format(Fd, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd), - ?line {ok, Fd2} = ?FILE_MODULE:open(Allocate, [write, binary]), + {ok, Fd2} = ?FILE_MODULE:open(Allocate, [write, binary]), allocate_and_assert(Fd2, 1, iolist_size(Line1)), - ?line ok = io:format(Fd2, "~s", [Line1]), - ?line ok = io:format(Fd2, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd2), + ok = io:format(Fd2, "~s", [Line1]), + ok = io:format(Fd2, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd2), - ?line {ok, Fd3} = ?FILE_MODULE:open(Allocate, [write, binary]), + {ok, Fd3} = ?FILE_MODULE:open(Allocate, [write, binary]), allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1), - ?line ok = io:format(Fd3, "~s", [Line1]), - ?line ok = io:format(Fd3, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd3), + ok = io:format(Fd3, "~s", [Line1]), + ok = io:format(Fd3, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd3), - ?line {ok, Fd4} = ?FILE_MODULE:open(Allocate, [write, binary]), + {ok, Fd4} = ?FILE_MODULE:open(Allocate, [write, binary]), allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])), - ?line ok = io:format(Fd4, "~s", [Line1]), - ?line ok = io:format(Fd4, "~s", [Line2]), - ?line ok = ?FILE_MODULE:close(Fd4), + ok = io:format(Fd4, "~s", [Line1]), + ok = io:format(Fd4, "~s", [Line2]), + ok = ?FILE_MODULE:close(Fd4), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. allocate_and_assert(Fd, Offset, Length) -> - % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have - % any other negative side effect. We can't really asssert against a - % specific return value, because support for file space pre-allocation - % depends on the OS, OS version and underlying filesystem. - % - % The Linux kernel added support for fallocate() in version 2.6.23, - % which currently works only for the ext4, ocfs2, xfs and btrfs file - % systems. posix_fallocate() is available in glibc as of version - % 2.1.94, but it was buggy until glibc version 2.7. - % - % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE. - % - % Solaris supports posix_fallocate() but only for the UFS file system - % apparently (not supported for ZFS). - % - % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate(). - % - % For Windows there's apparently no way to pre-allocate file space, at - % least with same semantics as posix_fallocate(), fallocate() and - % fcntl F_PREALLOCATE. + %% Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have + %% any other negative side effect. We can't really asssert against a + %% specific return value, because support for file space pre-allocation + %% depends on the OS, OS version and underlying filesystem. + %% + %% The Linux kernel added support for fallocate() in version 2.6.23, + %% which currently works only for the ext4, ocfs2, xfs and btrfs file + %% systems. posix_fallocate() is available in glibc as of version + %% 2.1.94, but it was buggy until glibc version 2.7. + %% + %% Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE. + %% + %% Solaris supports posix_fallocate() but only for the UFS file system + %% apparently (not supported for ZFS). + %% + %% FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate(). + %% + %% For Windows there's apparently no way to pre-allocate file space, at + %% least with same semantics as posix_fallocate(), fallocate() and + %% fcntl F_PREALLOCATE. Result = ?FILE_MODULE:allocate(Fd, Offset, Length), case os:type() of {win32, _} -> - ?line {error, enotsup} = Result; + {error, enotsup} = Result; _ -> - ?line _ = Result + _ = Result end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -delete(suite) -> []; -delete(doc) -> []; delete(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_delete.fil"), - ?line {ok, Fd1} = ?FILE_MODULE:open(Name, write), - ?line io:format(Fd1,"ok.\n",[]), - ?line ok = ?FILE_MODULE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_delete.fil"), + {ok, Fd1} = ?FILE_MODULE:open(Name, write), + io:format(Fd1,"ok.\n",[]), + ok = ?FILE_MODULE:close(Fd1), %% Check that the file is readable - ?line {ok, Fd2} = ?FILE_MODULE:open(Name, read), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line ok = ?FILE_MODULE:delete(Name), + {ok, Fd2} = ?FILE_MODULE:open(Name, read), + ok = ?FILE_MODULE:close(Fd2), + ok = ?FILE_MODULE:delete(Name), %% Check that the file is not readable anymore - ?line {error, _} = ?FILE_MODULE:open(Name, read), + {error, _} = ?FILE_MODULE:open(Name, read), %% Try deleting a nonexistent file - ?line {error, enoent} = ?FILE_MODULE:delete(Name), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + {error, enoent} = ?FILE_MODULE:delete(Name), + [] = flush(), ok. -rename(suite) ->[]; -rename(doc) ->[]; rename(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line FileName1 = atom_to_list(?MODULE)++"_rename.fil", - ?line FileName2 = atom_to_list(?MODULE)++"_rename.ful", - ?line Name1 = filename:join(RootDir, FileName1), - ?line Name2 = filename:join(RootDir, FileName2), - ?line {ok,Fd1} = ?FILE_MODULE:open(Name1,write), - ?line ok = ?FILE_MODULE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + FileName1 = atom_to_list(?MODULE)++"_rename.fil", + FileName2 = atom_to_list(?MODULE)++"_rename.ful", + Name1 = filename:join(RootDir, FileName1), + Name2 = filename:join(RootDir, FileName2), + {ok,Fd1} = ?FILE_MODULE:open(Name1,write), + ok = ?FILE_MODULE:close(Fd1), %% Rename, and check that id really changed name - ?line ok = ?FILE_MODULE:rename(Name1,Name2), - ?line {error, _} = ?FILE_MODULE:open(Name1,read), - ?line {ok,Fd2} = ?FILE_MODULE:open(Name2,read), - ?line ok = ?FILE_MODULE:close(Fd2), + ok = ?FILE_MODULE:rename(Name1,Name2), + {error, _} = ?FILE_MODULE:open(Name1,read), + {ok,Fd2} = ?FILE_MODULE:open(Name2,read), + ok = ?FILE_MODULE:close(Fd2), %% Try renaming something to itself - ?line ok = ?FILE_MODULE:rename(Name2,Name2), + ok = ?FILE_MODULE:rename(Name2,Name2), %% Try renaming something that doesn't exist - ?line {error, enoent} = ?FILE_MODULE:rename(Name1,Name2), + {error, enoent} = ?FILE_MODULE:rename(Name1,Name2), %% Try renaming to something else than a string - ?line {error, badarg} = ?FILE_MODULE:rename(Name1,{foo,bar}), - + {error, badarg} = ?FILE_MODULE:rename(Name1,{foo,bar}), + %% Move between directories - ?line DirName1 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_rename_dir"), - ?line DirName2 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_second_rename_dir"), - ?line Name1foo = filename:join(DirName1, "foo.fil"), - ?line Name2foo = filename:join(DirName2, "foo.fil"), - ?line Name2bar = filename:join(DirName2, "bar.dir"), - ?line ok = ?FILE_MODULE:make_dir(DirName1), + DirName1 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_rename_dir"), + DirName2 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_second_rename_dir"), + Name1foo = filename:join(DirName1, "foo.fil"), + Name2foo = filename:join(DirName2, "foo.fil"), + Name2bar = filename:join(DirName2, "bar.dir"), + ok = ?FILE_MODULE:make_dir(DirName1), %% The name has to include the full file name, path in not enough - ?line expect({error, eisdir}, {error, eexist}, - ?FILE_MODULE:rename(Name2,DirName1)), - ?line ok = ?FILE_MODULE:rename(Name2, Name1foo), + expect({error, eisdir}, {error, eexist}, + ?FILE_MODULE:rename(Name2,DirName1)), + ok = ?FILE_MODULE:rename(Name2, Name1foo), %% Now rename the directory - ?line ok = ?FILE_MODULE:rename(DirName1,DirName2), + ok = ?FILE_MODULE:rename(DirName1,DirName2), %% And check that the file is there now - ?line {ok,Fd3} = ?FILE_MODULE:open(Name2foo, read), - ?line ok = ?FILE_MODULE:close(Fd3), + {ok,Fd3} = ?FILE_MODULE:open(Name2foo, read), + ok = ?FILE_MODULE:close(Fd3), %% Try some dirty things now: move the directory into itself - ?line {error, Msg1} = ?FILE_MODULE:rename(DirName2, Name2bar), - ?line io:format("Errmsg1: ~p",[Msg1]), + {error, Msg1} = ?FILE_MODULE:rename(DirName2, Name2bar), + io:format("Errmsg1: ~p",[Msg1]), %% move dir into a file in itself - ?line {error, Msg2} = ?FILE_MODULE:rename(DirName2, Name2foo), - ?line io:format("Errmsg2: ~p",[Msg2]), + {error, Msg2} = ?FILE_MODULE:rename(DirName2, Name2foo), + io:format("Errmsg2: ~p",[Msg2]), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -names(suite) -> []; -names(doc) -> []; names(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), - ?line RootDir = ?config(priv_dir,Config), - ?line FileName = "foo1.fil", - ?line Name1 = filename:join(RootDir, FileName), - ?line Name2 = [RootDir,"/","foo1",".","fil"], - ?line Name3 = [RootDir,"/",foo,$1,[[[],[],'.']],"f",il], - ?line {ok,Fd0} = ?FILE_MODULE:open(Name1,write), - ?line ok = ?FILE_MODULE:close(Fd0), + RootDir = proplists:get_value(priv_dir,Config), + FileName = "foo1.fil", + Name1 = filename:join(RootDir, FileName), + Name2 = [RootDir,"/","foo1",".","fil"], + Name3 = [RootDir,"/",foo,$1,[[[],[],'.']],"f",il], + {ok,Fd0} = ?FILE_MODULE:open(Name1,write), + ok = ?FILE_MODULE:close(Fd0), %% Try some file names - ?line {ok,Fd1} = ?FILE_MODULE:open(Name1,read), - ?line ok = ?FILE_MODULE:close(Fd1), - ?line {ok,Fd2f} = ?FILE_MODULE:open(lists:flatten(Name2),read), - ?line ok = ?FILE_MODULE:close(Fd2f), - ?line {ok,Fd2} = ?FILE_MODULE:open(Name2,read), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok,Fd3} = ?FILE_MODULE:open(Name3,read), - ?line ok = ?FILE_MODULE:close(Fd3), - case length(Name1) > 255 of - true -> - io:format("Path too long for an atom:\n\n~p\n", [Name1]); - false -> - Name4 = list_to_atom(Name1), - {ok,Fd4} = ?FILE_MODULE:open(Name4,read), - ok = ?FILE_MODULE:close(Fd4) - end, + {ok,Fd1} = ?FILE_MODULE:open(Name1,read), + ok = ?FILE_MODULE:close(Fd1), + {ok,Fd2f} = ?FILE_MODULE:open(lists:flatten(Name2),read), + ok = ?FILE_MODULE:close(Fd2f), + {ok,Fd2} = ?FILE_MODULE:open(Name2,read), + ok = ?FILE_MODULE:close(Fd2), + {ok,Fd3} = ?FILE_MODULE:open(Name3,read), + ok = ?FILE_MODULE:close(Fd3), + case length(Name1) > 255 of + true -> + io:format("Path too long for an atom:\n\n~p\n", [Name1]); + false -> + Name4 = list_to_atom(Name1), + {ok,Fd4} = ?FILE_MODULE:open(Name4,read), + ok = ?FILE_MODULE:close(Fd4) + end, %% Try some path names - ?line Path1 = RootDir, - ?line Path2 = [RootDir], - ?line Path3 = ['',[],[RootDir,[[]]]], - ?line {ok,Fd11,_} = ?FILE_MODULE:path_open([Path1],FileName,read), - ?line ok = ?FILE_MODULE:close(Fd11), - ?line {ok,Fd12,_} = ?FILE_MODULE:path_open([Path2],FileName,read), - ?line ok = ?FILE_MODULE:close(Fd12), - ?line {ok,Fd13,_} = ?FILE_MODULE:path_open([Path3],FileName,read), - ?line ok = ?FILE_MODULE:close(Fd13), - case length(Path1) > 255 of - true-> - io:format("Path too long for an atom:\n\n~p\n", [Path1]); - false -> - Path4 = list_to_atom(Path1), - {ok,Fd14,_} = ?FILE_MODULE:path_open([Path4],FileName,read), - ok = ?FILE_MODULE:close(Fd14) - end, - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + Path1 = RootDir, + Path2 = [RootDir], + Path3 = ['',[],[RootDir,[[]]]], + {ok,Fd11,_} = ?FILE_MODULE:path_open([Path1],FileName,read), + ok = ?FILE_MODULE:close(Fd11), + {ok,Fd12,_} = ?FILE_MODULE:path_open([Path2],FileName,read), + ok = ?FILE_MODULE:close(Fd12), + {ok,Fd13,_} = ?FILE_MODULE:path_open([Path3],FileName,read), + ok = ?FILE_MODULE:close(Fd13), + case length(Path1) > 255 of + true-> + io:format("Path too long for an atom:\n\n~p\n", [Path1]); + false -> + Path4 = list_to_atom(Path1), + {ok,Fd14,_} = ?FILE_MODULE:path_open([Path4],FileName,read), + ok = ?FILE_MODULE:close(Fd14) + end, + [] = flush(), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -e_delete(suite) -> []; -e_delete(doc) -> []; e_delete(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_delete"), - ?line ok = ?FILE_MODULE:make_dir(Base), + RootDir = proplists:get_value(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_delete"), + ok = ?FILE_MODULE:make_dir(Base), %% Delete a non-existing file. - ?line {error, enoent} = + {error, enoent} = ?FILE_MODULE:delete(filename:join(Base, "non_existing")), %% Delete a directory. - ?line {error, eperm} = ?FILE_MODULE:delete(Base), + {error, eperm} = ?FILE_MODULE:delete(Base), %% Use a path-name with a non-directory component. - ?line Afile = filename:join(Base, "a_file"), - ?line ok = ?FILE_MODULE:write_file(Afile, "hello\n"), - ?line {error, E} = + Afile = filename:join(Base, "a_file"), + ok = ?FILE_MODULE:write_file(Afile, "hello\n"), + {error, E} = expect({error, enotdir}, {error, enoent}, ?FILE_MODULE:delete(filename:join(Afile, "another_file"))), - ?line io:format("Result: ~p~n", [E]), + io:format("Result: ~p~n", [E]), %% No permission. - ?line case os:type() of - {win32, _} -> - %% Remove a character device. - ?line {error, eacces} = ?FILE_MODULE:delete("nul"); - _ -> - ?line ?FILE_MODULE:write_file_info( - Base, #file_info {mode=0}), - ?line {error, eacces} = ?FILE_MODULE:delete(Afile), - ?line ?FILE_MODULE:write_file_info( - Base, #file_info {mode=8#600}) - end, + case os:type() of + {win32, _} -> + %% Remove a character device. + {error, eacces} = ?FILE_MODULE:delete("nul"); + _ -> + ?FILE_MODULE:write_file_info( + Base, #file_info {mode=0}), + {error, eacces} = ?FILE_MODULE:delete(Afile), + ?FILE_MODULE:write_file_info( + Base, #file_info {mode=8#600}) + end, - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %%% FreeBSD gives EEXIST when renaming a file to an empty dir, although the @@ -2256,13 +2119,10 @@ e_delete(Config) when is_list(Config) -> %%% (What about FreeBSD? We store our nightly build results on a FreeBSD %%% file system, that's what.) -e_rename(suite) -> []; -e_rename(doc) -> []; e_rename(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(10)), - RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_rename"), + atom_to_list(?MODULE)++"_e_rename"), ok = ?FILE_MODULE:make_dir(Base), %% Create an empty directory. @@ -2273,15 +2133,15 @@ e_rename(Config) when is_list(Config) -> NonEmptyDir = filename:join(Base, "non_empty_dir"), ok = ?FILE_MODULE:make_dir(NonEmptyDir), ok = ?FILE_MODULE:write_file( - filename:join(NonEmptyDir, "a_file"), - "hello\n"), + filename:join(NonEmptyDir, "a_file"), + "hello\n"), %% Create another non-empty directory. ADirectory = filename:join(Base, "a_directory"), ok = ?FILE_MODULE:make_dir(ADirectory), ok = ?FILE_MODULE:write_file( - filename:join(ADirectory, "a_file"), - "howdy\n\n"), + filename:join(ADirectory, "a_file"), + "howdy\n\n"), %% Create a data file. File = filename:join(Base, "just_a_file"), @@ -2295,15 +2155,15 @@ e_rename(Config) when is_list(Config) -> %% Move Base into Base/new_name. {error, einval} = - ?FILE_MODULE:rename(Base, filename:join(Base, "new_name")), + ?FILE_MODULE:rename(Base, filename:join(Base, "new_name")), %% Overwrite a directory with a file. expect({error, eexist}, %FreeBSD (?) - {error, eisdir}, - ?FILE_MODULE:rename(File, EmptyDir)), + {error, eisdir}, + ?FILE_MODULE:rename(File, EmptyDir)), expect({error, eexist}, %FreeBSD (?) - {error, eisdir}, - ?FILE_MODULE:rename(File, NonEmptyDir)), + {error, eisdir}, + ?FILE_MODULE:rename(File, NonEmptyDir)), %% Move a non-existing file. NonExistingFile = filename:join(Base, "non_existing_file"), @@ -2311,8 +2171,8 @@ e_rename(Config) when is_list(Config) -> %% Overwrite a file with a directory. expect({error, eexist}, %FreeBSD (?) - {error, enotdir}, - ?FILE_MODULE:rename(ADirectory, File)), + {error, enotdir}, + ?FILE_MODULE:rename(ADirectory, File)), %% Move a file to another filesystem. %% XXX - This test case is bogus. We cannot be guaranteed that @@ -2321,49 +2181,42 @@ e_rename(Config) when is_list(Config) -> %% %% XXX - Gross hack! Comment = case os:type() of - {unix, _} -> - OtherFs = "/tmp", - NameOnOtherFs = filename:join(OtherFs, filename:basename(File)), - {ok, Com} = case ?FILE_MODULE:rename(File, NameOnOtherFs) of - {error, exdev} -> - %% The file could be in - %% the same filesystem! - {ok, ok}; - ok -> - {ok, {comment, - "Moving between filesystems " - "suceeded, files are probably " - "in the same filesystem!"}}; - {error, eperm} -> - {ok, {comment, "SBS! You don't " - "have the permission to do " - "this test!"}}; - Else -> - Else - end, - Com; - {win32, _} -> - %% At least Windows NT can - %% successfully move a file to - %% another drive. - ok; - {ose, _} -> - %% disabled for now - ok - end, + {unix, _} -> + OtherFs = "/tmp", + NameOnOtherFs = filename:join(OtherFs, filename:basename(File)), + {ok, Com} = case ?FILE_MODULE:rename(File, NameOnOtherFs) of + {error, exdev} -> + %% The file could be in + %% the same filesystem! + {ok, ok}; + ok -> + {ok, {comment, + "Moving between filesystems " + "suceeded, files are probably " + "in the same filesystem!"}}; + {error, eperm} -> + {ok, {comment, "SBS! You don't " + "have the permission to do " + "this test!"}}; + Else -> + Else + end, + Com; + {win32, _} -> + %% At least Windows NT can + %% successfully move a file to + %% another drive. + ok + end, [] = flush(), - test_server:timetrap_cancel(Dog), Comment. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -e_make_dir(suite) -> []; -e_make_dir(doc) -> []; e_make_dir(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(10)), - RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_make_dir"), + atom_to_list(?MODULE)++"_e_make_dir"), ok = ?FILE_MODULE:make_dir(Base), %% A component of the path does not exist. @@ -2386,18 +2239,14 @@ e_make_dir(Config) when is_list(Config) -> ?FILE_MODULE:write_file_info(Base, #file_info {mode=0}), {error, eacces} = ?FILE_MODULE:make_dir(filename:join(Base, "xxxx")), ?FILE_MODULE:write_file_info( - Base, #file_info {mode=8#600}) + Base, #file_info {mode=8#600}) end, - test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -e_del_dir(suite) -> []; -e_del_dir(doc) -> []; e_del_dir(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(10)), - RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), Base = test_server:temp_name(filename:join(RootDir, "e_del_dir")), io:format("Base: ~p", [Base]), ok = ?FILE_MODULE:make_dir(Base), @@ -2410,21 +2259,21 @@ e_del_dir(Config) when is_list(Config) -> Afile = filename:join(Base, "a_directory"), ok = ?FILE_MODULE:write_file(Afile, "hello\n"), {error, E1} = expect({error, enotdir}, {error, enoent}, - ?FILE_MODULE:del_dir( - filename:join(Afile, "another_directory"))), + ?FILE_MODULE:del_dir( + filename:join(Afile, "another_directory"))), io:format("Result: ~p", [E1]), %% Delete a non-empty directory. {error, E2} = expect({error, enotempty}, {error, eexist}, {error, eacces}, - ?FILE_MODULE:del_dir(Base)), + ?FILE_MODULE:del_dir(Base)), io:format("Result: ~p", [E2]), %% Remove the current directory. {error, E3} = expect({error, einval}, - {error, eperm}, % Linux and DUX - {error, eacces}, - {error, ebusy}, - ?FILE_MODULE:del_dir(".")), + {error, eperm}, % Linux and DUX + {error, eacces}, + {error, ebusy}, + ?FILE_MODULE:del_dir(".")), io:format("Result: ~p", [E3]), %% No permission. @@ -2439,7 +2288,6 @@ e_del_dir(Config) when is_list(Config) -> ?FILE_MODULE:write_file_info( Base, #file_info {mode=8#600}) end, [] = flush(), - test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2448,35 +2296,35 @@ e_del_dir(Config) when is_list(Config) -> %% Trying reading and positioning from a compressed file. read_compressed_cooked(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Real = filename:join(Data, "realmen.html.gz"), - ?line {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed]), - ?line try_read_file_list(Fd). + Data = proplists:get_value(data_dir, Config), + Real = filename:join(Data, "realmen.html.gz"), + {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed]), + try_read_file_list(Fd). read_compressed_cooked_binary(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Real = filename:join(Data, "realmen.html.gz"), - ?line {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed,binary]), - ?line try_read_file_binary(Fd). + Data = proplists:get_value(data_dir, Config), + Real = filename:join(Data, "realmen.html.gz"), + {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed,binary]), + try_read_file_binary(Fd). %% Trying reading and positioning from an uncompressed file, %% but with the compressed flag given. read_not_really_compressed(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Priv = ?config(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + Priv = proplists:get_value(priv_dir, Config), %% The file realmen.html might have got CRs added (by WinZip). %% Remove them, or the file positions will not be correct. - ?line Real = filename:join(Data, "realmen.html"), - ?line RealPriv = filename:join(Priv, - atom_to_list(?MODULE)++"_realmen.html"), - ?line {ok, RealDataBin} = ?FILE_MODULE:read_file(Real), - ?line RealData = remove_crs(binary_to_list(RealDataBin), []), - ?line ok = ?FILE_MODULE:write_file(RealPriv, RealData), - ?line {ok, Fd} = ?FILE_MODULE:open(RealPriv, [read, compressed]), - ?line try_read_file_list(Fd). + Real = filename:join(Data, "realmen.html"), + RealPriv = filename:join(Priv, + atom_to_list(?MODULE)++"_realmen.html"), + {ok, RealDataBin} = ?FILE_MODULE:read_file(Real), + RealData = remove_crs(binary_to_list(RealDataBin), []), + ok = ?FILE_MODULE:write_file(RealPriv, RealData), + {ok, Fd} = ?FILE_MODULE:open(RealPriv, [read, compressed]), + try_read_file_list(Fd). remove_crs([$\r|Rest], Result) -> remove_crs(Rest, Result); @@ -2486,146 +2334,134 @@ remove_crs([], Result) -> lists:reverse(Result). try_read_file_list(Fd) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - %% Seek to the current position (nothing should happen). - ?line {ok, 0} = ?FILE_MODULE:position(Fd, 0), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}), + {ok, 0} = ?FILE_MODULE:position(Fd, 0), + {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}), %% Read a few lines from a compressed file. - ?line ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n", - ?line ShouldBe = io:get_line(Fd, ''), + ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n", + ShouldBe = io:get_line(Fd, ''), %% Now seek forward. - ?line {ok, 381} = ?FILE_MODULE:position(Fd, 381), - ?line Back = "Back in the good old days -- the \"Golden Era\" " ++ + {ok, 381} = ?FILE_MODULE:position(Fd, 381), + Back = "Back in the good old days -- the \"Golden Era\" " ++ "of computers, it was\n", - ?line Back = io:get_line(Fd, ''), + Back = io:get_line(Fd, ''), %% Try to search forward relative to the current position. - ?line {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}), - ?line RealPos = 4273, - ?line {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}), - ?line RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n", - ?line RealProg = io:get_line(Fd, ''), + {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}), + RealPos = 4273, + {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}), + RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n", + RealProg = io:get_line(Fd, ''), %% Seek backward. - ?line AfterTitle = length("<TITLE>"), - ?line {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle), - ?line Title = "Real Programmers Don't Use PASCAL</TITLE>\n", - ?line Title = io:get_line(Fd, ''), + AfterTitle = length("<TITLE>"), + {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle), + Title = "Real Programmers Don't Use PASCAL</TITLE>\n", + Title = io:get_line(Fd, ''), %% Seek past the end of the file. - ?line {ok, _} = ?FILE_MODULE:position(Fd, 25000), + {ok, _} = ?FILE_MODULE:position(Fd, 25000), %% Done. - ?line ?FILE_MODULE:close(Fd), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + ?FILE_MODULE:close(Fd), + [] = flush(), ok. try_read_file_binary(Fd) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - %% Seek to the current position (nothing should happen). - ?line {ok, 0} = ?FILE_MODULE:position(Fd, 0), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}), + {ok, 0} = ?FILE_MODULE:position(Fd, 0), + {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}), %% Read a few lines from a compressed file. - ?line ShouldBe = <<"<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n">>, - ?line ShouldBe = io:get_line(Fd, ''), + ShouldBe = <<"<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n">>, + ShouldBe = io:get_line(Fd, ''), %% Now seek forward. - ?line {ok, 381} = ?FILE_MODULE:position(Fd, 381), - ?line Back = <<"Back in the good old days -- the \"Golden Era\" " - "of computers, it was\n">>, - ?line Back = io:get_line(Fd, ''), + {ok, 381} = ?FILE_MODULE:position(Fd, 381), + Back = <<"Back in the good old days -- the \"Golden Era\" " + "of computers, it was\n">>, + Back = io:get_line(Fd, ''), %% Try to search forward relative to the current position. - ?line {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}), - ?line RealPos = 4273, - ?line {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}), - ?line RealProg = <<"<LI> Real Programmers aren't afraid to use GOTOs.\n">>, - ?line RealProg = io:get_line(Fd, ''), + {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}), + RealPos = 4273, + {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}), + RealProg = <<"<LI> Real Programmers aren't afraid to use GOTOs.\n">>, + RealProg = io:get_line(Fd, ''), %% Seek backward. - ?line AfterTitle = length("<TITLE>"), - ?line {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle), - ?line Title = <<"Real Programmers Don't Use PASCAL</TITLE>\n">>, - ?line Title = io:get_line(Fd, ''), + AfterTitle = length("<TITLE>"), + {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle), + Title = <<"Real Programmers Don't Use PASCAL</TITLE>\n">>, + Title = io:get_line(Fd, ''), %% Done. - ?line ?FILE_MODULE:close(Fd), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + ?FILE_MODULE:close(Fd), + [] = flush(), ok. read_cooked_tar_problem(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), + Data = proplists:get_value(data_dir, Config), + ProblemFile = filename:join(Data, "cooked_tar_problem.tar.gz"), + {ok,Fd} = ?FILE_MODULE:open(ProblemFile, [read,compressed,binary]), + + {ok,34304} = file:position(Fd, 34304), + {ok,Bin} = file:read(Fd, 512), + 512 = byte_size(Bin), - ?line Data = ?config(data_dir, Config), - ?line ProblemFile = filename:join(Data, "cooked_tar_problem.tar.gz"), - ?line {ok,Fd} = ?FILE_MODULE:open(ProblemFile, [read,compressed,binary]), + {ok,34304+512+1024} = file:position(Fd, {cur,1024}), - ?line {ok,34304} = file:position(Fd, 34304), - ?line {ok,Bin} = file:read(Fd, 512), - ?line 512 = byte_size(Bin), - - ?line {ok,34304+512+1024} = file:position(Fd, {cur,1024}), - - ?line ok = file:close(Fd), + ok = file:close(Fd), - ?line test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -write_compressed(suite) -> []; -write_compressed(doc) -> []; write_compressed(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line Priv = ?config(priv_dir, Config), - ?line MyFile = filename:join(Priv, - atom_to_list(?MODULE)++"_test.gz"), + Priv = proplists:get_value(priv_dir, Config), + MyFile = filename:join(Priv, + atom_to_list(?MODULE)++"_test.gz"), %% Write a file. - ?line {ok, Fd} = ?FILE_MODULE:open(MyFile, [write, compressed]), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, 0), - ?line Prefix = "hello\n", - ?line End = "end\n", - ?line ok = io:put_chars(Fd, Prefix), - ?line {ok, 143} = ?FILE_MODULE:position(Fd, 143), - ?line ok = io:put_chars(Fd, End), - ?line ok = ?FILE_MODULE:close(Fd), + {ok, Fd} = ?FILE_MODULE:open(MyFile, [write, compressed]), + {ok, 0} = ?FILE_MODULE:position(Fd, 0), + Prefix = "hello\n", + End = "end\n", + ok = io:put_chars(Fd, Prefix), + {ok, 143} = ?FILE_MODULE:position(Fd, 143), + ok = io:put_chars(Fd, End), + ok = ?FILE_MODULE:close(Fd), %% Read the file and verify the contents. - ?line {ok, Fd1} = ?FILE_MODULE:open(MyFile, [read, compressed]), - ?line Prefix = io:get_line(Fd1, ''), - ?line Second = lists:duplicate(143-length(Prefix), 0) ++ End, - ?line Second = io:get_line(Fd1, ''), - ?line ok = ?FILE_MODULE:close(Fd1), + {ok, Fd1} = ?FILE_MODULE:open(MyFile, [read, compressed]), + Prefix = io:get_line(Fd1, ''), + Second = lists:duplicate(143-length(Prefix), 0) ++ End, + Second = io:get_line(Fd1, ''), + ok = ?FILE_MODULE:close(Fd1), %% Verify successful compression by uncompressing the file %% using zlib:gunzip/1. - ?line {ok,Contents} = file:read_file(MyFile), - ?line <<"hello\n",0:137/unit:8,"end\n">> = zlib:gunzip(Contents), + {ok,Contents} = file:read_file(MyFile), + <<"hello\n",0:137/unit:8,"end\n">> = zlib:gunzip(Contents), %% Ensure that the file is compressed. @@ -2634,99 +2470,92 @@ write_compressed(Config) when is_list(Config) -> {ok, #file_info{size=Size}} when Size < TotalSize -> ok; {ok, #file_info{size=Size}} when Size == TotalSize -> - test_server:fail(file_not_compressed) + ct:fail(file_not_compressed) end, %% Write again to ensure that the file is truncated. - ?line {ok, Fd2} = ?FILE_MODULE:open(MyFile, [write, compressed]), - ?line NewString = "aaaaaaaaaaa", - ?line ok = io:put_chars(Fd2, NewString), - ?line ok = ?FILE_MODULE:close(Fd2), - ?line {ok, Fd3} = ?FILE_MODULE:open(MyFile, [read, compressed]), - ?line {ok, NewString} = ?FILE_MODULE:read(Fd3, 1024), - ?line ok = ?FILE_MODULE:close(Fd3), + {ok, Fd2} = ?FILE_MODULE:open(MyFile, [write, compressed]), + NewString = "aaaaaaaaaaa", + ok = io:put_chars(Fd2, NewString), + ok = ?FILE_MODULE:close(Fd2), + {ok, Fd3} = ?FILE_MODULE:open(MyFile, [read, compressed]), + {ok, NewString} = ?FILE_MODULE:read(Fd3, 1024), + ok = ?FILE_MODULE:close(Fd3), %% Done. - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% catenated_gzips(Config) when is_list(Config) -> - ?line Priv = ?config(priv_dir, Config), - ?line MyFile = filename:join(Priv, ?MODULE_STRING++"_test.gz"), + Priv = proplists:get_value(priv_dir, Config), + MyFile = filename:join(Priv, ?MODULE_STRING++"_test.gz"), First = "Hello, all good men going to search parties. ", Second = "Now I really need your help.", All = iolist_to_binary([First|Second]), - ?line Cat = [zlib:gzip(First),zlib:gzip(Second)], - - ?line ok = file:write_file(MyFile, Cat), + Cat = [zlib:gzip(First),zlib:gzip(Second)], + + ok = file:write_file(MyFile, Cat), - ?line {ok,Fd} = file:open(MyFile, [read,compressed,binary]), - ?line {ok,All} = file:read(Fd, 100000), - ?line ok = file:close(Fd), + {ok,Fd} = file:open(MyFile, [read,compressed,binary]), + {ok,All} = file:read(Fd, 100000), + ok = file:close(Fd), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compress_errors(suite) -> []; -compress_errors(doc) -> []; compress_errors(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line DataDir = + DataDir = filename:dirname( - filename:join(?config(data_dir, Config), "x")), - ?line DataDirSlash = DataDir++"/", - ?line {error, enoent} = ?FILE_MODULE:open("non_existing__", - [compressed, read]), - ?line {error, einval} = ?FILE_MODULE:open("non_existing__", - [compressed, read, write]), - ?line {error, einval} = ?FILE_MODULE:open("non_existing__", - [compressed, read, append]), - ?line {error, einval} = ?FILE_MODULE:open("non_existing__", - [compressed, write, append]), - ?line {error, E1} = ?FILE_MODULE:open(DataDir, [compressed, read]), - ?line {error, E2} = ?FILE_MODULE:open(DataDirSlash, [compressed, read]), - ?line {error, E3} = ?FILE_MODULE:open(DataDir, [compressed, write]), - ?line {error, E4} = ?FILE_MODULE:open(DataDirSlash, [compressed, write]), - ?line {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4}, + filename:join(proplists:get_value(data_dir, Config), "x")), + DataDirSlash = DataDir++"/", + {error, enoent} = ?FILE_MODULE:open("non_existing__", + [compressed, read]), + {error, einval} = ?FILE_MODULE:open("non_existing__", + [compressed, read, write]), + {error, einval} = ?FILE_MODULE:open("non_existing__", + [compressed, read, append]), + {error, einval} = ?FILE_MODULE:open("non_existing__", + [compressed, write, append]), + {error, E1} = ?FILE_MODULE:open(DataDir, [compressed, read]), + {error, E2} = ?FILE_MODULE:open(DataDirSlash, [compressed, read]), + {error, E3} = ?FILE_MODULE:open(DataDir, [compressed, write]), + {error, E4} = ?FILE_MODULE:open(DataDirSlash, [compressed, write]), + {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4}, %% Read a corrupted .gz file. - ?line Corrupted = filename:join(DataDir, "corrupted.gz"), - ?line {ok, Fd} = ?FILE_MODULE:open(Corrupted, [read, compressed]), - ?line {error, eio} = ?FILE_MODULE:read(Fd, 100), - ?line ?FILE_MODULE:close(Fd), + Corrupted = filename:join(DataDir, "corrupted.gz"), + {ok, Fd} = ?FILE_MODULE:open(Corrupted, [read, compressed]), + {error, eio} = ?FILE_MODULE:read(Fd, 100), + ?FILE_MODULE:close(Fd), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compress_async_crash(suite) -> []; -compress_async_crash(doc) -> []; compress_async_crash(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line Path = filename:join(DataDir, "test.gz"), + DataDir = proplists:get_value(data_dir, Config), + Path = filename:join(DataDir, "test.gz"), ExpectedData = <<"qwerty">>, - ?line _ = ?FILE_MODULE:delete(Path), - ?line {ok, Fd} = ?FILE_MODULE:open(Path, [write, binary, compressed]), - ?line ok = ?FILE_MODULE:write(Fd, ExpectedData), - ?line ok = ?FILE_MODULE:close(Fd), + _ = ?FILE_MODULE:delete(Path), + {ok, Fd} = ?FILE_MODULE:open(Path, [write, binary, compressed]), + ok = ?FILE_MODULE:write(Fd, ExpectedData), + ok = ?FILE_MODULE:close(Fd), - % Test that when using async thread pool, the emulator doesn't crash - % when the efile port driver is stopped while a compressed file operation - % is in progress (being carried by an async thread). - ?line ok = compress_async_crash_loop(10000, Path, ExpectedData), - ?line ok = ?FILE_MODULE:delete(Path), + %% Test that when using async thread pool, the emulator doesn't crash + %% when the efile port driver is stopped while a compressed file operation + %% is in progress (being carried by an async thread). + ok = compress_async_crash_loop(10000, Path, ExpectedData), + ok = ?FILE_MODULE:delete(Path), ok. compress_async_crash_loop(0, _Path, _ExpectedData) -> @@ -2734,80 +2563,107 @@ compress_async_crash_loop(0, _Path, _ExpectedData) -> compress_async_crash_loop(N, Path, ExpectedData) -> Parent = self(), {Pid, Ref} = spawn_monitor( - fun() -> - ?line {ok, Fd} = ?FILE_MODULE:open( - Path, [read, compressed, raw, binary]), - Len = byte_size(ExpectedData), - Parent ! {self(), continue}, - ?line {ok, ExpectedData} = ?FILE_MODULE:read(Fd, Len), - ?line ok = ?FILE_MODULE:close(Fd), - receive foobar -> ok end - end), + fun() -> + {ok, Fd} = ?FILE_MODULE:open( + Path, [read, compressed, raw, binary]), + Len = byte_size(ExpectedData), + Parent ! {self(), continue}, + {ok, ExpectedData} = ?FILE_MODULE:read(Fd, Len), + ok = ?FILE_MODULE:close(Fd), + receive foobar -> ok end + end), receive {Pid, continue} -> exit(Pid, shutdown), receive {'DOWN', Ref, _, _, Reason} -> - ?line shutdown = Reason + shutdown = Reason end; {'DOWN', Ref, _, _, Reason2} -> - test_server:fail({worker_exited, Reason2}) + ct:fail({worker_exited, Reason2}) after 60000 -> exit(Pid, shutdown), erlang:demonitor(Ref, [flush]), - test_server:fail(worker_timeout) + ct:fail(worker_timeout) end, compress_async_crash_loop(N - 1, Path, ExpectedData). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -altname(doc) -> - "Test the file:altname/1 function"; -altname(suite) -> - []; +unicode(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + Name = filename:join(Dir, "data-utf8.txt"), + Txt = lists:seq(128, 255), + D = unicode:characters_to_binary(Txt, latin1, latin1), + {ok,Fd1} = + ?FILE_MODULE:open(Name, [write,read,binary,{encoding,unicode}]), + ok = ?FILE_MODULE:truncate(Fd1), + ok = ?FILE_MODULE:write(Fd1, Txt), + {ok,0} = ?FILE_MODULE:position(Fd1, bof), + {ok,D} = ?FILE_MODULE:read(Fd1, 129), + {ok,0} = ?FILE_MODULE:position(Fd1, bof), + {ok,D1} = ?FILE_MODULE:read(Fd1, 64), + {ok,Pos} = ?FILE_MODULE:position(Fd1, cur), + {ok,D2} = ?FILE_MODULE:pread(Fd1, {cur,0}, 65), + D = <<D1/binary, D2/binary>>, + {ok,D1} = ?FILE_MODULE:pread(Fd1, bof, 64), + {ok,Pos} = ?FILE_MODULE:position(Fd1, Pos), + {ok,D2} = ?FILE_MODULE:read(Fd1, 64), + ok = ?FILE_MODULE:close(Fd1), + %% + RawD = unicode:characters_to_binary(Txt, latin1, unicode), + {ok,RawD} = ?FILE_MODULE:read_file(Name), + %% + {ok,Fd2} = ?FILE_MODULE:open(Name, [read,{encoding,unicode}]), + {ok,Txt} = ?FILE_MODULE:read(Fd2, 129), + {Txt1,Txt2} = lists:split(64, Txt), + {ok,Txt2} = ?FILE_MODULE:pread(Fd2, Pos, 65), + {ok,0} = ?FILE_MODULE:position(Fd2, bof), + {ok,Txt1} = ?FILE_MODULE:read(Fd2, 64), + ok = ?FILE_MODULE:close(Fd2). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Test the file:altname/1 function. altname(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - "long alternative path name with spaces"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - ?line Name = filename:join(NewDir, "a_file_with_long_name"), - ?line ShortName = filename:join(NewDir, "short"), - ?line NonexName = filename:join(NewDir, "nonexistent"), - ?line ok = ?FILE_MODULE:write_file(Name, "some contents\n"), - ?line ok = ?FILE_MODULE:write_file(ShortName, "some contents\n"), - ?line Result = + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + "long alternative path name with spaces"), + ok = ?FILE_MODULE:make_dir(NewDir), + Name = filename:join(NewDir, "a_file_with_long_name"), + ShortName = filename:join(NewDir, "short"), + NonexName = filename:join(NewDir, "nonexistent"), + ok = ?FILE_MODULE:write_file(Name, "some contents\n"), + ok = ?FILE_MODULE:write_file(ShortName, "some contents\n"), + Result = case ?FILE_MODULE:altname(NewDir) of {error, enotsup} -> {skipped, "Altname not supported on this platform"}; {ok, "LONGAL~1"} -> - ?line {ok, "A_FILE~1"} = ?FILE_MODULE:altname(Name), - ?line {ok, "C:/"} = ?FILE_MODULE:altname("C:/"), - ?line {ok, "C:\\"} = ?FILE_MODULE:altname("C:\\"), - ?line {error,enoent} = ?FILE_MODULE:altname(NonexName), - ?line {ok, "short"} = ?FILE_MODULE:altname(ShortName), + {ok, "A_FILE~1"} = ?FILE_MODULE:altname(Name), + {ok, "C:/"} = ?FILE_MODULE:altname("C:/"), + {ok, "C:\\"} = ?FILE_MODULE:altname("C:\\"), + {error,enoent} = ?FILE_MODULE:altname(NonexName), + {ok, "short"} = ?FILE_MODULE:altname(ShortName), ok end, - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), Result. -make_link(doc) -> "Test creating a hard link."; -make_link(suite) -> []; +%% Test creating a hard link. make_link(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_make_link"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - - ?line Name = filename:join(NewDir, "a_file"), - ?line ok = ?FILE_MODULE:write_file(Name, "some contents\n"), - - ?line Alias = filename:join(NewDir, "an_alias"), - ?line Result = + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_make_link"), + ok = ?FILE_MODULE:make_dir(NewDir), + + Name = filename:join(NewDir, "a_file"), + ok = ?FILE_MODULE:write_file(Name, "some contents\n"), + + Alias = filename:join(NewDir, "an_alias"), + Result = case ?FILE_MODULE:make_link(Name, Alias) of {error, enotsup} -> {skipped, "Links not supported on this platform"}; @@ -2817,53 +2673,45 @@ make_link(Config) when is_list(Config) -> %% which should in behave exactly as %% ?FILE_MODULE:read_file_info/1 %% since they are not used on symbolic links. - - ?line {ok, Info} = ?FILE_MODULE:read_link_info(Name), + + {ok, Info} = ?FILE_MODULE:read_link_info(Name), {ok,Info} = ?FILE_MODULE:read_link_info(Name, [raw]), - ?line {ok, Info} = ?FILE_MODULE:read_link_info(Alias), + {ok, Info} = ?FILE_MODULE:read_link_info(Alias), {ok,Info} = ?FILE_MODULE:read_link_info(Alias, [raw]), - ?line #file_info{links = 2, type = regular} = Info, - ?line {error, eexist} = + #file_info{links = 2, type = regular} = Info, + {error, eexist} = ?FILE_MODULE:make_link(Name, Alias), ok end, - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + + [] = flush(), Result. -read_link_info_for_non_link(doc) -> - "Test that reading link info for an ordinary file or directory works " - "(on all platforms)."; -read_link_info_for_non_link(suite) -> []; +%% Test that reading link info for an ordinary file or directory works +%% (on all platforms). read_link_info_for_non_link(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - - ?line {ok, #file_info{type=directory}} = + {ok, #file_info{type=directory}} = ?FILE_MODULE:read_link_info("."), {ok, #file_info{type=directory}} = ?FILE_MODULE:read_link_info(".", [raw]), - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + + [] = flush(), ok. -symlinks(doc) -> "Test operations on symbolic links (for Unix)."; -symlinks(suite) -> []; +%% Test operations on symbolic links (for Unix). symlinks(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line {error, _} = ?FILE_MODULE:read_link(lists:duplicate(10000,$a)), + {error, _} = ?FILE_MODULE:read_link(lists:duplicate(10000,$a)), {error, _} = ?FILE_MODULE:read_link_all(lists:duplicate(10000,$a)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_symlinks"), - ?line ok = ?FILE_MODULE:make_dir(NewDir), - - ?line Name = filename:join(NewDir, "a_plain_file"), - ?line ok = ?FILE_MODULE:write_file(Name, "some stupid content\n"), - - ?line Alias = filename:join(NewDir, "a_symlink_alias"), - ?line Result = + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_symlinks"), + ok = ?FILE_MODULE:make_dir(NewDir), + + Name = filename:join(NewDir, "a_plain_file"), + ok = ?FILE_MODULE:write_file(Name, "some stupid content\n"), + + Alias = filename:join(NewDir, "a_symlink_alias"), + Result = case ?FILE_MODULE:make_symlink(Name, Alias) of {error, enotsup} -> {skipped, "Links not supported on this platform"}; @@ -2871,41 +2719,37 @@ symlinks(Config) when is_list(Config) -> {win32,_} = os:type(), {skipped, "Windows user not privileged to create symlinks"}; ok -> - ?line {ok, Info1} = ?FILE_MODULE:read_file_info(Name), + {ok, Info1} = ?FILE_MODULE:read_file_info(Name), {ok,Info1} = ?FILE_MODULE:read_file_info(Name, [raw]), - ?line {ok, Info1} = ?FILE_MODULE:read_file_info(Alias), + {ok, Info1} = ?FILE_MODULE:read_file_info(Alias), {ok,Info1} = ?FILE_MODULE:read_file_info(Alias, [raw]), - ?line {ok, Info1} = ?FILE_MODULE:read_link_info(Name), + {ok, Info1} = ?FILE_MODULE:read_link_info(Name), {ok,Info1} = ?FILE_MODULE:read_link_info(Name, [raw]), - ?line #file_info{links = 1, type = regular} = Info1, - - ?line {ok, Info2} = ?FILE_MODULE:read_link_info(Alias), + #file_info{links = 1, type = regular} = Info1, + + {ok, Info2} = ?FILE_MODULE:read_link_info(Alias), {ok,Info2} = ?FILE_MODULE:read_link_info(Alias, [raw]), - ?line #file_info{links=1, type=symlink} = Info2, - ?line {ok, Name} = ?FILE_MODULE:read_link(Alias), + #file_info{links=1, type=symlink} = Info2, + {ok, Name} = ?FILE_MODULE:read_link(Alias), {ok, Name} = ?FILE_MODULE:read_link_all(Alias), %% If all is good, delete dir again (avoid hanging dir on windows) rm_rf(?FILE_MODULE,NewDir), ok - end, - - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + end, + + [] = flush(), Result. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -copy(doc) -> []; -copy(suite) -> []; copy(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), %% Create a text file. - ?line Name1 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_1.txt"), - ?line Line = "The quick brown fox jumps over a lazy dog. 0123456789\n", - ?line Len = length(Line), - ?line {ok, Handle1} = ?FILE_MODULE:open(Name1, [write]), - ?line {_, Size1} = + Name1 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_1.txt"), + Line = "The quick brown fox jumps over a lazy dog. 0123456789\n", + Len = length(Line), + {ok, Handle1} = ?FILE_MODULE:open(Name1, [write]), + {_, Size1} = iterate({0, 0}, done, fun({_, S}) when S >= 128*1024 -> @@ -2915,45 +2759,44 @@ copy(Config) when is_list(Config) -> ok = ?FILE_MODULE:write(Handle1, [H, " ", Line]), {N + 1, S + length(H) + 1 + Len} end), - ?line ?FILE_MODULE:close(Handle1), + ?FILE_MODULE:close(Handle1), %% Make a copy - ?line Name2 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_2.txt"), - ?line {ok, Size1} = ?FILE_MODULE:copy(Name1, Name2), + Name2 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_2.txt"), + {ok, Size1} = ?FILE_MODULE:copy(Name1, Name2), %% Concatenate 1 - ?line Name3 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_3.txt"), - ?line {ok, Handle3} = ?FILE_MODULE:open(Name3, [raw, write, binary]), - ?line {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle3), - ?line {ok, Handle2} = ?FILE_MODULE:open(Name2, [read, binary]), - ?line {ok, Size1} = ?FILE_MODULE:copy(Handle2, Handle3), - ?line ok = ?FILE_MODULE:close(Handle3), - ?line ok = ?FILE_MODULE:close(Handle2), + Name3 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_3.txt"), + {ok, Handle3} = ?FILE_MODULE:open(Name3, [raw, write, binary]), + {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle3), + {ok, Handle2} = ?FILE_MODULE:open(Name2, [read, binary]), + {ok, Size1} = ?FILE_MODULE:copy(Handle2, Handle3), + ok = ?FILE_MODULE:close(Handle3), + ok = ?FILE_MODULE:close(Handle2), %% Concatenate 2 - ?line Name4 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_4.txt"), - ?line {ok, Handle4} = ?FILE_MODULE:open(Name4, [write, binary]), - ?line {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle4), - ?line {ok, Handle5} = ?FILE_MODULE:open(Name2, [raw, read, binary]), - ?line {ok, Size1} = ?FILE_MODULE:copy(Handle5, Handle4), - ?line ok = ?FILE_MODULE:close(Handle5), - ?line ok = ?FILE_MODULE:close(Handle4), + Name4 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_4.txt"), + {ok, Handle4} = ?FILE_MODULE:open(Name4, [write, binary]), + {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle4), + {ok, Handle5} = ?FILE_MODULE:open(Name2, [raw, read, binary]), + {ok, Size1} = ?FILE_MODULE:copy(Handle5, Handle4), + ok = ?FILE_MODULE:close(Handle5), + ok = ?FILE_MODULE:close(Handle4), %% %% Just for test of the test - %% ?line {ok, Handle2q} = ?FILE_MODULE:open(Name2, [write, append]), - %% ?line ok = ?FILE_MODULE:write(Handle2q, "q"), - %% ?line ok = ?FILE_MODULE:close(Handle2q), + %% {ok, Handle2q} = ?FILE_MODULE:open(Name2, [write, append]), + %% ok = ?FILE_MODULE:write(Handle2q, "q"), + %% ok = ?FILE_MODULE:close(Handle2q), %% Compare the files - ?line {ok, Handle1a} = ?FILE_MODULE:open(Name1, [raw, read]), - ?line {ok, Handle2a} = ?FILE_MODULE:open(Name2, [raw, read]), - ?line true = stream_cmp(fd_stream_factory([Handle1a]), - fd_stream_factory([Handle2a])), - ?line {ok, 0} = ?FILE_MODULE:position(Handle1a, 0), - ?line {ok, 0} = ?FILE_MODULE:position(Handle2a, 0), - ?line {ok, Handle3a} = ?FILE_MODULE:open(Name3, [raw, read]), - ?line true = stream_cmp(fd_stream_factory([Handle1a, Handle2a]), - fd_stream_factory([Handle2a])), - ?line ok = ?FILE_MODULE:close(Handle1a), - ?line ok = ?FILE_MODULE:close(Handle2a), - ?line ok = ?FILE_MODULE:close(Handle3a), - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + {ok, Handle1a} = ?FILE_MODULE:open(Name1, [raw, read]), + {ok, Handle2a} = ?FILE_MODULE:open(Name2, [raw, read]), + true = stream_cmp(fd_stream_factory([Handle1a]), + fd_stream_factory([Handle2a])), + {ok, 0} = ?FILE_MODULE:position(Handle1a, 0), + {ok, 0} = ?FILE_MODULE:position(Handle2a, 0), + {ok, Handle3a} = ?FILE_MODULE:open(Name3, [raw, read]), + true = stream_cmp(fd_stream_factory([Handle1a, Handle2a]), + fd_stream_factory([Handle2a])), + ok = ?FILE_MODULE:close(Handle1a), + ok = ?FILE_MODULE:close(Handle2a), + ok = ?FILE_MODULE:close(Handle3a), + [] = flush(), ok. @@ -2974,7 +2817,7 @@ fd_stream_factory([Fd | T] = L) -> end end. - + stream_cmp(F1, F2) when is_function(F1), is_function(F2) -> stream_cmp(F1(), F2()); @@ -2999,80 +2842,75 @@ stream_cmp([H | T1], [H | T2]) -> %% Test the get_cwd(), open(), and copy() file server calls. new_slave(_RootDir, Cwd) -> - ?line L = "qwertyuiopasdfghjklzxcvbnm", - ?line N = length(L), - ?line {ok, Cwd} = ?FILE_MODULE:get_cwd(), - ?line {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase - ?line {ok, FD1} = ?FILE_MODULE:open("file1.txt", write), - ?line ok = ?FILE_MODULE:close(FD1), - ?line {ok, FD2} = ?FILE_MODULE:open("file1.txt", - [write, append, - binary, compressed, - delayed_write, - {delayed_write, 0, 0}, - read_ahead, - {read_ahead, 0}]), - ?line ok = ?FILE_MODULE:write(FD2, L), - ?line ok = ?FILE_MODULE:close(FD2), - ?line {ok, N2} = ?FILE_MODULE:copy("file1.txt", "file2.txt"), - ?line io:format("Size ~p, compressed ~p.~n", [N, N2]), - ?line {ok, FD3} = ?FILE_MODULE:open("file2.txt", - [binary, compressed]), + L = "qwertyuiopasdfghjklzxcvbnm", + N = length(L), + {ok, Cwd} = ?FILE_MODULE:get_cwd(), + {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase + {ok, FD1} = ?FILE_MODULE:open("file1.txt", write), + ok = ?FILE_MODULE:close(FD1), + {ok, FD2} = ?FILE_MODULE:open("file1.txt", + [write, append, + binary, compressed, + delayed_write, + {delayed_write, 0, 0}, + read_ahead, + {read_ahead, 0}]), + ok = ?FILE_MODULE:write(FD2, L), + ok = ?FILE_MODULE:close(FD2), + {ok, N2} = ?FILE_MODULE:copy("file1.txt", "file2.txt"), + io:format("Size ~p, compressed ~p.~n", [N, N2]), + {ok, FD3} = ?FILE_MODULE:open("file2.txt", + [binary, compressed]), %% The file_io_server will translate the binary into a list - ?line {ok, L} = ?FILE_MODULE:read(FD3, N+1), - ?line ok = ?FILE_MODULE:close(FD3), + {ok, L} = ?FILE_MODULE:read(FD3, N+1), + ok = ?FILE_MODULE:close(FD3), %% - ?line ok = ?FILE_MODULE:delete("file1.txt"), - ?line ok = ?FILE_MODULE:delete("file2.txt"), - ?line [] = flush(), + ok = ?FILE_MODULE:delete("file1.txt"), + ok = ?FILE_MODULE:delete("file2.txt"), + [] = flush(), ok. %% Test the get_cwd() and open() file server calls. old_slave(_RootDir, Cwd) -> - ?line L = "qwertyuiopasdfghjklzxcvbnm", - ?line N = length(L), - ?line {ok, Cwd} = ?FILE_MODULE:get_cwd(), - ?line {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase - ?line {ok, FD1} = ?FILE_MODULE:open("file1.txt", write), - ?line ok = ?FILE_MODULE:close(FD1), - ?line {ok, FD2} = ?FILE_MODULE:open("file1.txt", - [write, binary, compressed]), - ?line ok = ?FILE_MODULE:write(FD2, L), - ?line ok = ?FILE_MODULE:close(FD2), - ?line {ok, FD3} = ?FILE_MODULE:open("file1.txt", [write, append]), - ?line ok = ?FILE_MODULE:close(FD3), - ?line {ok, FD4} = ?FILE_MODULE:open("file1.txt", - [binary, compressed]), + L = "qwertyuiopasdfghjklzxcvbnm", + N = length(L), + {ok, Cwd} = ?FILE_MODULE:get_cwd(), + {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase + {ok, FD1} = ?FILE_MODULE:open("file1.txt", write), + ok = ?FILE_MODULE:close(FD1), + {ok, FD2} = ?FILE_MODULE:open("file1.txt", + [write, binary, compressed]), + ok = ?FILE_MODULE:write(FD2, L), + ok = ?FILE_MODULE:close(FD2), + {ok, FD3} = ?FILE_MODULE:open("file1.txt", [write, append]), + ok = ?FILE_MODULE:close(FD3), + {ok, FD4} = ?FILE_MODULE:open("file1.txt", + [binary, compressed]), %% The file_io_server will translate the binary into a list - ?line {ok, L} = ?FILE_MODULE:read(FD4, N+1), - ?line ok = ?FILE_MODULE:close(FD4), + {ok, L} = ?FILE_MODULE:read(FD4, N+1), + ok = ?FILE_MODULE:close(FD4), %% - ?line ok = ?FILE_MODULE:delete("file1.txt"), - ?line [] = flush(), + ok = ?FILE_MODULE:delete("file1.txt"), + [] = flush(), ok. run_test(Test, Args) -> - ?line case (catch apply(?MODULE, Test, Args)) of - {'EXIT', _} = Exit -> - {done, Exit, get(test_server_loc)}; - Result -> - {done, Result} - end. + case (catch apply(?MODULE, Test, Args)) of + {'EXIT', _} = Exit -> + {done, Exit, get(test_server_loc)}; + Result -> + {done, Result} + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -delayed_write(suite) -> - []; -delayed_write(doc) -> - ["Tests the file open option {delayed_write, Size, Delay}"]; +%% Tests the file open option {delayed_write, Size, Delay}. delayed_write(Config) when is_list(Config) -> - Dog = ?t:timetrap(?t:seconds(20)), - - RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), File = filename:join(RootDir, - atom_to_list(?MODULE)++"_delayed_write.txt"), + atom_to_list(?MODULE)++"_delayed_write.txt"), Data1 = "asdfghjkl", Data2 = "qwertyuio", Data3 = "zxcvbnm,.", @@ -3087,18 +2925,18 @@ delayed_write(Config) when is_list(Config) -> {ok, Fd1} = ?FILE_MODULE:open(File, [write, {delayed_write, Size+1, 2000}]), ok = ?FILE_MODULE:write(Fd1, Data1), - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow {ok, Fd2} = ?FILE_MODULE:open(File, [read]), eof = ?FILE_MODULE:read(Fd2, 1), ok = ?FILE_MODULE:write(Fd1, Data1), % Data flush on size - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow {ok, Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 2*Size+1), ok = ?FILE_MODULE:write(Fd1, Data1), - ?t:sleep(3000), % Wait until data flush on timeout + timer:sleep(3000), % Wait until data flush on timeout {ok, Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 3*Size+1), ok = ?FILE_MODULE:write(Fd1, Data1), ok = ?FILE_MODULE:close(Fd1), % Data flush on close - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow {ok, Data1Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 4*Size+1), ok = ?FILE_MODULE:close(Fd2), %% @@ -3106,33 +2944,33 @@ delayed_write(Config) when is_list(Config) -> %% raw file, default parameters. Parent = self(), Fun = fun() -> - Child = self(), - Test = - fun () -> - {ok, Fd} = ?FILE_MODULE:open(File, - [raw, write, delayed_write]), - ok = ?FILE_MODULE:write(Fd, Data1), - Parent ! {Child, wrote}, - receive - {Parent, continue, Reason} -> - {ok, Reason} - end - end, - case (catch Test()) of - {ok, Reason} -> exit(Reason); - Unknown -> - exit({Unknown, get(test_server_loc)}) - end - end, + Child = self(), + Test = + fun () -> + {ok, Fd} = ?FILE_MODULE:open(File, + [raw, write, delayed_write]), + ok = ?FILE_MODULE:write(Fd, Data1), + Parent ! {Child, wrote}, + receive + {Parent, continue, Reason} -> + {ok, Reason} + end + end, + case (catch Test()) of + {ok, Reason} -> exit(Reason); + Unknown -> + exit({Unknown, get(test_server_loc)}) + end + end, Child1 = spawn(Fun), Mref1 = erlang:monitor(process, Child1), receive {Child1, wrote} -> ok; {'DOWN', Mref1, _, _, _} = Down1a -> - ?t:fail(Down1a) + ct:fail(Down1a) end, - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow {ok, Fd3} = ?FILE_MODULE:open(File, [read]), eof = ?FILE_MODULE:read(Fd3, 1), Child1 ! {Parent, continue, normal}, @@ -3140,9 +2978,9 @@ delayed_write(Config) when is_list(Config) -> {'DOWN', Mref1, process, Child1, normal} -> ok; {'DOWN', Mref1, _, _, _} = Down1b -> - ?t:fail(Down1b) + ct:fail(Down1b) end, - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow {ok, Data1} = ?FILE_MODULE:pread(Fd3, bof, Size+1), ok = ?FILE_MODULE:close(Fd3), %% @@ -3153,9 +2991,9 @@ delayed_write(Config) when is_list(Config) -> {Child2, wrote} -> ok; {'DOWN', Mref2, _, _, _} = Down2a -> - ?t:fail(Down2a) + ct:fail(Down2a) end, - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow {ok, Fd4} = ?FILE_MODULE:open(File, [read]), eof = ?FILE_MODULE:read(Fd4, 1), Child2 ! {Parent, continue, kill}, @@ -3163,15 +3001,15 @@ delayed_write(Config) when is_list(Config) -> {'DOWN', Mref2, process, Child2, kill} -> ok; {'DOWN', Mref2, _, _, _} = Down2b -> - ?t:fail(Down2b) + ct:fail(Down2b) end, - ?t:sleep(1000), % Just in case the file system is slow + timer:sleep(1000), % Just in case the file system is slow eof = ?FILE_MODULE:pread(Fd4, bof, 1), ok = ?FILE_MODULE:close(Fd4), %% %% Test if file position works with delayed_write {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, - delayed_write]), + delayed_write]), ok = ?FILE_MODULE:truncate(Fd5), ok = ?FILE_MODULE:write(Fd5, [Data1|Data2]), {ok, 0} = ?FILE_MODULE:position(Fd5, bof), @@ -3183,93 +3021,82 @@ delayed_write(Config) when is_list(Config) -> ok = ?FILE_MODULE:close(Fd5), %% [] = flush(), - ?t:timetrap_cancel(Dog), ok. -pid2name(doc) -> "Tests file:pid2name/1."; -pid2name(suite) -> []; +%% Tests file:pid2name/1. pid2name(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line Base = test_server:temp_name( - filename:join(RootDir, "pid2name_")), - ?line Name1 = [Base, '.txt'], - ?line Name2 = Base ++ ".txt", + RootDir = proplists:get_value(priv_dir, Config), + Base = test_server:temp_name( + filename:join(RootDir, "pid2name_")), + Name1 = [Base, '.txt'], + Name2 = Base ++ ".txt", %% - ?line {ok, Pid} = file:open(Name1, [write]), - ?line {ok, Name2} = file:pid2name(Pid), - ?line undefined = file:pid2name(self()), - ?line ok = file:close(Pid), - ?line test_server:sleep(1000), - ?line false = is_process_alive(Pid), - ?line undefined = file:pid2name(Pid), - %% - ?line test_server:timetrap_cancel(Dog), + {ok, Pid} = file:open(Name1, [write]), + {ok, Name2} = file:pid2name(Pid), + undefined = file:pid2name(self()), + ok = file:close(Pid), + ct:sleep(1000), + false = is_process_alive(Pid), + undefined = file:pid2name(Pid), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -read_ahead(suite) -> - []; -read_ahead(doc) -> - ["Tests the file open option {read_ahead, Size}"]; +%% Tests the file open option {read_ahead, Size}. read_ahead(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(20)), - %% - ?line RootDir = ?config(priv_dir, Config), - ?line File = filename:join(RootDir, - atom_to_list(?MODULE)++"_read_ahead.txt"), - ?line Data1 = "asdfghjkl", % Must be - ?line Data2 = "qwertyuio", % same - ?line Data3 = "zxcvbnm,.", % length - ?line Size = length(Data1), - ?line Size = length(Data2), - ?line Size = length(Data3), + RootDir = proplists:get_value(priv_dir, Config), + File = filename:join(RootDir, + atom_to_list(?MODULE)++"_read_ahead.txt"), + Data1 = "asdfghjkl", % Must be + Data2 = "qwertyuio", % same + Data3 = "zxcvbnm,.", % length + Size = length(Data1), + Size = length(Data2), + Size = length(Data3), %% %% Test caching of normal non-raw file - ?line {ok, Fd1} = ?FILE_MODULE:open(File, [write]), - ?line ok = ?FILE_MODULE:write(Fd1, [Data1|Data1]), - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Fd2} = ?FILE_MODULE:open(File, [read, {read_ahead, 2*Size}]), - ?line {ok, Data1} = ?FILE_MODULE:read(Fd2, Size), - ?line ok = ?FILE_MODULE:pwrite(Fd1, Size, Data2), - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Data1} = ?FILE_MODULE:read(Fd2, Size), % Will read cached data - ?line Data2Data2Data2 = Data2++Data2++Data2, - ?line ok = ?FILE_MODULE:pwrite(Fd1, eof, Data2Data2Data2), - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Data2Data2Data2} = + {ok, Fd1} = ?FILE_MODULE:open(File, [write]), + ok = ?FILE_MODULE:write(Fd1, [Data1|Data1]), + timer:sleep(1000), % Just in case the file system is slow + {ok, Fd2} = ?FILE_MODULE:open(File, [read, {read_ahead, 2*Size}]), + {ok, Data1} = ?FILE_MODULE:read(Fd2, Size), + ok = ?FILE_MODULE:pwrite(Fd1, Size, Data2), + timer:sleep(1000), % Just in case the file system is slow + {ok, Data1} = ?FILE_MODULE:read(Fd2, Size), % Will read cached data + Data2Data2Data2 = Data2++Data2++Data2, + ok = ?FILE_MODULE:pwrite(Fd1, eof, Data2Data2Data2), + timer:sleep(1000), % Just in case the file system is slow + {ok, Data2Data2Data2} = ?FILE_MODULE:read(Fd2, 3*Size), % Read more than cache buffer - ?line ok = ?FILE_MODULE:close(Fd1), - ?line ok = ?FILE_MODULE:close(Fd2), + ok = ?FILE_MODULE:close(Fd1), + ok = ?FILE_MODULE:close(Fd2), %% Test caching of raw file and default parameters - ?line {ok, Fd3} = ?FILE_MODULE:open(File, [raw, write]), - ?line ok = ?FILE_MODULE:write(Fd3, [Data1|Data1]), - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Fd4} = ?FILE_MODULE:open(File, [raw, read, read_ahead]), - ?line {ok, Data1} = ?FILE_MODULE:read(Fd4, Size), - ?line ok = ?FILE_MODULE:pwrite(Fd3, Size, Data2), - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Data1} = ?FILE_MODULE:read(Fd4, Size), % Will read cached data - ?line ok = ?FILE_MODULE:close(Fd3), - ?line ok = ?FILE_MODULE:close(Fd4), + {ok, Fd3} = ?FILE_MODULE:open(File, [raw, write]), + ok = ?FILE_MODULE:write(Fd3, [Data1|Data1]), + timer:sleep(1000), % Just in case the file system is slow + {ok, Fd4} = ?FILE_MODULE:open(File, [raw, read, read_ahead]), + {ok, Data1} = ?FILE_MODULE:read(Fd4, Size), + ok = ?FILE_MODULE:pwrite(Fd3, Size, Data2), + timer:sleep(1000), % Just in case the file system is slow + {ok, Data1} = ?FILE_MODULE:read(Fd4, Size), % Will read cached data + ok = ?FILE_MODULE:close(Fd3), + ok = ?FILE_MODULE:close(Fd4), %% Test if the file position works in combination with read_ahead - ?line {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, read_ahead]), - ?line ok = ?FILE_MODULE:truncate(Fd5), - ?line ok = ?FILE_MODULE:write(Fd5, [Data1,Data1|Data3]), - ?line {ok, 0} = ?FILE_MODULE:position(Fd5, bof), - ?line {ok, Data1} = ?FILE_MODULE:read(Fd5, Size), - ?line ok = ?FILE_MODULE:write(Fd5, Data2), - ?line {ok, 0} = ?FILE_MODULE:position(Fd5, bof), - ?line Data1Data2Data3 = Data1++Data2++Data3, - ?line {ok, Data1Data2Data3} = ?FILE_MODULE:read(Fd5, 3*Size+1), - ?line ok = ?FILE_MODULE:close(Fd5), + {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, read_ahead]), + ok = ?FILE_MODULE:truncate(Fd5), + ok = ?FILE_MODULE:write(Fd5, [Data1,Data1|Data3]), + {ok, 0} = ?FILE_MODULE:position(Fd5, bof), + {ok, Data1} = ?FILE_MODULE:read(Fd5, Size), + ok = ?FILE_MODULE:write(Fd5, Data2), + {ok, 0} = ?FILE_MODULE:position(Fd5, bof), + Data1Data2Data3 = Data1++Data2++Data3, + {ok, Data1Data2Data3} = ?FILE_MODULE:read(Fd5, 3*Size+1), + ok = ?FILE_MODULE:close(Fd5), %% - ?line [] = flush(), - ?line ?t:timetrap_cancel(Dog), + [] = flush(), ok. @@ -3278,137 +3105,131 @@ read_ahead(Config) when is_list(Config) -> -segment_read(suite) -> - []; -segment_read(doc) -> - ["Tests the segmenting of large reads"]; +%% Tests the segmenting of large reads. segment_read(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(60)), - %% - ?line Name = filename:join(?config(priv_dir, Config), - ?MODULE_STRING ++ "_segment_read"), - ?line SegSize = 256*1024, - ?line SegCnt = SegSize div 4, - ?line Cnt = 4 * SegCnt, - ?line ok = create_file(Name, Cnt), + Name = filename:join(proplists:get_value(priv_dir, Config), + ?MODULE_STRING ++ "_segment_read"), + SegSize = 256*1024, + SegCnt = SegSize div 4, + Cnt = 4 * SegCnt, + ok = create_file(Name, Cnt), %% %% read_file/1 %% - ?line {ok, Bin} = ?FILE_MODULE:read_file(Name), - ?line true = verify_bin(Bin, 0, Cnt), + {ok, Bin} = ?FILE_MODULE:read_file(Name), + true = verify_bin(Bin, 0, Cnt), %% %% read/2 %% %% Not segmented - ?line {ok, FD1} = ?FILE_MODULE:open(Name, [read, raw, binary]), - ?line {ok, B1a} = ?FILE_MODULE:read(FD1, SegSize), - ?line {ok, B1b} = ?FILE_MODULE:read(FD1, SegSize), - ?line {ok, B1c} = ?FILE_MODULE:read(FD1, SegSize), - ?line {ok, B1d} = ?FILE_MODULE:read(FD1, SegSize), - ?line ok = ?FILE_MODULE:close(FD1), - ?line true = verify_bin(B1a, 0*SegCnt, SegCnt), - ?line true = verify_bin(B1b, 1*SegCnt, SegCnt), - ?line true = verify_bin(B1c, 2*SegCnt, SegCnt), - ?line true = verify_bin(B1d, 3*SegCnt, SegCnt), + {ok, FD1} = ?FILE_MODULE:open(Name, [read, raw, binary]), + {ok, B1a} = ?FILE_MODULE:read(FD1, SegSize), + {ok, B1b} = ?FILE_MODULE:read(FD1, SegSize), + {ok, B1c} = ?FILE_MODULE:read(FD1, SegSize), + {ok, B1d} = ?FILE_MODULE:read(FD1, SegSize), + ok = ?FILE_MODULE:close(FD1), + true = verify_bin(B1a, 0*SegCnt, SegCnt), + true = verify_bin(B1b, 1*SegCnt, SegCnt), + true = verify_bin(B1c, 2*SegCnt, SegCnt), + true = verify_bin(B1d, 3*SegCnt, SegCnt), %% %% Segmented - ?line {ok, FD2} = ?FILE_MODULE:open(Name, [read, raw, binary]), - ?line {ok, B2a} = ?FILE_MODULE:read(FD2, 1*SegSize), - ?line {ok, B2b} = ?FILE_MODULE:read(FD2, 2*SegSize), - ?line {ok, B2c} = ?FILE_MODULE:read(FD2, 2*SegSize), - ?line ok = ?FILE_MODULE:close(FD2), - ?line true = verify_bin(B2a, 0*SegCnt, 1*SegCnt), - ?line true = verify_bin(B2b, 1*SegCnt, 2*SegCnt), - ?line true = verify_bin(B2c, 3*SegCnt, 1*SegCnt), + {ok, FD2} = ?FILE_MODULE:open(Name, [read, raw, binary]), + {ok, B2a} = ?FILE_MODULE:read(FD2, 1*SegSize), + {ok, B2b} = ?FILE_MODULE:read(FD2, 2*SegSize), + {ok, B2c} = ?FILE_MODULE:read(FD2, 2*SegSize), + ok = ?FILE_MODULE:close(FD2), + true = verify_bin(B2a, 0*SegCnt, 1*SegCnt), + true = verify_bin(B2b, 1*SegCnt, 2*SegCnt), + true = verify_bin(B2c, 3*SegCnt, 1*SegCnt), %% %% pread/3 %% - ?line {ok, FD3} = ?FILE_MODULE:open(Name, [read, raw, binary]), + {ok, FD3} = ?FILE_MODULE:open(Name, [read, raw, binary]), %% %% Not segmented - ?line {ok, B3d} = ?FILE_MODULE:pread(FD3, 3*SegSize, SegSize), - ?line {ok, B3c} = ?FILE_MODULE:pread(FD3, 2*SegSize, SegSize), - ?line {ok, B3b} = ?FILE_MODULE:pread(FD3, 1*SegSize, SegSize), - ?line {ok, B3a} = ?FILE_MODULE:pread(FD3, 0*SegSize, SegSize), - ?line true = verify_bin(B3a, 0*SegCnt, SegCnt), - ?line true = verify_bin(B3b, 1*SegCnt, SegCnt), - ?line true = verify_bin(B3c, 2*SegCnt, SegCnt), - ?line true = verify_bin(B3d, 3*SegCnt, SegCnt), + {ok, B3d} = ?FILE_MODULE:pread(FD3, 3*SegSize, SegSize), + {ok, B3c} = ?FILE_MODULE:pread(FD3, 2*SegSize, SegSize), + {ok, B3b} = ?FILE_MODULE:pread(FD3, 1*SegSize, SegSize), + {ok, B3a} = ?FILE_MODULE:pread(FD3, 0*SegSize, SegSize), + true = verify_bin(B3a, 0*SegCnt, SegCnt), + true = verify_bin(B3b, 1*SegCnt, SegCnt), + true = verify_bin(B3c, 2*SegCnt, SegCnt), + true = verify_bin(B3d, 3*SegCnt, SegCnt), %% %% Segmented - ?line {ok, B3g} = ?FILE_MODULE:pread(FD3, 3*SegSize, 2*SegSize), - ?line {ok, B3f} = ?FILE_MODULE:pread(FD3, 1*SegSize, 2*SegSize), - ?line {ok, B3e} = ?FILE_MODULE:pread(FD3, 0*SegSize, 1*SegSize), - ?line true = verify_bin(B3e, 0*SegCnt, 1*SegCnt), - ?line true = verify_bin(B3f, 1*SegCnt, 2*SegCnt), - ?line true = verify_bin(B3g, 3*SegCnt, 1*SegCnt), + {ok, B3g} = ?FILE_MODULE:pread(FD3, 3*SegSize, 2*SegSize), + {ok, B3f} = ?FILE_MODULE:pread(FD3, 1*SegSize, 2*SegSize), + {ok, B3e} = ?FILE_MODULE:pread(FD3, 0*SegSize, 1*SegSize), + true = verify_bin(B3e, 0*SegCnt, 1*SegCnt), + true = verify_bin(B3f, 1*SegCnt, 2*SegCnt), + true = verify_bin(B3g, 3*SegCnt, 1*SegCnt), %% - ?line ok = ?FILE_MODULE:close(FD3), + ok = ?FILE_MODULE:close(FD3), %% %% pread/2 %% - ?line {ok, FD5} = ?FILE_MODULE:open(Name, [read, raw, binary]), + {ok, FD5} = ?FILE_MODULE:open(Name, [read, raw, binary]), %% %% +---+---+---+---+ %% | 4 | 3 | 2 | 1 | %% +---+---+---+---+ %% < ^ > - ?line {ok, [B5d, B5c, B5b, B5a]} = + {ok, [B5d, B5c, B5b, B5a]} = ?FILE_MODULE:pread(FD5, [{3*SegSize, SegSize}, {2*SegSize, SegSize}, {1*SegSize, SegSize}, {0*SegSize, SegSize}]), - ?line true = verify_bin(B5a, 0*SegCnt, SegCnt), - ?line true = verify_bin(B5b, 1*SegCnt, SegCnt), - ?line true = verify_bin(B5c, 2*SegCnt, SegCnt), - ?line true = verify_bin(B5d, 3*SegCnt, SegCnt), + true = verify_bin(B5a, 0*SegCnt, SegCnt), + true = verify_bin(B5b, 1*SegCnt, SegCnt), + true = verify_bin(B5c, 2*SegCnt, SegCnt), + true = verify_bin(B5d, 3*SegCnt, SegCnt), %% %% +---+-------+-------+ %% | 3 | 2 | 1 | %% +---+-------+-------+ %% < ^ ^ > - ?line {ok, [B5g, B5f, B5e]} = + {ok, [B5g, B5f, B5e]} = ?FILE_MODULE:pread(FD5, [{3*SegSize, 2*SegSize}, {1*SegSize, 2*SegSize}, {0*SegSize, 1*SegSize}]), - ?line true = verify_bin(B5e, 0*SegCnt, 1*SegCnt), - ?line true = verify_bin(B5f, 1*SegCnt, 2*SegCnt), - ?line true = verify_bin(B5g, 3*SegCnt, 1*SegCnt), + true = verify_bin(B5e, 0*SegCnt, 1*SegCnt), + true = verify_bin(B5f, 1*SegCnt, 2*SegCnt), + true = verify_bin(B5g, 3*SegCnt, 1*SegCnt), %% %% %% +-------+-----------+ %% | 2 | 1 | %% +-------+-----------+ %% < ^ ^ > - ?line {ok, [B5i, B5h]} = + {ok, [B5i, B5h]} = ?FILE_MODULE:pread(FD5, [{2*SegSize, 3*SegSize}, {0*SegSize, 2*SegSize}]), - ?line true = verify_bin(B5h, 0*SegCnt, 2*SegCnt), - ?line true = verify_bin(B5i, 2*SegCnt, 2*SegCnt), + true = verify_bin(B5h, 0*SegCnt, 2*SegCnt), + true = verify_bin(B5i, 2*SegCnt, 2*SegCnt), %% %% +-------+---+---+ %% | 3 | 2 | 1 | %% +-------+---+---+ %% < ^ ^ > - ?line {ok, [B5l, B5k, B5j]} = + {ok, [B5l, B5k, B5j]} = ?FILE_MODULE:pread(FD5, [{3*SegSize, 1*SegSize}, {2*SegSize, 1*SegSize}, {0*SegSize, 2*SegSize}]), - ?line true = verify_bin(B5j, 0*SegCnt, 2*SegCnt), - ?line true = verify_bin(B5k, 2*SegCnt, 1*SegCnt), - ?line true = verify_bin(B5l, 3*SegCnt, 1*SegCnt), + true = verify_bin(B5j, 0*SegCnt, 2*SegCnt), + true = verify_bin(B5k, 2*SegCnt, 1*SegCnt), + true = verify_bin(B5l, 3*SegCnt, 1*SegCnt), %% %% Real time response time test. %% Req = lists:flatten(lists:duplicate(17, [{2*SegSize, 2*SegSize}, {0*SegSize, 2*SegSize}])), - ?line {{ok, _}, Comment} = + {{ok, _}, Comment} = response_analysis(?FILE_MODULE, pread, [FD5, Req]), - ?line ok = ?FILE_MODULE:close(FD5), + ok = ?FILE_MODULE:close(FD5), %% - ?line [] = flush(), - ?line ?t:timetrap_cancel(Dog), + [] = flush(), {comment, Comment}. @@ -3417,100 +3238,95 @@ segment_read(Config) when is_list(Config) -> -segment_write(suite) -> - []; -segment_write(doc) -> - ["Tests the segmenting of large writes"]; +%% Tests the segmenting of large writes. segment_write(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(60)), - %% - ?line Name = filename:join(?config(priv_dir, Config), - ?MODULE_STRING ++ "_segment_write"), - ?line SegSize = 256*1024, - ?line SegCnt = SegSize div 4, - ?line Cnt = 4 * SegCnt, - ?line Bin = create_bin(0, Cnt), + Name = filename:join(proplists:get_value(priv_dir, Config), + ?MODULE_STRING ++ "_segment_write"), + SegSize = 256*1024, + SegCnt = SegSize div 4, + Cnt = 4 * SegCnt, + Bin = create_bin(0, Cnt), %% %% write/2 %% %% Not segmented - ?line {ok, FD1} = ?FILE_MODULE:open(Name, [write, raw, binary]), - ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 0*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 1*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 2*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 3*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:close(FD1), - ?line true = verify_file(Name, Cnt), + {ok, FD1} = ?FILE_MODULE:open(Name, [write, raw, binary]), + ok = ?FILE_MODULE:write(FD1, subbin(Bin, 0*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:write(FD1, subbin(Bin, 1*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:write(FD1, subbin(Bin, 2*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:write(FD1, subbin(Bin, 3*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:close(FD1), + true = verify_file(Name, Cnt), %% %% Segmented - ?line {ok, FD2} = ?FILE_MODULE:open(Name, [write, raw, binary]), - ?line ok = ?FILE_MODULE:write(FD2, subbin(Bin, 0*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:write(FD2, subbin(Bin, 1*SegSize, 2*SegSize)), - ?line ok = ?FILE_MODULE:write(FD2, subbin(Bin, 3*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:close(FD2), - ?line true = verify_file(Name, Cnt), + {ok, FD2} = ?FILE_MODULE:open(Name, [write, raw, binary]), + ok = ?FILE_MODULE:write(FD2, subbin(Bin, 0*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:write(FD2, subbin(Bin, 1*SegSize, 2*SegSize)), + ok = ?FILE_MODULE:write(FD2, subbin(Bin, 3*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:close(FD2), + true = verify_file(Name, Cnt), %% %% +---+---+---+---+ %% | | | | | %% +---+---+---+---+ %% < ^ > - ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize), - subbin(Bin, 1*SegSize, 1*SegSize), - subbin(Bin, 2*SegSize, 1*SegSize), - subbin(Bin, 3*SegSize, 1*SegSize)]), - ?line true = verify_file(Name, Cnt), + ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize), + subbin(Bin, 1*SegSize, 1*SegSize), + subbin(Bin, 2*SegSize, 1*SegSize), + subbin(Bin, 3*SegSize, 1*SegSize)]), + true = verify_file(Name, Cnt), %% %% +---+-------+---+ %% | | | | %% +---+-------+---+ %% < ^ ^ > - ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize), - subbin(Bin, 1*SegSize, 2*SegSize), - subbin(Bin, 3*SegSize, 1*SegSize)]), - ?line true = verify_file(Name, Cnt), + ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize), + subbin(Bin, 1*SegSize, 2*SegSize), + subbin(Bin, 3*SegSize, 1*SegSize)]), + true = verify_file(Name, Cnt), %% %% +-------+-------+ %% | | | %% +-------+-------+ %% < ^ ^ > - ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize), - subbin(Bin, 2*SegSize, 2*SegSize)]), - ?line true = verify_file(Name, Cnt), + ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize), + subbin(Bin, 2*SegSize, 2*SegSize)]), + true = verify_file(Name, Cnt), %% %% +-------+---+---+ %% | | | | %% +-------+---+---+ %% < ^ ^ > - ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize), - subbin(Bin, 2*SegSize, 1*SegSize), - subbin(Bin, 3*SegSize, 1*SegSize)]), - ?line true = verify_file(Name, Cnt), + ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize), + subbin(Bin, 2*SegSize, 1*SegSize), + subbin(Bin, 3*SegSize, 1*SegSize)]), + true = verify_file(Name, Cnt), %% %% pwrite/3 %% %% Not segmented - ?line {ok, FD3} = ?FILE_MODULE:open(Name, [write, raw, binary]), - ?line ok = ?FILE_MODULE:pwrite(FD3, 3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:pwrite(FD3, 2*SegSize, - subbin(Bin, 2*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:pwrite(FD3, 1*SegSize, - subbin(Bin, 1*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:pwrite(FD3, 0*SegSize, - subbin(Bin, 0*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:close(FD3), - ?line true = verify_file(Name, Cnt), + {ok, FD3} = ?FILE_MODULE:open(Name, [write, raw, binary]), + ok = ?FILE_MODULE:pwrite(FD3, 3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:pwrite(FD3, 2*SegSize, + subbin(Bin, 2*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:pwrite(FD3, 1*SegSize, + subbin(Bin, 1*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:pwrite(FD3, 0*SegSize, + subbin(Bin, 0*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:close(FD3), + true = verify_file(Name, Cnt), %% %% Segmented - ?line {ok, FD4} = ?FILE_MODULE:open(Name, [write, raw, binary]), - ?line ok = ?FILE_MODULE:pwrite(FD4, 3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:pwrite(FD4, 1*SegSize, - subbin(Bin, 1*SegSize, 2*SegSize)), - ?line ok = ?FILE_MODULE:pwrite(FD4, 0*SegSize, - subbin(Bin, 0*SegSize, 1*SegSize)), - ?line ok = ?FILE_MODULE:close(FD4), - ?line true = verify_file(Name, Cnt), + {ok, FD4} = ?FILE_MODULE:open(Name, [write, raw, binary]), + ok = ?FILE_MODULE:pwrite(FD4, 3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:pwrite(FD4, 1*SegSize, + subbin(Bin, 1*SegSize, 2*SegSize)), + ok = ?FILE_MODULE:pwrite(FD4, 0*SegSize, + subbin(Bin, 0*SegSize, 1*SegSize)), + ok = ?FILE_MODULE:close(FD4), + true = verify_file(Name, Cnt), @@ -3518,125 +3334,118 @@ segment_write(Config) when is_list(Config) -> %% pwrite/2 %% %% Not segmented - ?line {ok, FD5} = ?FILE_MODULE:open(Name, [write, raw, binary]), - ?line ok = ?FILE_MODULE:pwrite(FD5, [{3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)}]), - ?line ok = ?FILE_MODULE:pwrite(FD5, [{2*SegSize, - subbin(Bin, 2*SegSize, 1*SegSize)}]), - ?line ok = ?FILE_MODULE:pwrite(FD5, [{1*SegSize, - subbin(Bin, 1*SegSize, 1*SegSize)}]), - ?line ok = ?FILE_MODULE:pwrite(FD5, [{0*SegSize, - subbin(Bin, 0*SegSize, 1*SegSize)}]), - ?line ok = ?FILE_MODULE:close(FD5), - ?line true = verify_file(Name, Cnt), + {ok, FD5} = ?FILE_MODULE:open(Name, [write, raw, binary]), + ok = ?FILE_MODULE:pwrite(FD5, [{3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)}]), + ok = ?FILE_MODULE:pwrite(FD5, [{2*SegSize, + subbin(Bin, 2*SegSize, 1*SegSize)}]), + ok = ?FILE_MODULE:pwrite(FD5, [{1*SegSize, + subbin(Bin, 1*SegSize, 1*SegSize)}]), + ok = ?FILE_MODULE:pwrite(FD5, [{0*SegSize, + subbin(Bin, 0*SegSize, 1*SegSize)}]), + ok = ?FILE_MODULE:close(FD5), + true = verify_file(Name, Cnt), %% %% Segmented - ?line {ok, FD6} = ?FILE_MODULE:open(Name, [write, raw, binary]), - ?line ok = ?FILE_MODULE:pwrite(FD6, [{3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)}]), - ?line ok = ?FILE_MODULE:pwrite(FD6, [{1*SegSize, - subbin(Bin, 1*SegSize, 2*SegSize)}]), - ?line ok = ?FILE_MODULE:pwrite(FD6, [{0*SegSize, - subbin(Bin, 0*SegSize, 1*SegSize)}]), - ?line ok = ?FILE_MODULE:close(FD6), - ?line true = verify_file(Name, Cnt), + {ok, FD6} = ?FILE_MODULE:open(Name, [write, raw, binary]), + ok = ?FILE_MODULE:pwrite(FD6, [{3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)}]), + ok = ?FILE_MODULE:pwrite(FD6, [{1*SegSize, + subbin(Bin, 1*SegSize, 2*SegSize)}]), + ok = ?FILE_MODULE:pwrite(FD6, [{0*SegSize, + subbin(Bin, 0*SegSize, 1*SegSize)}]), + ok = ?FILE_MODULE:close(FD6), + true = verify_file(Name, Cnt), %% %% +---+---+---+---+ %% | 4 | 3 | 2 | 1 | %% +---+---+---+---+ %% < ^ > - ?line ok = pwrite_file(Name, [{3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)}, - {2*SegSize, - subbin(Bin, 2*SegSize, 1*SegSize)}, - {1*SegSize, - subbin(Bin, 1*SegSize, 1*SegSize)}, - {0*SegSize, - subbin(Bin, 0*SegSize, 1*SegSize)}]), - ?line true = verify_file(Name, Cnt), + ok = pwrite_file(Name, [{3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)}, + {2*SegSize, + subbin(Bin, 2*SegSize, 1*SegSize)}, + {1*SegSize, + subbin(Bin, 1*SegSize, 1*SegSize)}, + {0*SegSize, + subbin(Bin, 0*SegSize, 1*SegSize)}]), + true = verify_file(Name, Cnt), %% %% +---+-------+---+ %% | 3 | 2 | 1 | %% +---+-------+---+ %% < ^ ^ > - ?line ok = pwrite_file(Name, [{3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)}, - {1*SegSize, - subbin(Bin, 1*SegSize, 2*SegSize)}, - {0*SegSize, - subbin(Bin, 0*SegSize, 1*SegSize)}]), - ?line true = verify_file(Name, Cnt), + ok = pwrite_file(Name, [{3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)}, + {1*SegSize, + subbin(Bin, 1*SegSize, 2*SegSize)}, + {0*SegSize, + subbin(Bin, 0*SegSize, 1*SegSize)}]), + true = verify_file(Name, Cnt), %% %% +-------+-------+ %% | 2 | 1 | %% +-------+-------+ %% < ^ ^ > - ?line ok = pwrite_file(Name, [{2*SegSize, - subbin(Bin, 2*SegSize, 2*SegSize)}, - {0*SegSize, - subbin(Bin, 0*SegSize, 2*SegSize)}]), - ?line true = verify_file(Name, Cnt), + ok = pwrite_file(Name, [{2*SegSize, + subbin(Bin, 2*SegSize, 2*SegSize)}, + {0*SegSize, + subbin(Bin, 0*SegSize, 2*SegSize)}]), + true = verify_file(Name, Cnt), %% %% +-------+---+---+ %% | 3 | 2 | 1 | %% +-------+---+---+ %% < ^ ^ > - ?line ok = pwrite_file(Name, [{3*SegSize, - subbin(Bin, 3*SegSize, 1*SegSize)}, - {2*SegSize, - subbin(Bin, 2*SegSize, 1*SegSize)}, - {0*SegSize, - subbin(Bin, 0*SegSize, 2*SegSize)}]), - ?line true = verify_file(Name, Cnt), + ok = pwrite_file(Name, [{3*SegSize, + subbin(Bin, 3*SegSize, 1*SegSize)}, + {2*SegSize, + subbin(Bin, 2*SegSize, 1*SegSize)}, + {0*SegSize, + subbin(Bin, 0*SegSize, 2*SegSize)}]), + true = verify_file(Name, Cnt), %% %% Real time response time test. %% - ?line {ok, FD7} = ?FILE_MODULE:open(Name, [write, raw, binary]), + {ok, FD7} = ?FILE_MODULE:open(Name, [write, raw, binary]), Req = lists:flatten(lists:duplicate(17, [{2*SegSize, subbin(Bin, 2*SegSize, 2*SegSize)}, - {0*SegSize, - subbin(Bin, 0*SegSize, 2*SegSize)}])), - ?line {ok, Comment} = + {0*SegSize, + subbin(Bin, 0*SegSize, 2*SegSize)}])), + {ok, Comment} = response_analysis(?FILE_MODULE, pwrite, [FD7, Req]), - ?line ok = ?FILE_MODULE:close(FD7), + ok = ?FILE_MODULE:close(FD7), %% - ?line [] = flush(), - ?line ?t:timetrap_cancel(Dog), + [] = flush(), {comment, Comment}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -ipread(suite) -> - []; -ipread(doc) -> - ["Test Dets special indirect pread"]; +%% Test Dets special indirect pread. ipread(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(30)), - %% - ?line Dir = ?config(priv_dir, Config), - ?line ok = ipread_int(Dir, [raw, binary]), - ?line ok = ipread_int(Dir, [raw]), - ?line ok = ipread_int(Dir, [binary]), - ?line ok = ipread_int(Dir, []), - ?line ok = ipread_int(Dir, [ram, binary]), - ?line ok = ipread_int(Dir, [ram]), + Dir = proplists:get_value(priv_dir, Config), + ok = ipread_int(Dir, [raw, binary]), + ok = ipread_int(Dir, [raw]), + ok = ipread_int(Dir, [binary]), + ok = ipread_int(Dir, []), + ok = ipread_int(Dir, [ram, binary]), + ok = ipread_int(Dir, [ram]), %% - ?line [] = flush(), - ?line ?t:timetrap_cancel(Dog), + [] = flush(), ok. ipread_int(Dir, ModeList) -> - ?line Name = + Name = filename:join(Dir, lists:flatten([?MODULE_STRING, "_ipread", - lists:map(fun (X) -> - ["_", atom_to_list(X)] - end, - ModeList)])), - ?line io:format("ipread_int<~p, ~p>~n", [Name, ModeList]), - ?line {Conv, Sizeof} = + lists:map(fun (X) -> + ["_", atom_to_list(X)] + end, + ModeList)])), + io:format("ipread_int<~p, ~p>~n", [Name, ModeList]), + {Conv, Sizeof} = case lists:member(binary, ModeList) of true -> {fun (Bin) when is_binary(Bin) -> Bin; @@ -3649,144 +3458,130 @@ ipread_int(Dir, ModeList) -> end, fun erlang:length/1} end, - ?line Pos = 4711, - ?line Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"), - ?line Size = Sizeof(Data), - ?line Init = Conv(" "), - ?line SizeInit = Sizeof(Init), - ?line Head = Conv(<<Size:32/big-unsigned, Pos:32/big-unsigned>>), - ?line Filler = Conv(bytes($ , Pos-SizeInit-Sizeof(Head))), - ?line Size1 = Size+1, - ?line SizePos = Size+Pos, + Pos = 4711, + Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"), + Size = Sizeof(Data), + Init = Conv(" "), + SizeInit = Sizeof(Init), + Head = Conv(<<Size:32/big-unsigned, Pos:32/big-unsigned>>), + Filler = Conv(bytes($ , Pos-SizeInit-Sizeof(Head))), + Size1 = Size+1, + SizePos = Size+Pos, %% - ?line {ok, FD} = ?FILE_MODULE:open(Name, [write, read | ModeList]), - ?line ok = ?FILE_MODULE:truncate(FD), - ?line ok = ?FILE_MODULE:write(FD, Init), - ?line ok = ?FILE_MODULE:write(FD, Head), - ?line ok = ?FILE_MODULE:write(FD, Filler), - ?line ok = ?FILE_MODULE:write(FD, Data), + {ok, FD} = ?FILE_MODULE:open(Name, [write, read | ModeList]), + ok = ?FILE_MODULE:truncate(FD), + ok = ?FILE_MODULE:write(FD, Init), + ok = ?FILE_MODULE:write(FD, Head), + ok = ?FILE_MODULE:write(FD, Filler), + ok = ?FILE_MODULE:write(FD, Data), %% Correct read - ?line {ok, {Size, Pos, Data}} = + {ok, {Size, Pos, Data}} = ?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, infinity), %% Invalid header - size > max - ?line eof = + eof = ?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size-1), %% Data block protudes over eof - ?line ok = + ok = ?FILE_MODULE:pwrite(FD, SizeInit, <<Size1:32/big-unsigned, - Pos:32/big-unsigned>>), - ?line {ok, {Size1, Pos, Data}} = + Pos:32/big-unsigned>>), + {ok, {Size1, Pos, Data}} = ?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size1), %% Data block outside file - ?line ok = + ok = ?FILE_MODULE:pwrite(FD, SizeInit, <<Size:32/big-unsigned, - SizePos:32/big-unsigned>>), - ?line {ok, {Size, SizePos, eof}} = + SizePos:32/big-unsigned>>), + {ok, {Size, SizePos, eof}} = ?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size), %% Zero size - ?line ok = + ok = ?FILE_MODULE:pwrite(FD, SizeInit, <<0:32/big-unsigned, - Pos:32/big-unsigned>>), - ?line {ok, {0, Pos, eof}} = + Pos:32/big-unsigned>>), + {ok, {0, Pos, eof}} = ?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size), %% Invalid header - protudes over eof - ?line eof = + eof = ?FILE_MODULE:ipread_s32bu_p32bu(FD, Pos+Size-(Sizeof(Head)-1), infinity), %% Header not even in file - ?line eof = + eof = ?FILE_MODULE:ipread_s32bu_p32bu(FD, Pos+Size, infinity), %% - ?line ok = ?FILE_MODULE:close(FD), + ok = ?FILE_MODULE:close(FD), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -interleaved_read_write(suite) -> - []; -interleaved_read_write(doc) -> - ["Tests interleaved read and writes"]; +%% Tests interleaved read and writes. interleaved_read_write(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(30)), - %% - ?line Dir = ?config(priv_dir, Config), - ?line File = + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, ?MODULE_STRING++"interleaved_read_write.txt"), - ?line {ok,F1} = ?FILE_MODULE:open(File, [write]), - ?line ok = ?FILE_MODULE:write(F1, "data---r1."), % 10 chars each - ?line ok = ?FILE_MODULE:write(F1, "data---r2."), - ?line ok = ?FILE_MODULE:write(F1, "data---r3."), - ?line ok = ?FILE_MODULE:close(F1), - ?line {ok,F2} = ?FILE_MODULE:open(File, [read, write]), - ?line {ok, "data---r1."} = ?FILE_MODULE:read(F2, 10), - ?line ok = ?FILE_MODULE:write(F2, "data---w2."), - ?line ok = ?FILE_MODULE:close(F2), - ?line {ok,F3} = ?FILE_MODULE:open(File, [read]), - ?line {ok, "data---r1."} = ?FILE_MODULE:read(F3, 10), - ?line {ok, "data---w2."} = ?FILE_MODULE:read(F3, 10), - ?line {ok, "data---r3."} = ?FILE_MODULE:read(F3, 10), - ?line eof = ?FILE_MODULE:read(F3, 1), - ?line ok = ?FILE_MODULE:close(F2), + {ok,F1} = ?FILE_MODULE:open(File, [write]), + ok = ?FILE_MODULE:write(F1, "data---r1."), % 10 chars each + ok = ?FILE_MODULE:write(F1, "data---r2."), + ok = ?FILE_MODULE:write(F1, "data---r3."), + ok = ?FILE_MODULE:close(F1), + {ok,F2} = ?FILE_MODULE:open(File, [read, write]), + {ok, "data---r1."} = ?FILE_MODULE:read(F2, 10), + ok = ?FILE_MODULE:write(F2, "data---w2."), + ok = ?FILE_MODULE:close(F2), + {ok,F3} = ?FILE_MODULE:open(File, [read]), + {ok, "data---r1."} = ?FILE_MODULE:read(F3, 10), + {ok, "data---w2."} = ?FILE_MODULE:read(F3, 10), + {ok, "data---r3."} = ?FILE_MODULE:read(F3, 10), + eof = ?FILE_MODULE:read(F3, 1), + ok = ?FILE_MODULE:close(F2), %% - ?line [] = flush(), - ?line ?t:timetrap_cancel(Dog), + [] = flush(), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -otp_5814(suite) -> - []; -otp_5814(doc) -> - ["OTP-5814. eval/consult/script return correct line numbers"]; +%% OTP-5814. eval/consult/script return correct line numbers. otp_5814(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(10)), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), File = filename:join(PrivDir, "otp_5814"), Path = [PrivDir], - ?line ok = file:write_file(File, <<"{a,b,c}. + ok = file:write_file(File, <<"{a,b,c}. a. - b. - c. - {d,e, - [}.">>), - ?line {error, {6,erl_parse,_}} = file:eval(File), - ?line {error, {6,erl_parse,_}} = file:consult(File), - ?line {error, {6,erl_parse,_}} = file:path_consult(Path, File), - ?line {error, {6,erl_parse,_}} = file:path_eval(Path, File), - ?line {error, {6,erl_parse,_}} = file:script(File), - ?line {error, {6,erl_parse,_}} = file:path_script(Path, File), - - ?line ok = file:write_file(File, <<>>), - ?line {error, {1,file,undefined_script}} = file:path_script(Path, File), +b. +c. +{d,e, + [}.">>), + {error, {6,erl_parse,_}} = file:eval(File), + {error, {6,erl_parse,_}} = file:consult(File), + {error, {6,erl_parse,_}} = file:path_consult(Path, File), + {error, {6,erl_parse,_}} = file:path_eval(Path, File), + {error, {6,erl_parse,_}} = file:script(File), + {error, {6,erl_parse,_}} = file:path_script(Path, File), + + ok = file:write_file(File, <<>>), + {error, {1,file,undefined_script}} = file:path_script(Path, File), %% The error is not propagated... - ?line ok = file:write_file(File, <<"a. + ok = file:write_file(File, <<"a. b. - 1/0.">>), - ?line {error, {3, file, {error, badarith, _}}} = file:eval(File), - - ?line ok = file:write_file(File, <<"erlang:raise(throw, apa, []).">>), - ?line {error, {1, file, {throw, apa, _}}} = file:eval(File), +1/0.">>), + {error, {3, file, {error, badarith, _}}} = file:eval(File), - file:delete(File), - ?line ?t:timetrap_cancel(Dog), - ok. +ok = file:write_file(File, <<"erlang:raise(throw, apa, []).">>), +{error, {1, file, {throw, apa, _}}} = file:eval(File), + +file:delete(File), +ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -otp_10852(suite) -> - []; -otp_10852(doc) -> - ["OTP-10852. +fnu and latin1 filenames"]; +%% OTP-10852. +fnu and latin1 filenames. otp_10852(Config) when is_list(Config) -> Node = start_node(erl_pp_helper, "+fnu"), - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), B = filename:join(Dir, <<"\xE4">>), ok = rpc_call(Node, get_cwd, [B]), {error, no_translation} = rpc_call(Node, set_cwd, [B]), @@ -3801,10 +3596,10 @@ otp_10852(Config) when is_list(Config) -> ok = rpc_call(Node, read_file, [B]), ok = rpc_call(Node, make_link, [B,B]), case rpc_call(Node, make_symlink, [B,B]) of - ok -> ok; - {error, E} when (E =:= enotsup) or (E =:= eperm) -> - {win32,_} = os:type() - end, + ok -> ok; + {error, E} when (E =:= enotsup) or (E =:= eperm) -> + {win32,_} = os:type() + end, ok = rpc_call(Node, delete, [B]), ok = rpc_call(Node, make_dir, [B]), ok = rpc_call(Node, del_dir, [B]), @@ -3827,58 +3622,58 @@ rpc_call(N, F, As) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -large_file(suite) -> - []; -large_file(doc) -> - ["Tests positioning in large files (> 4G)"]; +large_file() -> + [{timetrap,{minutes,20}}]. + +%% Tests positioning in large files (> 4G). large_file(Config) when is_list(Config) -> run_large_file_test(Config, fun(Name) -> do_large_file(Name) end, "_large_file"). do_large_file(Name) -> - ?line Watchdog = ?t:timetrap(?t:minutes(20)), - - ?line S = "1234567890", + S = "1234567890", L = length(S), R = lists:reverse(S), P = 1 bsl 32, Ss = lists:sort(S), Rs = lists:reverse(Ss), - ?line {ok,F} = ?FILE_MODULE:open(Name, [raw,read,write]), - ?line ok = ?FILE_MODULE:write(F, S), - ?line {ok,P} = ?FILE_MODULE:position(F, P), - ?line ok = ?FILE_MODULE:write(F, R), - ?line {ok,0} = ?FILE_MODULE:position(F, bof), - ?line {ok,S} = ?FILE_MODULE:read(F, L), - ?line {ok,P} = ?FILE_MODULE:position(F, {eof,-L}), - ?line {ok,R} = ?FILE_MODULE:read(F, L+1), - ?line {ok,S} = ?FILE_MODULE:pread(F, 0, L), - ?line {ok,R} = ?FILE_MODULE:pread(F, P, L+1), - ?line ok = ?FILE_MODULE:pwrite(F, 0, Ss), - ?line ok = ?FILE_MODULE:pwrite(F, P, Rs), - ?line {ok,0} = ?FILE_MODULE:position(F, bof), - ?line {ok,Ss} = ?FILE_MODULE:read(F, L), - ?line {ok,P} = ?FILE_MODULE:position(F, {eof,-L}), - ?line {ok,Rs} = ?FILE_MODULE:read(F, L+1), - ?line ok = ?FILE_MODULE:close(F), + {ok,F} = ?FILE_MODULE:open(Name, [raw,read,write]), + ok = ?FILE_MODULE:write(F, S), + {ok,P} = ?FILE_MODULE:position(F, P), + ok = ?FILE_MODULE:write(F, R), + {ok,0} = ?FILE_MODULE:position(F, bof), + {ok,S} = ?FILE_MODULE:read(F, L), + {ok,P} = ?FILE_MODULE:position(F, {eof,-L}), + {ok,R} = ?FILE_MODULE:read(F, L+1), + {ok,S} = ?FILE_MODULE:pread(F, 0, L), + {ok,R} = ?FILE_MODULE:pread(F, P, L+1), + ok = ?FILE_MODULE:pwrite(F, 0, Ss), + ok = ?FILE_MODULE:pwrite(F, P, Rs), + {ok,0} = ?FILE_MODULE:position(F, bof), + {ok,Ss} = ?FILE_MODULE:read(F, L), + {ok,P} = ?FILE_MODULE:position(F, {eof,-L}), + {ok,Rs} = ?FILE_MODULE:read(F, L+1), + ok = ?FILE_MODULE:close(F), %% Reopen the file with 'append'; used to fail on Windows causing %% writes to go to the beginning of the file for files > 4GB. - ?line PL = P + L, - ?line PLL = PL + L, - ?line {ok,F1} = ?FILE_MODULE:open(Name, [raw,read,write,append]), - ?line ok = ?FILE_MODULE:write(F1, R), - ?line {ok,PLL} = ?FILE_MODULE:position(F1, {cur,0}), - ?line {ok,Rs} = ?FILE_MODULE:pread(F1, P, L), - ?line {ok,PL} = ?FILE_MODULE:position(F1, {eof,-L}), - ?line {ok,R} = ?FILE_MODULE:read(F1, L+1), - ?line ok = ?FILE_MODULE:close(F1), - %% - ?line ?t:timetrap_cancel(Watchdog), + PL = P + L, + PLL = PL + L, + {ok,F1} = ?FILE_MODULE:open(Name, [raw,read,write,append]), + ok = ?FILE_MODULE:write(F1, R), + {ok,PLL} = ?FILE_MODULE:position(F1, {cur,0}), + {ok,Rs} = ?FILE_MODULE:pread(F1, P, L), + {ok,PL} = ?FILE_MODULE:position(F1, {eof,-L}), + {ok,R} = ?FILE_MODULE:read(F1, L+1), + ok = ?FILE_MODULE:close(F1), + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +large_write() -> + [{timetrap,{minutes,20}}]. + large_write(Config) when is_list(Config) -> run_large_file_test(Config, fun(Name) -> do_large_write(Name) end, @@ -3908,8 +3703,8 @@ do_large_write(Name) -> response_analysis(Module, Function, Arguments) -> Parent = self(), - ?line erlang:yield(), % Schedule out before test - ?line Child = + erlang:yield(), % Schedule out before test + Child = spawn_link( fun () -> receive {Parent, start, Ts} -> ok end, @@ -3929,21 +3724,21 @@ response_analysis(Module, Function, Arguments) -> Parent ! {self(), stopped, response_stat(Stat, micro_ts())} end), Child ! {Parent, start, micro_ts()}, - ?line Result = apply(Module, Function, Arguments), - ?line Child ! {Parent, stop}, - ?line {N, Sum, _, M, Max} = receive {Child, stopped, X} -> X end, - ?line Mean_ms = (0.001*Sum) / (N-1), - ?line Max_ms = 0.001 * Max, - ?line Comment = + Result = apply(Module, Function, Arguments), + Child ! {Parent, stop}, + {N, Sum, _, M, Max} = receive {Child, stopped, X} -> X end, + Mean_ms = (0.001*Sum) / (N-1), + Max_ms = 0.001 * Max, + Comment = lists:flatten( io_lib:format( "Scheduling interval: Mean = ~.3f ms, " ++"Max = ~.3f ms for no ~p of ~p.~n", [Mean_ms, Max_ms, M, (N-1)])), - ?line {Result, Comment}. - + {Result, Comment}. + micro_ts() -> - erlang:monotonic_time(micro_seconds). + erlang:monotonic_time(microsecond). response_stat(init, Ts) -> {0, 0, Ts, 0, 0}; @@ -3965,10 +3760,10 @@ response_stat({N, Sum, Ts0, M, Max}, Ts) -> %% create_file/2 below is some 44 times faster. create_file_slow(Name, N) when is_integer(N), N >= 0 -> - ?line {ok, FD} = + {ok, FD} = ?FILE_MODULE:open(Name, [raw, write, delayed_write, binary]), - ?line ok = create_file_slow(FD, 0, N), - ?line ok = ?FILE_MODULE:close(FD), + ok = create_file_slow(FD, 0, N), + ok = ?FILE_MODULE:close(FD), ok. create_file_slow(_FD, M, M) -> @@ -3983,10 +3778,10 @@ create_file_slow(FD, M, N) -> %% from 0 to N-1. create_file(Name, N) when is_integer(N), N >= 0 -> - ?line {ok, FD} = + {ok, FD} = ?FILE_MODULE:open(Name, [raw, write, delayed_write, binary]), - ?line ok = create_file(FD, 0, N), - ?line ok = ?FILE_MODULE:close(FD), + ok = create_file(FD, 0, N), + ok = ?FILE_MODULE:close(FD), ok. create_file(_FD, M, M) -> @@ -4003,10 +3798,10 @@ create_file(FD, M, N0, R) when M + 8 =< N0 -> N1 = N0-1, N2 = N0-2, N3 = N0-3, N4 = N0-4, N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8, create_file(FD, M, N8, - [<<N8:32/unsigned, N7:32/unsigned, - N6:32/unsigned, N5:32/unsigned, - N4:32/unsigned, N3:32/unsigned, - N2:32/unsigned, N1:32/unsigned>> | R]); + [<<N8:32/unsigned, N7:32/unsigned, + N6:32/unsigned, N5:32/unsigned, + N4:32/unsigned, N3:32/unsigned, + N2:32/unsigned, N1:32/unsigned>> | R]); create_file(FD, M, N0, R) -> N1 = N0-1, create_file(FD, M, N1, [<<N1:32/unsigned>> | R]). @@ -4023,14 +3818,14 @@ create_bin(M, N0, R) when M+8 =< N0 -> N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8, create_bin(M, N8, [<<N8:32/unsigned, N7:32/unsigned, - N6:32/unsigned, N5:32/unsigned, - N4:32/unsigned, N3:32/unsigned, - N2:32/unsigned, N1:32/unsigned>> | R]); + N6:32/unsigned, N5:32/unsigned, + N4:32/unsigned, N3:32/unsigned, + N2:32/unsigned, N1:32/unsigned>> | R]); create_bin(M, N0, R) -> N1 = N0-1, create_bin(M, N1, [<<N1:32/unsigned>> | R]). - - + + verify_bin(<<>>, _, 0) -> @@ -4042,8 +3837,8 @@ verify_bin(Bin, N, Cnt) -> N4 = N + 4, N5 = N + 5, N6 = N + 6, N7 = N + 7, case Bin of <<N0:32/unsigned, N1:32/unsigned, N2:32/unsigned, N3:32/unsigned, - N4:32/unsigned, N5:32/unsigned, N6:32/unsigned, N7:32/unsigned, - B/binary>> -> + N4:32/unsigned, N5:32/unsigned, N6:32/unsigned, N7:32/unsigned, + B/binary>> -> verify_bin(B, N+8, Cnt-8); <<N:32/unsigned, B/binary>> -> verify_bin(B, N+1, Cnt-1); @@ -4124,13 +3919,13 @@ pwrite_file(Name, Data) -> read_line_testdata(PrivDir) -> All0 = [{fun read_line_create0/1,"Testdata1.txt",5,10}, - {fun read_line_create1/1,"Testdata2.txt",401,802}, - {fun read_line_create2/1,"Testdata3.txt",1,2}, - {fun read_line_create3/1,"Testdata4.txt",601,fail}, - {fun read_line_create4/1,"Testdata5.txt",601,1002}, - {fun read_line_create5/1,"Testdata6.txt",601,1202}, - {fun read_line_create6/1,"Testdata7.txt",601,1202}, - {fun read_line_create7/1,"Testdata8.txt",4001,8002}], + {fun read_line_create1/1,"Testdata2.txt",401,802}, + {fun read_line_create2/1,"Testdata3.txt",1,2}, + {fun read_line_create3/1,"Testdata4.txt",601,fail}, + {fun read_line_create4/1,"Testdata5.txt",601,1002}, + {fun read_line_create5/1,"Testdata6.txt",601,1202}, + {fun read_line_create6/1,"Testdata7.txt",601,1202}, + {fun read_line_create7/1,"Testdata8.txt",4001,8002}], [ {A,filename:join([PrivDir,B]),C,D} || {A,B,C,D} <- All0 ]. read_line_create_files(TestData) -> @@ -4139,105 +3934,93 @@ read_line_create_files(TestData) -> read_line_remove_files(TestData) -> [ file:delete(File) || {_Function,File,_,_} <- TestData ]. -read_line_1(suite) -> - []; -read_line_1(doc) -> - ["read_line with prim_file"]; +%% read_line with prim_file. read_line_1(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line All = read_line_testdata(PrivDir), - ?line read_line_create_files(All), - ?line [ begin - io:format("read_line_all: ~s~n",[File]), - {X,_} = read_line_all(File), - true - end || {_,File,X,_} <- All ], - ?line [ begin - io:format("read_line_all_alternating: ~s~n",[File]), - {Y,_} = read_line_all_alternating(File), - true - end || {_,File,_,Y} <- All , Y =/= fail], - ?line [ begin - io:format("read_line_all_alternating (failing as should): ~s~n",[File]), - {'EXIT',_} = (catch read_line_all_alternating(File)), - true - end || {_,File,_,Y} <- All , Y =:= fail], - ?line read_line_remove_files(All), + PrivDir = proplists:get_value(priv_dir, Config), + All = read_line_testdata(PrivDir), + read_line_create_files(All), + [ begin + io:format("read_line_all: ~s~n",[File]), + {X,_} = read_line_all(File), + true + end || {_,File,X,_} <- All ], + [ begin + io:format("read_line_all_alternating: ~s~n",[File]), + {Y,_} = read_line_all_alternating(File), + true + end || {_,File,_,Y} <- All , Y =/= fail], + [ begin + io:format("read_line_all_alternating (failing as should): ~s~n",[File]), + {'EXIT',_} = (catch read_line_all_alternating(File)), + true + end || {_,File,_,Y} <- All , Y =:= fail], + read_line_remove_files(All), ok. -read_line_2(suite) -> - []; -read_line_2(doc) -> - ["read_line with file"]; +%% read_line with file. read_line_2(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line All = read_line_testdata(PrivDir), - ?line read_line_create_files(All), - ?line [ begin - io:format("read_line_all: ~s~n",[File]), - {X,_} = read_line_all2(File), - true - end || {_,File,X,_} <- All ], - ?line [ begin - io:format("read_line_all_alternating: ~s~n",[File]), - {Y,_} = read_line_all_alternating2(File), - true - end || {_,File,_,Y} <- All , Y =/= fail], - ?line [ begin - io:format("read_line_all_alternating (failing as should): ~s~n",[File]), - {'EXIT',_} = (catch read_line_all_alternating2(File)), - true - end || {_,File,_,Y} <- All , Y =:= fail], - ?line read_line_remove_files(All), + PrivDir = proplists:get_value(priv_dir, Config), + All = read_line_testdata(PrivDir), + read_line_create_files(All), + [ begin + io:format("read_line_all: ~s~n",[File]), + {X,_} = read_line_all2(File), + true + end || {_,File,X,_} <- All ], + [ begin + io:format("read_line_all_alternating: ~s~n",[File]), + {Y,_} = read_line_all_alternating2(File), + true + end || {_,File,_,Y} <- All , Y =/= fail], + [ begin + io:format("read_line_all_alternating (failing as should): ~s~n",[File]), + {'EXIT',_} = (catch read_line_all_alternating2(File)), + true + end || {_,File,_,Y} <- All , Y =:= fail], + read_line_remove_files(All), ok. -read_line_3(suite) -> - []; -read_line_3(doc) -> - ["read_line with raw file"]; +%% read_line with raw file. read_line_3(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line All = read_line_testdata(PrivDir), - ?line read_line_create_files(All), - ?line [ begin - io:format("read_line_all: ~s~n",[File]), - {X,_} = read_line_all3(File), - true - end || {_,File,X,_} <- All ], - ?line [ begin - io:format("read_line_all_alternating: ~s~n",[File]), - {Y,_} = read_line_all_alternating3(File), - true - end || {_,File,_,Y} <- All , Y =/= fail], - ?line [ begin - io:format("read_line_all_alternating (failing as should): ~s~n",[File]), - {'EXIT',_} = (catch read_line_all_alternating3(File)), - true - end || {_,File,_,Y} <- All , Y =:= fail], - ?line read_line_remove_files(All), + PrivDir = proplists:get_value(priv_dir, Config), + All = read_line_testdata(PrivDir), + read_line_create_files(All), + [ begin + io:format("read_line_all: ~s~n",[File]), + {X,_} = read_line_all3(File), + true + end || {_,File,X,_} <- All ], + [ begin + io:format("read_line_all_alternating: ~s~n",[File]), + {Y,_} = read_line_all_alternating3(File), + true + end || {_,File,_,Y} <- All , Y =/= fail], + [ begin + io:format("read_line_all_alternating (failing as should): ~s~n",[File]), + {'EXIT',_} = (catch read_line_all_alternating3(File)), + true + end || {_,File,_,Y} <- All , Y =:= fail], + read_line_remove_files(All), ok. -read_line_4(suite) -> - []; -read_line_4(doc) -> - ["read_line with raw buffered file"]; +%% read_line with raw buffered file. read_line_4(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line All = read_line_testdata(PrivDir), - ?line read_line_create_files(All), - ?line [ begin - io:format("read_line_all: ~s~n",[File]), - {X,_} = read_line_all4(File), - true - end || {_,File,X,_} <- All ], - ?line [ begin - io:format("read_line_all_alternating: ~s~n",[File]), - {Y,_} = read_line_all_alternating4(File), - true - end || {_,File,_,Y} <- All , Y =/= fail], - ?line [ begin - io:format("read_line_all_alternating (failing as should): ~s~n",[File]), - {'EXIT',_} = (catch read_line_all_alternating4(File)), - true - end || {_,File,_,Y} <- All , Y =:= fail], - ?line read_line_remove_files(All), + PrivDir = proplists:get_value(priv_dir, Config), + All = read_line_testdata(PrivDir), + read_line_create_files(All), + [ begin + io:format("read_line_all: ~s~n",[File]), + {X,_} = read_line_all4(File), + true + end || {_,File,X,_} <- All ], + [ begin + io:format("read_line_all_alternating: ~s~n",[File]), + {Y,_} = read_line_all_alternating4(File), + true + end || {_,File,_,Y} <- All , Y =/= fail], + [ begin + io:format("read_line_all_alternating (failing as should): ~s~n",[File]), + {'EXIT',_} = (catch read_line_all_alternating4(File)), + true + end || {_,File,_,Y} <- All , Y =:= fail], + read_line_remove_files(All), ok. rl_lines() -> @@ -4492,7 +4275,7 @@ run_large_file_test(Config, Run, Name) -> {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; {{unix,_},_} -> - N = disc_free(?config(priv_dir, Config)), + N = disc_free(proplists:get_value(priv_dir, Config)), io:format("Free disk: ~w KByte~n", [N]), if N < 5 * (1 bsl 20) -> %% Less than 5 GByte free @@ -4506,9 +4289,9 @@ run_large_file_test(Config, Run, Name) -> do_run_large_file_test(Config, Run, Name0) -> - Name = filename:join(?config(priv_dir, Config), + Name = filename:join(proplists:get_value(priv_dir, Config), ?MODULE_STRING ++ Name0), - + %% Set up a process that will delete this file. Tester = self(), Deleter = @@ -4521,7 +4304,7 @@ do_run_large_file_test(Config, Run, Name0) -> end, ?FILE_MODULE:delete(Name) end), - + %% Run the test case. Res = Run(Name), diff --git a/lib/kernel/test/file_SUITE_data/realmen.html b/lib/kernel/test/file_SUITE_data/realmen.html index c810a5d088..92e13f23b8 100644 --- a/lib/kernel/test/file_SUITE_data/realmen.html +++ b/lib/kernel/test/file_SUITE_data/realmen.html @@ -237,7 +237,7 @@ destroy most of the interesting uses for EQUIVALENCE, and make it impossible to modify the operating system code with negative subscripts. Worst of all, bounds checking is inefficient. -<LI> Source code maintainance systems. A Real Programmer keeps his +<LI> Source code maintenance systems. A Real Programmer keeps his code locked up in a card file, because it implies that its owner cannot leave his important programs unguarded [5]. @@ -396,7 +396,7 @@ double stuff Oreos for special occasions. <LI> Underneath the Oreos is a flow-charting template, left there by the previous occupant of the office. (Real Programmers write programs, -not documentation. Leave that to the maintainence people.) +not documentation. Leave that to the maintenance people.) </UL> <P> diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 32006d893e..899102c908 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -19,7 +19,7 @@ %% %CopyrightEnd% %% --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/file.hrl"). %% @@ -79,14 +79,14 @@ init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(60)), - [{watchdog,Dog}|Config]. + Config. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [normal, icky, very_icky, normalize, home_dir]. @@ -101,19 +101,16 @@ end_per_suite(_Config) -> ok. init_per_group(_GroupName, Config) -> - Config. + Config. end_per_group(_GroupName, Config) -> - Config. + Config. -home_dir(suite) -> - []; -home_dir(doc) -> - ["Check that Erlang can be started with unicode named home directory"]; +%% Check that Erlang can be started with unicode named home directory. home_dir(Config) when is_list(Config) -> try Name=[960,945,964,961,953,954], - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), UniMode = file:native_name_encoding() =/= latin1, if not UniMode -> @@ -142,7 +139,12 @@ home_dir(Config) when is_list(Config) -> test_server:stop_node(Node), ok after - os:putenv(SaveOldName,SaveOldValue), + case SaveOldValue of + false -> + os:unsetenv(SaveOldName); + _ -> + os:putenv(SaveOldName,SaveOldValue) + end, rm_rf(prim_file,NewHome) end catch @@ -154,49 +156,41 @@ home_dir(Config) when is_list(Config) -> {skipped,"Runs only on Unix/Windows"} end. -normalize(suite) -> - []; -normalize(doc) -> - ["Check that filename normalization works"]; +%% Check that filename normalization works. normalize(Config) when is_list(Config) -> - random:seed({1290,431421,830412}), + rand:seed(exsplus, {1290,431421,830412}), try - ?line UniMode = file:native_name_encoding() =/= latin1, + UniMode = file:native_name_encoding() =/= latin1, if not UniMode -> throw(need_unicode_mode); true -> ok end, - ?line Pairs = [rand_comp_decomp(200) || _ <- lists:seq(1,1000)], + Pairs = [rand_comp_decomp(200) || _ <- lists:seq(1,1000)], case os:type() of {unix,darwin} -> - ?line [ true = (A =:= prim_file:internal_native2name(B)) || + [ true = (A =:= prim_file:internal_native2name(B)) || {A,B} <- Pairs ]; _ -> ok end, - ?line [ true = (A =:= prim_file:internal_normalize_utf8(B)) || - {A,B} <- Pairs ] - + [ true = (A =:= prim_file:internal_normalize_utf8(B)) || + {A,B} <- Pairs ] + catch throw:need_unicode_mode -> io:format("Sorry, can only run in unicode mode.~n"), {skipped,"VM needs to be started in Unicode filename mode"} end. - -normal(suite) -> - []; -normal(doc) -> - "Check file operations on normal file names regardless of unicode mode"; + +%% Check file operations on normal file names regardless of unicode mode. normal(Config) when is_list(Config) -> {ok,Dir} = file:get_cwd(), try - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), file:set_cwd(Priv), - put(file_module,prim_file), ok = check_normal(prim_file), - put(file_module,file), ok = check_normal(file), %% If all is good, delete dir again (avoid hanging dir on windows) rm_rf(file,"normal_dir"), @@ -204,12 +198,9 @@ normal(Config) when is_list(Config) -> after file:set_cwd(Dir) end. - -icky(suite) -> - []; -icky(doc) -> - "Check file operations on normal file names regardless of unicode mode"; + +%% Check file operations on normal file names regardless of unicode mode. icky(Config) when is_list(Config) -> case hopeless_darwin() of true -> @@ -217,11 +208,9 @@ icky(Config) when is_list(Config) -> false -> {ok,Dir} = file:get_cwd(), try - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), file:set_cwd(Priv), - put(file_module,prim_file), ok = check_icky(prim_file), - put(file_module,file), ok = check_icky(file), %% If all is good, delete dir again (avoid hanging dir on windows) rm_rf(file,"icky_dir"), @@ -230,10 +219,7 @@ icky(Config) when is_list(Config) -> file:set_cwd(Dir) end end. -very_icky(suite) -> - []; -very_icky(doc) -> - "Check file operations on normal file names regardless of unicode mode"; +%% Check file operations on normal file names regardless of unicode mode. very_icky(Config) when is_list(Config) -> case hopeless_darwin() of true -> @@ -241,14 +227,12 @@ very_icky(Config) when is_list(Config) -> false -> {ok,Dir} = file:get_cwd(), try - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), file:set_cwd(Priv), - put(file_module,prim_file), case check_very_icky(prim_file) of need_unicode_mode -> {skipped,"VM needs to be started in Unicode filename mode"}; ok -> - put(file_module,file), ok = check_very_icky(file), %% If all is good, delete dir again %% (avoid hanging dir on windows) @@ -259,78 +243,79 @@ very_icky(Config) when is_list(Config) -> file:set_cwd(Dir) end end. - + check_normal(Mod) -> {ok,Dir} = Mod:get_cwd(), try - ?line make_normal_dir(Mod), - ?line {ok, L0} = Mod:list_dir("."), - ?line L1 = lists:sort(L0), - %erlang:display(L1), - ?line L1 = lists:sort(list(normal_dir())), - ?line {ok,D2} = Mod:get_cwd(), - ?line true = is_list(D2), - ?line case Mod:altname("fil1") of + NormalDir = make_normal_dir(Mod, "normal_dir"), + io:format("Normaldir = ~p\n", [NormalDir]), + L1 = lists:sort(list(NormalDir)), + {ok, L0} = Mod:list_dir("."), + io:format("L0 = ~p\n", [L0]), + L1 = lists:sort(L0), + {ok,D2} = Mod:get_cwd(), + true = is_list(D2), + case Mod:altname("fil1") of {error,enotsup} -> ok; {ok,LLL} when is_list(LLL) -> ok end, - ?line [ true = is_list(El) || El <- L1], - ?line Syms = [ {S,Targ,list_to_binary(get_data(Targ,normal_dir()))} - || {T,S,Targ} <- normal_dir(), T =:= symlink ], - ?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ], - ?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ], - ?line chk_cre_dir(Mod,[{directory,"temp_dir",normal_dir()}]), - ?line {ok,BeginAt} = Mod:get_cwd(), - ?line true = is_list(BeginAt), - ?line {error,enoent} = Mod:set_cwd("tmp_dir"), - ?line ok = Mod:set_cwd("temp_dir"), - ?line {ok, NowAt} = Mod:get_cwd(), - ?line true = BeginAt =/= NowAt, - ?line ok = Mod:set_cwd(".."), - ?line {ok,BeginAt} = Mod:get_cwd(), - ?line rm_r(Mod,"temp_dir"), - ?line true = is_list(Dir), - ?line [ true = is_list(FN) || FN <- L0 ], - case has_links() of - true -> - ?line ok = Mod:make_link("fil1","nisse"), - ?line {ok, <<"fil1">>} = Mod:read_file("nisse"), - ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisse"), - ?line ok = Mod:delete("nisse"), - ?line {ok, <<"fil1">>} = Mod:read_file("fil1"), - ?line {error,enoent} = Mod:read_file("nisse"), - ?line {error,enoent} = Mod:read_link_info("nisse"); - false -> + [ true = is_list(El) || El <- L1], + Syms = [ {S,Targ,list_to_binary(get_data(Targ, NormalDir))} + || {T,S,Targ} <- NormalDir, T =:= symlink ], + [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ], + [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ], + + {ok,BeginAt} = Mod:get_cwd(), + true = is_list(BeginAt), + TempDir = "temp_dir", + make_normal_dir(Mod, TempDir), + {error,enoent} = Mod:set_cwd("tmp_dir"), + {ok, NowAt} = Mod:get_cwd(), + true = BeginAt =/= NowAt, + ok = Mod:set_cwd(".."), + {ok,BeginAt} = Mod:get_cwd(), + rm_r(Mod, TempDir), + true = is_list(Dir), + [ true = is_list(FN) || FN <- L0 ], + case Mod:make_link("fil1","nisse") of + ok -> + {ok, <<"fil1">>} = Mod:read_file("nisse"), + {ok, #file_info{type = regular}} = Mod:read_link_info("nisse"), + ok = Mod:delete("nisse"), + {ok, <<"fil1">>} = Mod:read_file("fil1"), + {error,enoent} = Mod:read_file("nisse"), + {error,enoent} = Mod:read_link_info("nisse"); + {error,enotsup} -> ok end, - ?line [ begin - ?line {ok, FD} = Mod:open(Name,[read]), - ?line {ok, Content} = Mod:read(FD,1024), - ?line ok = file:close(FD) - end || {regular,Name,Content} <- normal_dir() ], - ?line [ begin - ?line {ok, FD} = Mod:open(Name,[read,binary]), - ?line BC = list_to_binary(Content), - ?line {ok, BC} = Mod:read(FD,1024), - ?line ok = file:close(FD) - end || {regular,Name,Content} <- normal_dir() ], - ?line Mod:rename("fil1","tmp_fil1"), - ?line {ok, <<"fil1">>} = Mod:read_file("tmp_fil1"), - ?line {error,enoent} = Mod:read_file("fil1"), - ?line Mod:rename("tmp_fil1","fil1"), - ?line {ok, <<"fil1">>} = Mod:read_file("fil1"), - ?line {error,enoent} = Mod:read_file("tmp_fil1"), - ?line {ok,FI} = Mod:read_file_info("fil1"), - ?line NewMode = FI#file_info.mode band (bnot 8#333), - ?line NewMode2 = NewMode bor 8#222, - ?line true = NewMode2 =/= NewMode, - ?line ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode}), - ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("fil1"), - ?line ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode2}), - ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("fil1"), + [ begin + {ok, FD} = Mod:open(Name,[read]), + {ok, Content} = Mod:read(FD,1024), + ok = file:close(FD) + end || {regular,Name,Content} <- NormalDir ], + [ begin + {ok, FD} = Mod:open(Name,[read,binary]), + BC = list_to_binary(Content), + {ok, BC} = Mod:read(FD,1024), + ok = file:close(FD) + end || {regular,Name,Content} <- NormalDir ], + Mod:rename("fil1","tmp_fil1"), + {ok, <<"fil1">>} = Mod:read_file("tmp_fil1"), + {error,enoent} = Mod:read_file("fil1"), + Mod:rename("tmp_fil1","fil1"), + {ok, <<"fil1">>} = Mod:read_file("fil1"), + {error,enoent} = Mod:read_file("tmp_fil1"), + {ok,FI} = Mod:read_file_info("fil1"), + NewMode = FI#file_info.mode band (bnot 8#333), + NewMode2 = NewMode bor 8#222, + true = NewMode2 =/= NewMode, + ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode}), + {ok,#file_info{mode = NewMode}} = Mod:read_file_info("fil1"), + ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode2}), + {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("fil1"), ok after case Mod:read_file_info("fil1") of @@ -347,129 +332,130 @@ check_normal(Mod) -> check_icky(Mod) -> {ok,Dir} = Mod:get_cwd(), try - ?line true=(length("åäö") =:= 3), - ?line UniMode = file:native_name_encoding() =/= latin1, - ?line make_icky_dir(Mod), + true=(length("åäö") =:= 3), + UniMode = file:native_name_encoding() =/= latin1, + IckyDir = make_icky_dir(Mod, "icky_dir"), {ok, L0} = Mod:list_dir_all("."), - ?line L1 = lists:sort(L0), - io:format("~p~n~p~n~n",[L1,lists:sort(list(icky_dir()))]), - ?line L1 = lists:sort(convlist(list(icky_dir()))), - ?line {ok,D2} = Mod:get_cwd(), - ?line true = is_list(D2), -%% Altname only on windows, and there are no non native filenames there -%% ?line case Mod:altname("fil1") of -%% {error,enotsup} -> -%% ok; -%% {ok,LLL} when is_list(LLL) -> -%% ok -%% end, - ?line [ true = ((is_list(El) or (UniMode and is_binary(El)))) || El <- L1], - ?line Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,icky_dir()))} - || {T,S,Targ} <- icky_dir(), T =:= symlink ], - ?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ], + L1 = lists:sort(L0), + io:format("~p~n~p~n~n",[L1,lists:sort(list(IckyDir))]), + L1 = lists:sort(convlist(list(IckyDir))), + {ok,D2} = Mod:get_cwd(), + true = is_list(D2), + %% Altname only on windows, and there are no non native filenames there + %% case Mod:altname("fil1") of + %% {error,enotsup} -> + %% ok; + %% {ok,LLL} when is_list(LLL) -> + %% ok + %% end, + [ true = ((is_list(El) or (UniMode and is_binary(El)))) || El <- L1], + Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,IckyDir))} + || {T,S,Targ} <- IckyDir, T =:= symlink ], + [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ], [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) || {SymL,Targ,_} <- Syms ], - ?line chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]), - ?line {ok,BeginAt} = Mod:get_cwd(), - ?line true = is_list(BeginAt), - ?line {error,enoent} = Mod:set_cwd("åä_dir"), - ?line ok = Mod:set_cwd("åäö_dir"), - ?line {ok, NowAt} = Mod:get_cwd(), - ?line true = is_list(NowAt), - ?line true = BeginAt =/= NowAt, - ?line ok = Mod:set_cwd(".."), - ?line {ok,BeginAt} = Mod:get_cwd(), - ?line rm_r2(Mod,"åäö_dir"), + + {ok,BeginAt} = Mod:get_cwd(), + true = is_list(BeginAt), + _ = make_icky_dir(Mod, "åäö_dir"), + {error,enoent} = Mod:set_cwd("åä_dir"), + {ok, NowAt} = Mod:get_cwd(), + true = is_list(NowAt), + true = BeginAt =/= NowAt, + ok = Mod:set_cwd(".."), + {ok,BeginAt} = Mod:get_cwd(), + rm_r2(Mod,"åäö_dir"), {OS,_} = os:type(), - % Check that treat_icky really converts to the same as the OS + + %% Check that treat_icky really converts to the same as the OS case UniMode of true -> - ?line chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]), - ?line ok = Mod:set_cwd("åäö_dir"), - ?line ok = Mod:write_file(<<"ååå">>,<<"hello">>), - ?line Treated = treat_icky(<<"ååå">>), + ok = Mod:make_dir("åäö_dir"), + ok = Mod:set_cwd("åäö_dir"), + ok = Mod:write_file(<<"ååå">>,<<"hello">>), + Treated = treat_icky(<<"ååå">>), {ok,[Treated]} = Mod:list_dir_all("."), - ?line ok = Mod:delete(<<"ååå">>), - ?line {ok,[]} = Mod:list_dir("."), - ?line ok = Mod:set_cwd(".."), - ?line rm_r2(Mod,"åäö_dir"); + ok = Mod:delete(<<"ååå">>), + {ok,[]} = Mod:list_dir("."), + ok = Mod:set_cwd(".."), + rm_r2(Mod,"åäö_dir"); false -> ok end, - ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]), + _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir"/utf8>>)), if UniMode and (OS =/= win32) -> - ?line {error,enoent} = Mod:set_cwd("åäö_dir"); + {error,enoent} = Mod:set_cwd("åäö_dir"); true -> ok end, - ?line {ok,BeginAt} = Mod:get_cwd(), - case has_links() of - true -> - ?line ok = Mod:make_link("fil1","nisseö"), - ?line {ok, <<"fil1">>} = Mod:read_file("nisseö"), - ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"), - ?line ok = Mod:delete("nisseö"), - ?line ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)), - ?line {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)), - ?line {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)), - ?line ok = Mod:delete(treat_icky(<<"nisseö">>)), - ?line {ok, <<"fil1">>} = Mod:read_file("fil1"), - ?line {error,enoent} = Mod:read_file("nisseö"), - ?line {error,enoent} = Mod:read_link_info("nisseö"), - ?line {error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)), - ?line {error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>)); - false -> + ok = Mod:set_cwd(".."), + {ok,BeginAt} = Mod:get_cwd(), + case Mod:make_link("fil1", "nisseö") of + ok -> + {ok, <<"fil1">>} = Mod:read_file("nisseö"), + {ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"), + ok = Mod:delete("nisseö"), + ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)), + {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)), + {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)), + ok = Mod:delete(treat_icky(<<"nisseö">>)), + {ok, <<"fil1">>} = Mod:read_file("fil1"), + {error,enoent} = Mod:read_file("nisseö"), + {error,enoent} = Mod:read_link_info("nisseö"), + {error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)), + {error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>)); + {error,enotsup} -> ok end, - ?line [ begin - ?line {ok, FD} = Mod:open(Name,[read]), - ?line {ok, Content} = Mod:read(FD,1024), - ?line ok = file:close(FD) - end || {regular,Name,Content} <- icky_dir() ], - ?line [ begin - ?line {ok, FD} = Mod:open(Name,[read,binary]), - ?line BC = list_to_binary([Content]), - ?line {ok, BC} = Mod:read(FD,1024), - ?line ok = file:close(FD) - end || {regular,Name,Content} <- icky_dir() ], - ?line Mod:rename("åäö2","åäö_fil1"), - ?line {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"), - ?line {error,enoent} = Mod:read_file("åäö2"), - ?line Mod:rename("åäö_fil1","åäö2"), - ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"), - ?line {error,enoent} = Mod:read_file("åäö_fil1"), + [ begin + {ok, FD} = Mod:open(Name,[read]), + {ok, Content} = Mod:read(FD,1024), + ok = file:close(FD) + end || {regular,Name,Content} <- IckyDir ], + [ begin + {ok, FD} = Mod:open(Name,[read,binary]), + BC = list_to_binary([Content]), + {ok, BC} = Mod:read(FD,1024), + ok = file:close(FD) + end || {regular,Name,Content} <- IckyDir ], + Mod:rename("åäö2","åäö_fil1"), + {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"), + {error,enoent} = Mod:read_file("åäö2"), + Mod:rename("åäö_fil1","åäö2"), + {ok, <<"åäö2">>} = Mod:read_file("åäö2"), + {error,enoent} = Mod:read_file("åäö_fil1"), - ?line Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)), - ?line {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)), + Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)), + {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)), if UniMode and (OS =/= win32) -> {error,enoent} = Mod:read_file("åäö_fil1"); true -> ok end, - ?line {error,enoent} = Mod:read_file("åäö2"), - ?line Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"), - ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"), - ?line {error,enoent} = Mod:read_file("åäö_fil1"), - ?line {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)), + {error,enoent} = Mod:read_file("åäö2"), + Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"), + {ok, <<"åäö2">>} = Mod:read_file("åäö2"), + {error,enoent} = Mod:read_file("åäö_fil1"), + {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)), - ?line {ok,FI} = Mod:read_file_info("åäö2"), - ?line NewMode = FI#file_info.mode band (bnot 8#333), - ?line NewMode2 = NewMode bor 8#222, - ?line true = NewMode2 =/= NewMode, - ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}), - ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"), - ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}), - ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"), + {ok,FI} = Mod:read_file_info("åäö2"), + NewMode = FI#file_info.mode band (bnot 8#333), + NewMode2 = NewMode bor 8#222, + true = NewMode2 =/= NewMode, + ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}), + {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"), + ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}), + {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"), - ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)), - ?line true = NewMode2 =/= NewMode, - ?line ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}), - ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)), - ?line ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}), - ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)), + {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)), + true = NewMode2 =/= NewMode, + ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}), + {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)), + ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}), + {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)), ok after Mod:set_cwd(Dir), @@ -479,90 +465,90 @@ check_icky(Mod) -> check_very_icky(Mod) -> {ok,Dir} = Mod:get_cwd(), try - ?line true=(length("åäö") =:= 3), - ?line UniMode = file:native_name_encoding() =/= latin1, + true=(length("åäö") =:= 3), + UniMode = file:native_name_encoding() =/= latin1, if not UniMode -> throw(need_unicode_mode); true -> ok end, - ?line make_very_icky_dir(Mod), - {ok, L0} = Mod:list_dir_all("."), - ?line L1 = lists:sort(L0), - ?line L1 = lists:sort(convlist(list(very_icky_dir()))), - ?line {ok,D2} = Mod:get_cwd(), - ?line true = is_list(D2), - ?line [ true = ((is_list(El) or is_binary(El))) || El <- L1], - ?line Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,very_icky_dir()))} - || {T,S,Targ} <- very_icky_dir(), T =:= symlink ], - ?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ], - ?line [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) || - {SymL,Targ,_} <- Syms ], - ?line chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]), - ?line {ok,BeginAt} = Mod:get_cwd(), - ?line true = is_list(BeginAt), - ?line {error,enoent} = Mod:set_cwd("åä_dir"), - ?line ok = Mod:set_cwd([1088,1079,1091]++"_dir"), - ?line {ok, NowAt} = Mod:get_cwd(), - ?line true = is_list(NowAt), - ?line true = BeginAt =/= NowAt, - ?line ok = Mod:set_cwd(".."), - ?line {ok,BeginAt} = Mod:get_cwd(), - ?line rm_r2(Mod,[1088,1079,1091]++"_dir"), + VeryIckyDir = make_very_icky_dir(Mod, "very_icky_dir"), + Expected = lists:sort(convlist(list(VeryIckyDir))), + {ok, Actual} = Mod:list_dir_all("."), + Expected = lists:sort(Actual), + {ok,D2} = Mod:get_cwd(), + true = is_list(D2), + [ true = ((is_list(El) or is_binary(El))) || El <- Expected], + Syms = [{S,conv(Targ),list_to_binary(get_data(Targ, VeryIckyDir))} + || {symlink,S,Targ} <- VeryIckyDir], + [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ], + [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) || + {SymL,Targ,_} <- Syms ], - case has_links() of - true -> - ?line ok = Mod:make_link("fil1","nisse"++[1088,1079,1091]), - ?line {ok, <<"fil1">>} = + {ok,BeginAt} = Mod:get_cwd(), + OtherDir = [1088,1079,1091] ++ "_dir", + true = is_list(BeginAt), + make_very_icky_dir(Mod, OtherDir), + {error,enoent} = Mod:set_cwd("åä_dir"), + {ok, NowAt} = Mod:get_cwd(), + true = is_list(NowAt), + true = BeginAt =/= NowAt, + ok = Mod:set_cwd(".."), + {ok,BeginAt} = Mod:get_cwd(), + rm_r2(Mod, OtherDir), + + case Mod:make_link("fil1","nisse"++[1088,1079,1091]) of + ok -> + {ok, <<"fil1">>} = Mod:read_file("nisse"++[1088,1079,1091]), - ?line {ok, #file_info{type = regular}} = + {ok, #file_info{type = regular}} = Mod:read_link_info("nisse"++[1088,1079,1091]), - ?line ok = Mod:delete("nisse"++[1088,1079,1091]), - ?line ok = Mod:make_link("fil1",<<"nisseö">>), - ?line {ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>), - ?line {ok, #file_info{type = regular}} = + ok = Mod:delete("nisse"++[1088,1079,1091]), + ok = Mod:make_link("fil1",<<"nisseö">>), + {ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>), + {ok, #file_info{type = regular}} = Mod:read_link_info(<<"nisseö">>), - ?line ok = Mod:delete(<<"nisseö">>), - ?line {ok, <<"fil1">>} = Mod:read_file("fil1"), - ?line {error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]), - ?line {error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]), - ?line {error,enoent} = Mod:read_file(<<"nisseö">>), - ?line {error,enoent} = Mod:read_link_info(<<"nisseö">>); - false -> + ok = Mod:delete(<<"nisseö">>), + {ok, <<"fil1">>} = Mod:read_file("fil1"), + {error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]), + {error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]), + {error,enoent} = Mod:read_file(<<"nisseö">>), + {error,enoent} = Mod:read_link_info(<<"nisseö">>); + {error,enotsup} -> ok end, - ?line [ begin - ?line {ok, FD} = Mod:open(Name,[read]), - ?line {ok, Content} = Mod:read(FD,1024), - ?line ok = file:close(FD) - end || {regular,Name,Content} <- very_icky_dir() ], - ?line [ begin - ?line {ok, FD} = Mod:open(Name,[read,binary]), - ?line BC = list_to_binary([Content]), - ?line {ok, BC} = Mod:read(FD,1024), - ?line ok = file:close(FD) - end || {regular,Name,Content} <- very_icky_dir() ], - ?line Mod:rename([956,965,963,954,959,49], - [956,965,963,954,959]++"_fil1"), - ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"), - ?line {error,enoent} = Mod:read_file([956,965,963,954,959,49]), - ?line Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]), - ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]), - ?line {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"), + [ begin + {ok, FD} = Mod:open(Name,[read]), + {ok, Content} = Mod:read(FD,1024), + ok = file:close(FD) + end || {regular,Name,Content} <- VeryIckyDir ], + [ begin + {ok, FD} = Mod:open(Name,[read,binary]), + BC = list_to_binary([Content]), + {ok, BC} = Mod:read(FD,1024), + ok = file:close(FD) + end || {regular,Name,Content} <- VeryIckyDir ], + Mod:rename([956,965,963,954,959,49], + [956,965,963,954,959]++"_fil1"), + {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"), + {error,enoent} = Mod:read_file([956,965,963,954,959,49]), + Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]), + {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]), + {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"), - ?line {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]), - ?line NewMode = FI#file_info.mode band (bnot 8#333), - ?line NewMode2 = NewMode bor 8#222, - ?line true = NewMode2 =/= NewMode, - ?line ok = Mod:write_file_info([956,965,963,954,959,49], - FI#file_info{mode = NewMode}), - ?line {ok,#file_info{mode = NewMode}} = - Mod:read_file_info([956,965,963,954,959,49]), - ?line ok = Mod:write_file_info([956,965,963,954,959,49], - FI#file_info{mode = NewMode2}), - ?line {ok,#file_info{mode = NewMode2}} = - Mod:read_file_info([956,965,963,954,959,49]), + {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]), + NewMode = FI#file_info.mode band (bnot 8#333), + NewMode2 = NewMode bor 8#222, + true = NewMode2 =/= NewMode, + ok = Mod:write_file_info([956,965,963,954,959,49], + FI#file_info{mode = NewMode}), + {ok,#file_info{mode = NewMode}} = + Mod:read_file_info([956,965,963,954,959,49]), + ok = Mod:write_file_info([956,965,963,954,959,49], + FI#file_info{mode = NewMode2}), + {ok,#file_info{mode = NewMode2}} = + Mod:read_file_info([956,965,963,954,959,49]), ok catch throw:need_unicode_mode -> @@ -592,7 +578,6 @@ rm_rf(Mod,Dir) -> end. rm_r(Mod,Dir) -> - %erlang:display({rm_r,Dir}), case Mod:read_link_info(Dir) of {ok, #file_info{type = directory}} -> {ok,#file_info{type = directory}} = Mod:read_file_info(Dir), @@ -610,7 +595,7 @@ rm_r(Mod,Dir) -> end. %% For icky test, allow binaries sometimes rm_r2(Mod,Dir) -> - %erlang:display({rm_r2,Dir}), + %% erlang:display({rm_r2,Dir}), case Mod:read_link_info(Dir) of {ok, #file_info{type = directory}} -> {ok,#file_info{type = directory}} = Mod:read_file_info(Dir), @@ -627,90 +612,35 @@ rm_r2(Mod,Dir) -> {ok, #file_info{type = symlink}} -> ok = Mod:delete(Dir) end. -chk_cre_dir(_,[]) -> - ok; -chk_cre_dir(Mod,[{regular,Name,Content}|T]) -> - %io:format("~p~n",[Name]), - ok = Mod:write_file(Name,Content), - chk_cre_dir(Mod,T); -chk_cre_dir(Mod,[{link,Name,Target}|T]) -> - ok = Mod:make_link(Target,Name), - chk_cre_dir(Mod,T); -chk_cre_dir(Mod,[{symlink,Name,Target}|T]) -> - ok = Mod:make_symlink(Target,Name), - chk_cre_dir(Mod,T); -chk_cre_dir(Mod,[{directory,Name,Content}|T]) -> - ok = Mod:make_dir(Name), - %io:format("Content = ~p~n",[Content]), - Content2 = [{Ty,filename:join(Name,N),case Ty of link -> filename:join(Name,C); _ -> C end} || {Ty,N,C} <- Content ], - %io:format("Content2 = ~p~n",[Content2]), - chk_cre_dir(Mod,Content2), - chk_cre_dir(Mod,T). - -has_links() -> - case os:type() of - {win32,_} -> - case os:version() of - {N,NN,_} when (N > 5) andalso (NN >= 1) -> - true; - _ -> - false - end; - _ -> - true - end. - -make_normal_dir(Mod) -> - rm_rf(Mod,"normal_dir"), - Mod:make_dir("normal_dir"), - Mod:set_cwd("normal_dir"), - Mod:write_file("fil1","fil1"), - Mod:write_file("fil2","fil2"), - case has_links() of - true -> - Mod:make_link("fil2","fil3"), - Mod:make_symlink("fil2","fil4"); - _ -> - ok - end, - Mod:make_dir("subdir"), - Mod:write_file(filename:join("subdir","subfil1"),"subfil1"), - ok. - -normal_dir() -> - [{regular,"fil1","fil1"}, - {regular,"fil2","fil2"}] ++ - case has_links() of - true -> - [{regular,"fil3","fil2"}, - {symlink,"fil4","fil2"}]; - false -> - [] - end ++ - [{directory,"subdir", - [{regular,"subfil1","subfil1"}]}]. -make_icky_dir(Mod) -> - rm_rf(Mod,"icky_dir"), - Icky=icky_dir(), - chk_cre_dir(Mod,[{directory,"icky_dir",linkify([],Icky)}]), - Mod:set_cwd("icky_dir"), - ok. +make_normal_dir(Mod, DirName) -> + Dir = [{regular,"fil1","fil1"}, + {regular,"fil2","fil2"}, + {hardlink,"fil3","fil2"}, + {symlink,"fil4","fil2"}, + {directory,"subdir", + [{regular,"subfil1","subfil1"}]}], + rm_rf(Mod, DirName), + Mod:make_dir(DirName), + Mod:set_cwd(DirName), + make_dir_contents(Dir, Mod). -linkify(_Passed,[]) -> - []; -linkify(Passed,[{regular,Name,Content}|T]) -> - Regulars = [ {N,C} || {regular,N,C} <- Passed, N =/= Name ], - case lists:keysearch(Content,2,Regulars) of - {value, {Linkto, Content}} -> - [{link,Name,Linkto} | linkify(Passed,T)]; - _ -> - [{regular,Name,Content} | linkify([{regular,Name,Content}|Passed],T)] - end; -linkify(Passed,[{directory, Name, Content}|T]) -> - [{directory,Name, linkify(Content,Content)}|linkify(Passed,T)]; -linkify(Passed,[H|T]) -> - [H|linkify([H|Passed],T)]. +make_icky_dir(Mod, IckyDirName) -> + Icky = [{regular,"fil1","fil1"}, + {regular,"åäö2","åäö2"}, + {hardlink,"åäö3","åäö2"}, + {symlink,"åäö4","åäö2"}, + {regular,treat_icky(<<"åäö5">>),"åäö5"}, + {symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}, + {directory,treat_icky(<<"åäösubdir2">>), + [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"}, + {regular,"åäösubfil3","åäösubfil13"}]}, + {directory,"åäösubdir", + [{regular,"åäösubfil1","åäösubfil1"}]}], + rm_rf(Mod, IckyDirName), + ok = Mod:make_dir(IckyDirName), + ok = Mod:set_cwd(IckyDirName), + make_dir_contents(Icky, Mod). hopeless_darwin() -> case {os:type(),os:version()} of @@ -720,58 +650,24 @@ hopeless_darwin() -> false end. -icky_dir() -> - [{regular,"fil1","fil1"}, - {regular,"åäö2","åäö2"}] ++ - case has_links() of - true -> - [{regular,"åäö3","åäö2"}, - {symlink,"åäö4","åäö2"}]; - false -> - [] - end ++ - [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++ - case has_links() of - true -> - [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}]; - false -> - [] - end ++ - [{directory,treat_icky(<<"åäösubdir2">>), - [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"}, - {regular,"åäösubfil3","åäösubfil13"}]}, - {directory,"åäösubdir", - [{regular,"åäösubfil1","åäösubfil1"}]}]. - -make_very_icky_dir(Mod) -> - rm_rf(Mod,"very_icky_dir"), - Icky=very_icky_dir(), - chk_cre_dir(Mod,[{directory,"very_icky_dir",linkify([],Icky)}]), - Mod:set_cwd("very_icky_dir"), - ok. - -very_icky_dir() -> - [{regular,"fil1","fil1"}, - {regular,[956,965,963,954,959,49],"åäö2"}] ++ - case has_links() of - true -> - [{regular,[956,965,963,954,959,50],"åäö2"}, - {symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]}]; - false -> - [] - end ++ - [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++ - case has_links() of - true -> - [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}]; - false -> - [] - end ++ - [{directory,treat_icky(<<"åäösubdir2">>), - [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"}, - {regular,"åäösubfil3","åäösubfil13"}]}, - {directory,[956,965,963,954,959]++"subdir1", - [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}]. +make_very_icky_dir(Mod, DirName) -> + Desc = [{regular,"fil1","fil1"}, + {regular,[956,965,963,954,959,49],"åäö2"}, + {hardlink,[956,965,963,954,959,50], + [956,965,963,954,959,49], + "åäö2"}, + {symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]}, + {regular,treat_icky(<<"åäö5">>),"åäö5"}, + {symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}, + {directory,treat_icky(<<"åäösubdir2">>), + [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"}, + {regular,"åäösubfil3","åäösubfil13"}]}, + {directory,[956,965,963,954,959]++"subdir1", + [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}], + rm_rf(Mod, DirName), + ok = Mod:make_dir(DirName), + ok = Mod:set_cwd(DirName), + make_dir_contents(Desc, Mod). %% Some OS'es simply do not allow non UTF8 filenames treat_icky(Bin) -> @@ -784,7 +680,7 @@ treat_icky(Bin) -> Bin end. -% Handle windows having absolute soft link targets. +%% Handle windows having absolute soft link targets. fixlink({ok,Link}) -> case os:type() of {win32,_} -> @@ -811,7 +707,7 @@ list([]) -> []; list([{_,Name,_} | T]) -> [Name | list(T)]. - + get_data(FN,List) -> case lists:keysearch(FN,2,List) of @@ -827,7 +723,7 @@ get_data(FN,List) -> convlist(L) -> convlist(file:native_name_encoding(),L). convlist(latin1,[Bin|T]) when is_binary(Bin) -> - %erlang:display('Convert...'), + %% erlang:display('Convert...'), [binary_to_list(Bin)| convlist(latin1,T)]; convlist(Any,[H|T]) -> [H|convlist(Any,T)]; @@ -844,18 +740,60 @@ conv(L) -> end. +make_dir_contents([{regular,Name,Contents}=H|T], Mod) -> + ok = Mod:write_file(Name, Contents), + [H|make_dir_contents(T, Mod)]; +make_dir_contents([{hardlink,Target,Name}|T], Mod) -> + case Mod:make_link(Name, Target) of + ok -> + [{regular,Target,Name}|make_dir_contents(T, Mod)]; + {error,enotsup} -> + make_dir_contents(T, Mod) + end; +make_dir_contents([{hardlink,Target,Name,Contents}|T], Mod) -> + case Mod:make_link(Name, Target) of + ok -> + [{regular,Target,Contents}|make_dir_contents(T, Mod)]; + {error,enotsup} -> + make_dir_contents(T, Mod) + end; +make_dir_contents([{symlink,Target,Name}=H|T], Mod) -> + case Mod:make_symlink(Name, Target) of + ok -> + [H|make_dir_contents(T, Mod)]; + {error,enotsup} -> + make_dir_contents(T, Mod); + {error,eperm} -> + make_dir_contents(T, Mod) + end; +make_dir_contents([{directory,Dir,C0}|T], Mod) -> + ok = Mod:make_dir(Dir), + C1 = [case Op of + Link when Link =:= hardlink; Link =:= symlink -> + {Op,filename:join(Dir, Name0),filename:join(Dir, Extra)}; + _ -> + {Op,filename:join(Dir, Name0),Extra} + end || {Op,Name0,Extra} <- C0], + C2 = make_dir_contents(C1, Mod), + C = [{Op,filename:basename(Name0),Extra} || + {Op,Name0,Extra} <- C2], + [{directory,Dir,C}|make_dir_contents(T, Mod)]; +make_dir_contents([], _Mod) -> + []. + + rand_comp_decomp(Max) -> - N = random:uniform(Max), + N = rand:uniform(Max), L = [ rand_decomp() || _ <- lists:seq(1,N) ], LC = [ A || {A,_} <- L], LD = lists:flatten([B || {_,B} <- L]), LB = unicode:characters_to_binary(LD,unicode,utf8), {LC,LB}. - + rand_decomp() -> BT = bigtup(), SZ = tuple_size(BT), - element(random:uniform(SZ),BT). + element(rand:uniform(SZ),BT). bigtup() -> {{192,[65,768]}, {200,[69,768]}, diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index 91a57d3290..620ab235a0 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2016. 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. @@ -19,7 +19,7 @@ %% -module(gen_sctp_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/inet_sctp.hrl"). %%-compile(export_all). @@ -29,7 +29,8 @@ init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). -export( - [basic/1, + [skip_old_solaris/1, + basic/1, api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1, xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1, open_multihoming_ipv4_socket/1, @@ -42,22 +43,32 @@ names_unihoming_ipv4/1, names_unihoming_ipv6/1, names_multihoming_ipv4/1, names_multihoming_ipv6/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. -all() -> - [basic, api_open_close, api_listen, api_connect_init, - api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6, - open_multihoming_ipv4_socket, - open_unihoming_ipv6_socket, - open_multihoming_ipv6_socket, - open_multihoming_ipv4_and_ipv6_socket, active_n, - basic_stream, xfer_stream_min, peeloff_active_once, - peeloff_active_true, peeloff_active_n, buffers, - names_unihoming_ipv4, names_unihoming_ipv6, - names_multihoming_ipv4, names_multihoming_ipv6]. +all() -> + G = case is_old_solaris() of + true -> old_solaris; + false -> extensive + end, + [{group,smoke}, + {group,G}]. groups() -> - []. + [{smoke,[],[basic,basic_stream]}, + {old_solaris,[],[skip_old_solaris]}, + {extensive,[], + [api_open_close, api_listen, api_connect_init, + api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6, + open_multihoming_ipv4_socket, + open_unihoming_ipv6_socket, + open_multihoming_ipv6_socket, + open_multihoming_ipv4_and_ipv6_socket, active_n, + xfer_stream_min, peeloff_active_once, + peeloff_active_true, peeloff_active_n, buffers, + names_unihoming_ipv4, names_unihoming_ipv6, + names_multihoming_ipv4, names_multihoming_ipv6]}]. init_per_suite(_Config) -> case gen_sctp:open() of @@ -81,48 +92,48 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(15)), - [{watchdog, Dog}|Config]. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). + Config. +end_per_testcase(_Func, _Config) -> + ok. -define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end). +is_old_solaris() -> + os:type() =:= {unix,sunos} andalso os:version() < {5,12,0}. +skip_old_solaris(_Config) -> + {skip,"Unreliable test cases and/or implementation on old Solaris"}. -basic(doc) -> - "Hello world"; -basic(suite) -> - []; +%% Hello world. basic(Config) when is_list(Config) -> - ?line {ok,S} = gen_sctp:open(), - ?line ok = gen_sctp:close(S), + {ok,S} = gen_sctp:open(), + ok = gen_sctp:close(S), ok. -xfer_min(doc) -> - "Minimal data transfer"; -xfer_min(suite) -> - []; +%% Minimal data transfer. xfer_min(Config) when is_list(Config) -> - ?line Stream = 0, - ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, - ?line Loopback = {127,0,0,1}, - ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]), - ?line {ok,Pb} = inet:port(Sb), - ?line ok = gen_sctp:listen(Sb, true), - - ?line {ok,Sa} = gen_sctp:open(), - ?line {ok,Pa} = inet:port(Sa), - ?line {ok,#sctp_assoc_change{state=comm_up, - error=0, - outbound_streams=SaOutboundStreams, - inbound_streams=SaInboundStreams, - assoc_id=SaAssocId}=SaAssocChange} = + Stream = 0, + Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, + Loopback = {127,0,0,1}, + StatOpts = + [recv_avg,recv_cnt,recv_max,recv_oct, + send_avg,send_cnt,send_max,send_oct], + {ok,Sb} = gen_sctp:open([{type,seqpacket}]), + {ok,SbStat1} = inet:getstat(Sb, StatOpts), + {ok,Pb} = inet:port(Sb), + ok = gen_sctp:listen(Sb, true), + + {ok,Sa} = gen_sctp:open(), + {ok,Pa} = inet:port(Sa), + {ok,#sctp_assoc_change{state=comm_up, + error=0, + outbound_streams=SaOutboundStreams, + inbound_streams=SaInboundStreams, + assoc_id=SaAssocId}=SaAssocChange} = gen_sctp:connect(Sa, Loopback, Pb, []), - ?line {SbAssocId,SaOutboundStreams,SaInboundStreams} = + {SbAssocId,SaOutboundStreams,SaInboundStreams} = case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of {Loopback,Pa, #sctp_assoc_change{state=comm_up, @@ -142,184 +153,195 @@ xfer_min(Config) when is_list(Config) -> outbound_streams=SbOutboundStreams, inbound_streams=SbInboundStreams, assoc_id=AssocId}} = - ?line recv_event(log_ok(gen_sctp:recv(Sb, infinity))), + recv_event(log_ok(gen_sctp:recv(Sb, infinity))), {AssocId,SbInboundStreams,SbOutboundStreams} end, - ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data), - ?line case log_ok(gen_sctp:recv(Sb, infinity)) of - {Loopback, - Pa, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - Data} -> ok; - Event1 -> - case recv_event(Event1) of - {Loopback,Pa, - #sctp_paddr_change{addr = {Loopback,_}, - state = State, - error = 0, - assoc_id = SbAssocId}} - when State =:= addr_available; - State =:= addr_confirmed -> - {Loopback, - Pa, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - Data} = log_ok(gen_sctp:recv(Sb, infinity)) - end - end, - ?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data), - ?line case log_ok(gen_sctp:recv(Sa, infinity)) of - {Loopback,Pb, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SaAssocId}], - Data} -> - ok; - Event2 -> - {Loopback,Pb, - #sctp_paddr_change{addr={_,Pb}, - state=addr_confirmed, - error=0, - assoc_id=SaAssocId}} = - ?line recv_event(Event2), - ?line {Loopback, - Pb, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SaAssocId}], - Data} = - log_ok(gen_sctp:recv(Sa, infinity)) - end, + ok = gen_sctp:send(Sa, SaAssocId, 0, Data), + case log_ok(gen_sctp:recv(Sb, infinity)) of + {Loopback, + Pa, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + Data} -> ok; + Event1 -> + case recv_event(Event1) of + {Loopback,Pa, + #sctp_paddr_change{addr = {Loopback,_}, + state = State, + error = 0, + assoc_id = SbAssocId}} + when State =:= addr_available; + State =:= addr_confirmed -> + {Loopback, + Pa, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + Data} = log_ok(gen_sctp:recv(Sb, infinity)) + end + end, + ok = gen_sctp:send(Sb, SbAssocId, 0, Data), + case log_ok(gen_sctp:recv(Sa, infinity)) of + {Loopback,Pb, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SaAssocId}], + Data} -> + ok; + Event2 -> + {Loopback,Pb, + #sctp_paddr_change{addr={_,Pb}, + state=addr_confirmed, + error=0, + assoc_id=SaAssocId}} = + recv_event(Event2), + {Loopback, + Pb, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SaAssocId}], + Data} = + log_ok(gen_sctp:recv(Sa, infinity)) + end, %% - ?line ok = gen_sctp:eof(Sa, SaAssocChange), - ?line {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} = + ok = gen_sctp:eof(Sa, SaAssocChange), + {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} = recv_event(log_ok(gen_sctp:recv(Sb, infinity))), - ?line {Loopback,Pb, - #sctp_assoc_change{state=shutdown_comp, - error=0, - assoc_id=SaAssocId}} = + {Loopback,Pb, + #sctp_assoc_change{state=shutdown_comp, + error=0, + assoc_id=SaAssocId}} = recv_event(log_ok(gen_sctp:recv(Sa, infinity))), - ?line {Loopback,Pa, - #sctp_assoc_change{state=shutdown_comp, - error=0, - assoc_id=SbAssocId}} = + {Loopback,Pa, + #sctp_assoc_change{state=shutdown_comp, + error=0, + assoc_id=SbAssocId}} = recv_event(log_ok(gen_sctp:recv(Sb, infinity))), - ?line ok = gen_sctp:close(Sa), - ?line ok = gen_sctp:close(Sb), + ok = gen_sctp:close(Sa), + {ok,SbStat2} = inet:getstat(Sb, StatOpts), + [] = filter_stat_eq(SbStat1, SbStat2), + ok = gen_sctp:close(Sb), - ?line receive - Msg -> test_server:fail({received,Msg}) - after 17 -> ok - end, + receive + Msg -> ct:fail({received,Msg}) + after 17 -> ok + end, ok. -xfer_active(doc) -> - "Minimal data transfer in active mode"; -xfer_active(suite) -> +filter_stat_eq([], []) -> []; +filter_stat_eq([{Tag,Val1}=Stat|SbStat1], [{Tag,Val2}|SbStat2]) -> + if + Val1 == Val2 -> + [Stat|filter_stat_eq(SbStat1, SbStat2)]; + true -> + filter_stat_eq(SbStat1, SbStat2) + end. + + + +%% Minimal data transfer in active mode. xfer_active(Config) when is_list(Config) -> - ?line Timeout = 2000, - ?line Stream = 0, - ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, - ?line Loopback = {127,0,0,1}, - ?line {ok,Sb} = gen_sctp:open([{active,true}]), - ?line {ok,Pb} = inet:port(Sb), - ?line ok = gen_sctp:listen(Sb, true), - - ?line {ok,Sa} = gen_sctp:open([{active,true}]), - ?line {ok,Pa} = inet:port(Sa), - ?line ok = gen_sctp:connect_init(Sa, Loopback, Pb, []), - ?line #sctp_assoc_change{state=comm_up, - error=0, - outbound_streams=SaOutboundStreams, - inbound_streams=SaInboundStreams, - assoc_id=SaAssocId} = SaAssocChange = + Timeout = 2000, + Stream = 0, + Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, + Loopback = {127,0,0,1}, + {ok,Sb} = gen_sctp:open([{active,true}]), + {ok,Pb} = inet:port(Sb), + ok = gen_sctp:listen(Sb, true), + + {ok,Sa} = gen_sctp:open([{active,true}]), + {ok,Pa} = inet:port(Sa), + ok = gen_sctp:connect_init(Sa, Loopback, Pb, []), + #sctp_assoc_change{state=comm_up, + error=0, + outbound_streams=SaOutboundStreams, + inbound_streams=SaInboundStreams, + assoc_id=SaAssocId} = SaAssocChange = recv_assoc_change(Sa, Loopback, Pb, Timeout), - ?line io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, " - "SaOutboundStreams=~p, SaInboundStreams=~p~n", - [Sa,Pa,Sb,Pb,SaAssocId, - SaOutboundStreams,SaInboundStreams]), - ?line #sctp_assoc_change{state=comm_up, - error=0, - outbound_streams=SbOutboundStreams, - inbound_streams=SbInboundStreams, - assoc_id=SbAssocId} = + io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, " + "SaOutboundStreams=~p, SaInboundStreams=~p~n", + [Sa,Pa,Sb,Pb,SaAssocId, + SaOutboundStreams,SaInboundStreams]), + #sctp_assoc_change{state=comm_up, + error=0, + outbound_streams=SbOutboundStreams, + inbound_streams=SbInboundStreams, + assoc_id=SbAssocId} = recv_assoc_change(Sb, Loopback, Pa, Timeout), - ?line SbOutboundStreams = SaInboundStreams, - ?line SbInboundStreams = SaOutboundStreams, - ?line io:format("SbAssocId=~p~n", [SbAssocId]), - - ?line case recv_paddr_change(Sa, Loopback, Pb, 314) of - #sctp_paddr_change{state=addr_confirmed, - addr={_,Pb}, - error=0, - assoc_id=SaAssocId} -> ok; - #sctp_paddr_change{state=addr_available, - addr={_,Pb}, - error=0, - assoc_id=SaAssocId} -> ok; - timeout -> ok - end, - ?line case recv_paddr_change(Sb, Loopback, Pa, 314) of - #sctp_paddr_change{state=addr_confirmed, - addr={Loopback,Pa}, - error=0, - assoc_id=SbAssocId} -> ok; - #sctp_paddr_change{state=addr_available, - addr={Loopback,P}, - error=0, - assoc_id=SbAssocId} -> - ?line match_unless_solaris(Pa, P); - timeout -> ok - end, - ?line [] = flush(), - - ?line ok = + SbOutboundStreams = SaInboundStreams, + SbInboundStreams = SaOutboundStreams, + io:format("SbAssocId=~p~n", [SbAssocId]), + + case recv_paddr_change(Sa, Loopback, Pb, 314) of + #sctp_paddr_change{state=addr_confirmed, + addr={_,Pb}, + error=0, + assoc_id=SaAssocId} -> ok; + #sctp_paddr_change{state=addr_available, + addr={_,Pb}, + error=0, + assoc_id=SaAssocId} -> ok; + timeout -> ok + end, + case recv_paddr_change(Sb, Loopback, Pa, 314) of + #sctp_paddr_change{state=addr_confirmed, + addr={Loopback,Pa}, + error=0, + assoc_id=SbAssocId} -> ok; + #sctp_paddr_change{state=addr_available, + addr={Loopback,P}, + error=0, + assoc_id=SbAssocId} -> + match_unless_solaris(Pa, P); + timeout -> ok + end, + [] = flush(), + + ok = do_from_other_process( fun () -> gen_sctp:send(Sa, SaAssocId, 0, Data) end), - ?line receive - {sctp,Sb,Loopback,Pa, - {[#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - Data}} -> ok - after Timeout -> - ?line test_server:fail({timeout,flush()}) - end, - ?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data), - ?line receive - {sctp,Sa,Loopback,Pb, - {[#sctp_sndrcvinfo{stream=Stream, - assoc_id=SaAssocId}], - Data}} -> ok - after Timeout -> - ?line test_server:fail({timeout,flush()}) - end, + receive + {sctp,Sb,Loopback,Pa, + {[#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + Data}} -> ok + after Timeout -> + ct:fail({timeout,flush()}) + end, + ok = gen_sctp:send(Sb, SbAssocId, 0, Data), + receive + {sctp,Sa,Loopback,Pb, + {[#sctp_sndrcvinfo{stream=Stream, + assoc_id=SaAssocId}], + Data}} -> ok + after Timeout -> + ct:fail({timeout,flush()}) + end, %% - ?line ok = gen_sctp:abort(Sa, SaAssocChange), - ?line case recv_assoc_change(Sb, Loopback, Pa, Timeout) of - #sctp_assoc_change{state=comm_lost, - assoc_id=SbAssocId} -> ok; - timeout -> - ?line test_server:fail({timeout,flush()}) - end, - ?line ok = gen_sctp:close(Sb), - ?line case recv_assoc_change(Sa, Loopback, Pb, Timeout) of - #sctp_assoc_change{state=comm_lost, - assoc_id=SaAssocId} -> ok; - timeout -> - ?line io:format("timeout waiting for comm_lost on Sa~n"), - ?line match_unless_solaris(ok, {timeout,flush()}) - end, - ?line receive - {sctp_error,Sa,enotconn} -> ok % Solaris - after 17 -> ok - end, - ?line ok = gen_sctp:close(Sa), + ok = gen_sctp:abort(Sa, SaAssocChange), + case recv_assoc_change(Sb, Loopback, Pa, Timeout) of + #sctp_assoc_change{state=comm_lost, + assoc_id=SbAssocId} -> ok; + timeout -> + ct:fail({timeout,flush()}) + end, + ok = gen_sctp:close(Sb), + case recv_assoc_change(Sa, Loopback, Pb, Timeout) of + #sctp_assoc_change{state=comm_lost, + assoc_id=SaAssocId} -> ok; + timeout -> + io:format("timeout waiting for comm_lost on Sa~n"), + match_unless_solaris(ok, {timeout,flush()}) + end, + receive + {sctp_error,Sa,enotconn} -> ok % Solaris + after 17 -> ok + end, + ok = gen_sctp:close(Sa), %% - ?line receive - Msg -> test_server:fail({unexpected,[Msg]++flush()}) - after 17 -> ok - end, + receive + Msg -> ct:fail({unexpected,[Msg]++flush()}) + after 17 -> ok + end, ok. recv_assoc_change(S, Addr, Port, Timeout) -> @@ -346,142 +368,141 @@ recv_paddr_change(S, Addr, Port, Timeout) -> timeout end. -def_sndrcvinfo(doc) -> - "Test that #sctp_sndrcvinfo{} parameters set on a socket " - "are used by gen_sctp:send/4"; -def_sndrcvinfo(suite) -> - []; +%% Test that #sctp_sndrcvinfo{} parameters set on a socket +%% are used by gen_sctp:send/4. def_sndrcvinfo(Config) when is_list(Config) -> - ?line Loopback = {127,0,0,1}, - ?line Data = <<"What goes up, must come down.">>, + Loopback = {127,0,0,1}, + Data = <<"What goes up, must come down.">>, %% - ?line S1 = + S1 = log_ok(gen_sctp:open( 0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])), ?LOGVAR(S1), - ?line P1 = + P1 = log_ok(inet:port(S1)), ?LOGVAR(P1), - ?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} = + #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} = getopt(S1, sctp_default_send_param), - ?line ok = + ok = gen_sctp:listen(S1, true), %% - ?line S2 = + S2 = log_ok(gen_sctp:open()), ?LOGVAR(S2), - ?line P2 = + P2 = log_ok(inet:port(S2)), ?LOGVAR(P2), - ?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} = + #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} = getopt(S2, sctp_default_send_param), %% - ?line #sctp_assoc_change{ + #sctp_assoc_change{ state=comm_up, error=0, assoc_id=S2AssocId} = S2AssocChange = log_ok(gen_sctp:connect(S2, Loopback, P1, [])), ?LOGVAR(S2AssocChange), - ?line case recv_event(log_ok(gen_sctp:recv(S1))) of - {Loopback,P2, - #sctp_assoc_change{ - state=comm_up, - error=0, - assoc_id=S1AssocId}} -> - ?LOGVAR(S1AssocId); - {Loopback,P2, - #sctp_paddr_change{ - state=addr_confirmed, - error=0, - assoc_id=S1AssocId}} -> - ?LOGVAR(S1AssocId), - {Loopback,P2, - #sctp_assoc_change{ - state=comm_up, - error=0, - assoc_id=S1AssocId}} = - recv_event(log_ok(gen_sctp:recv(S1))) - end, - - ?line #sctp_sndrcvinfo{ + S1AssocId = + case recv_event(log_ok(gen_sctp:recv(S1))) of + {Loopback,P2, + #sctp_assoc_change{ + state=comm_up, + error=0, + assoc_id=AssocId}} -> + AssocId; + {Loopback,P2, + #sctp_paddr_change{ + state=addr_confirmed, + error=0, + assoc_id=AssocId}} -> + {Loopback,P2, + #sctp_assoc_change{ + state=comm_up, + error=0, + assoc_id=AssocId}} = + recv_event(log_ok(gen_sctp:recv(S1))), + AssocId + end, + ?LOGVAR(S1AssocId), + + #sctp_sndrcvinfo{ ppid=17, context=0, timetolive=0} = %, assoc_id=S1AssocId} = getopt( S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}), - ?line #sctp_sndrcvinfo{ + #sctp_sndrcvinfo{ ppid=0, context=0, timetolive=0} = %, assoc_id=S2AssocId} = getopt( S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}), %% - ?line ok = + ok = gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>), - ?line case log_ok(gen_sctp:recv(S2)) of - {Loopback,P1, - [#sctp_sndrcvinfo{ - stream=1, ppid=17, context=0, assoc_id=S2AssocId}], - <<"1: ",Data/binary>>} -> ok; - Event1 -> - ?line {Loopback,P1, - #sctp_paddr_change{state=addr_confirmed, - addr={_,P1}, - error=0, - assoc_id=S2AssocId}} = - recv_event(Event1), - ?line {Loopback,P1, - [#sctp_sndrcvinfo{ - stream=1, ppid=17, context=0, assoc_id=S2AssocId}], - <<"1: ",Data/binary>>} = - log_ok(gen_sctp:recv(S2)) - end, + case log_ok(gen_sctp:recv(S2)) of + {Loopback,P1, + [#sctp_sndrcvinfo{ + stream=1, ppid=17, context=0, assoc_id=S2AssocId}], + <<"1: ",Data/binary>>} -> ok; + Event1 -> + {Loopback,P1, + #sctp_paddr_change{state=addr_confirmed, + addr={_,P1}, + error=0, + assoc_id=S2AssocId}} = + recv_event(Event1), + {Loopback,P1, + [#sctp_sndrcvinfo{ + stream=1, ppid=17, context=0, assoc_id=S2AssocId}], + <<"1: ",Data/binary>>} = + log_ok(gen_sctp:recv(S2)) + end, %% - ?line ok = + ok = setopt( S1, sctp_default_send_param, #sctp_sndrcvinfo{ppid=18}), - ?line ok = + ok = setopt( S1, sctp_default_send_param, #sctp_sndrcvinfo{ppid=19, assoc_id=S1AssocId}), - ?line #sctp_sndrcvinfo{ + #sctp_sndrcvinfo{ ppid=18, context=0, timetolive=0, assoc_id=0} = getopt(S1, sctp_default_send_param), - ?line #sctp_sndrcvinfo{ + #sctp_sndrcvinfo{ ppid=19, context=0, timetolive=0, assoc_id=S1AssocId} = getopt( S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}), %% - ?line ok = + ok = gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>), - ?line case log_ok(gen_sctp:recv(S2)) of - {Loopback,P1, - [#sctp_sndrcvinfo{ - stream=0, ppid=19, context=0, assoc_id=S2AssocId}], - <<"2: ",Data/binary>>} -> ok - end, - ?line ok = + case log_ok(gen_sctp:recv(S2)) of + {Loopback,P1, + [#sctp_sndrcvinfo{ + stream=0, ppid=19, context=0, assoc_id=S2AssocId}], + <<"2: ",Data/binary>>} -> ok + end, + ok = gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>), - ?line case log_ok(gen_sctp:recv(S1)) of - {Loopback,P2, - [#sctp_sndrcvinfo{ - stream=1, ppid=0, context=0, assoc_id=S1AssocId}], - <<"3: ",Data/binary>>} -> ok; - Event2 -> - case recv_event(Event2) of - {Loopback,P2, - #sctp_paddr_change{ - addr={Loopback,_}, - state=State, - error=0, assoc_id=S1AssocId}} - when State =:= addr_available; - State =:= addr_confirmed -> - ?line case log_ok(gen_sctp:recv(S1)) of - {Loopback,P2, - [#sctp_sndrcvinfo{ - stream=1, ppid=0, context=0, - assoc_id=S1AssocId}], - <<"3: ",Data/binary>>} -> ok - end - end - end, - ?line ok = + case log_ok(gen_sctp:recv(S1)) of + {Loopback,P2, + [#sctp_sndrcvinfo{ + stream=1, ppid=0, context=0, assoc_id=S1AssocId}], + <<"3: ",Data/binary>>} -> ok; + Event2 -> + case recv_event(Event2) of + {Loopback,P2, + #sctp_paddr_change{ + addr={Loopback,_}, + state=State, + error=0, assoc_id=S1AssocId}} + when State =:= addr_available; + State =:= addr_confirmed -> + case log_ok(gen_sctp:recv(S1)) of + {Loopback,P2, + [#sctp_sndrcvinfo{ + stream=1, ppid=0, context=0, + assoc_id=S1AssocId}], + <<"3: ",Data/binary>>} -> ok + end + end + end, + ok = do_from_other_process( fun () -> gen_sctp:send( @@ -489,22 +510,22 @@ def_sndrcvinfo(Config) when is_list(Config) -> #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId}, <<"4: ",Data/binary>>) end), - ?line case log_ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of - {Loopback,P2, - [#sctp_sndrcvinfo{ - stream=0, ppid=20, context=0, assoc_id=S1AssocId}], - <<"4: ",Data/binary>>} -> ok - end, + case log_ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of + {Loopback,P2, + [#sctp_sndrcvinfo{ + stream=0, ppid=20, context=0, assoc_id=S1AssocId}], + <<"4: ",Data/binary>>} -> ok + end, %% - ?line ok = + ok = gen_sctp:close(S1), - ?line ok = + ok = gen_sctp:close(S2), - ?line receive - Msg -> - test_server:fail({received,Msg}) - after 17 -> ok - end, + receive + Msg -> + ct:fail({received,Msg}) + after 17 -> ok + end, ok. getopt(S, Opt) -> @@ -541,147 +562,138 @@ flush() -> [] end. -api_open_close(doc) -> - "Test the API function open/1,2 and close/1"; -api_open_close(suite) -> - []; +%% Test the API function open/1,2 and close/1. api_open_close(Config) when is_list(Config) -> - ?line {ok,S1} = gen_sctp:open(0), - ?line {ok,P} = inet:port(S1), - ?line ok = gen_sctp:close(S1), + {ok,S1} = gen_sctp:open(0), + {ok,P} = inet:port(S1), + ok = gen_sctp:close(S1), - ?line {ok,S2} = gen_sctp:open(P), - ?line {ok,P} = inet:port(S2), - ?line ok = gen_sctp:close(S2), + {ok,S2} = gen_sctp:open(P), + {ok,P} = inet:port(S2), + ok = gen_sctp:close(S2), - ?line {ok,S3} = gen_sctp:open([{port,P}]), - ?line {ok,P} = inet:port(S3), - ?line ok = gen_sctp:close(S3), + {ok,S3} = gen_sctp:open([{port,P}]), + {ok,P} = inet:port(S3), + ok = gen_sctp:close(S3), - ?line {ok,S4} = gen_sctp:open(P, []), - ?line {ok,P} = inet:port(S4), - ?line ok = gen_sctp:close(S4), + {ok,S4} = gen_sctp:open(P, []), + {ok,P} = inet:port(S4), + ok = gen_sctp:close(S4), - ?line {ok,S5} = gen_sctp:open(P, [{ifaddr,any}]), - ?line {ok,P} = inet:port(S5), - ?line ok = gen_sctp:close(S5), + {ok,S5} = gen_sctp:open(P, [{ifaddr,any}]), + {ok,P} = inet:port(S5), + ok = gen_sctp:close(S5), - ?line ok = gen_sctp:close(S5), + ok = gen_sctp:close(S5), - ?line try gen_sctp:close(0) - catch error:badarg -> ok - end, + try gen_sctp:close(0) + catch error:badarg -> ok + end, - ?line try gen_sctp:open({}) - catch error:badarg -> ok - end, + try gen_sctp:open({}) + catch error:badarg -> ok + end, - ?line try gen_sctp:open(-1) - catch error:badarg -> ok - end, + try gen_sctp:open(-1) + catch error:badarg -> ok + end, - ?line try gen_sctp:open(65536) - catch error:badarg -> ok - end, + try gen_sctp:open(65536) + catch error:badarg -> ok + end, - ?line try gen_sctp:open(make_ref(), []) - catch error:badarg -> ok - end, + try gen_sctp:open(make_ref(), []) + catch error:badarg -> ok + end, - ?line try gen_sctp:open(0, {}) - catch error:badarg -> ok - end, + try gen_sctp:open(0, {}) + catch error:badarg -> ok + end, - ?line try gen_sctp:open(0, [make_ref()]) - catch error:badarg -> ok - end, + try gen_sctp:open(0, [make_ref()]) + catch error:badarg -> ok + end, - ?line try gen_sctp:open([{invalid_option,0}]) - catch error:badarg -> ok - end, + try gen_sctp:open([{invalid_option,0}]) + catch error:badarg -> ok + end, - ?line try gen_sctp:open(0, [{mode,invalid_mode}]) - catch error:badarg -> ok - end, + try gen_sctp:open(0, [{mode,invalid_mode}]) + catch error:badarg -> ok + end, ok. -api_listen(doc) -> - "Test the API function listen/2"; -api_listen(suite) -> - []; +%% Test the API function listen/2. api_listen(Config) when is_list(Config) -> - ?line Localhost = {127,0,0,1}, - - ?line try gen_sctp:listen(0, true) - catch error:badarg -> ok - end, - - ?line {ok,S} = gen_sctp:open(), - ?line {ok,Pb} = inet:port(S), - ?line try gen_sctp:listen(S, not_allowed_for_listen) - catch error:badarg -> ok - end, - ?line ok = gen_sctp:close(S), - ?line {error,closed} = gen_sctp:listen(S, true), - - ?line {ok,Sb} = gen_sctp:open(Pb), - ?line {ok,Sa} = gen_sctp:open(), - ?line case gen_sctp:connect(Sa, localhost, Pb, []) of - {error,econnrefused} -> - ?line {ok,{Localhost, - Pb,[], - #sctp_assoc_change{ - state=comm_lost}}} = - gen_sctp:recv(Sa, infinity); - {error,#sctp_assoc_change{state=cant_assoc}} -> - ok%; - %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} -> - %% ok - end, - ?line ok = gen_sctp:listen(Sb, true), - ?line {ok,#sctp_assoc_change{state=comm_up, - error=0}} = + Localhost = {127,0,0,1}, + + try gen_sctp:listen(0, true) + catch error:badarg -> ok + end, + + {ok,S} = gen_sctp:open(), + {ok,Pb} = inet:port(S), + try gen_sctp:listen(S, not_allowed_for_listen) + catch error:badarg -> ok + end, + ok = gen_sctp:close(S), + {error,closed} = gen_sctp:listen(S, true), + + {ok,Sb} = gen_sctp:open(Pb), + {ok,Sa} = gen_sctp:open(), + case gen_sctp:connect(Sa, localhost, Pb, []) of + {error,econnrefused} -> + {ok,{Localhost, + Pb,[], + #sctp_assoc_change{ + state=comm_lost}}} = + gen_sctp:recv(Sa, infinity); + {error,#sctp_assoc_change{state=cant_assoc}} -> + ok%; + %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} -> + %% ok + end, + ok = gen_sctp:listen(Sb, true), + {ok,#sctp_assoc_change{state=comm_up, + error=0}} = gen_sctp:connect(Sa, localhost, Pb, []), - ?line ok = gen_sctp:close(Sa), - ?line ok = gen_sctp:close(Sb), + ok = gen_sctp:close(Sa), + ok = gen_sctp:close(Sb), ok. -api_connect_init(doc) -> - "Test the API function connect_init/4"; -api_connect_init(suite) -> - []; +%% Test the API function connect_init/4. api_connect_init(Config) when is_list(Config) -> - ?line Localhost = {127,0,0,1}, - - ?line {ok,S} = gen_sctp:open(), - ?line {ok,Pb} = inet:port(S), - ?line try gen_sctp:connect_init(S, Localhost, not_allowed_for_port, []) - catch error:badarg -> ok - end, - ?line try gen_sctp:connect_init(S, Localhost, 12345, not_allowed_for_opts) - catch error:badarg -> ok - end, - ?line ok = gen_sctp:close(S), - ?line {error,closed} = gen_sctp:connect_init(S, Localhost, 12345, []), - - ?line {ok,Sb} = gen_sctp:open(Pb), - ?line {ok,Sa} = gen_sctp:open(), - ?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of - {error,econnrefused} -> - ?line {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} = - recv_event(log_ok(gen_sctp:recv(Sa, infinity))); - ok -> - ?line {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} = - recv_event(log_ok(gen_sctp:recv(Sa, infinity))) - end, - ?line ok = gen_sctp:listen(Sb, true), - ?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of - ok -> - ?line {Localhost,Pb,#sctp_assoc_change{state=comm_up}} = - recv_event(log_ok(gen_sctp:recv(Sa, infinity))) - end, - ?line ok = gen_sctp:close(Sa), - ?line ok = gen_sctp:close(Sb), + Localhost = {127,0,0,1}, + + {ok,S} = gen_sctp:open(), + {ok,Pb} = inet:port(S), + try gen_sctp:connect_init(S, Localhost, not_allowed_for_port, []) + catch error:badarg -> ok + end, + try gen_sctp:connect_init(S, Localhost, 12345, not_allowed_for_opts) + catch error:badarg -> ok + end, + ok = gen_sctp:close(S), + {error,closed} = gen_sctp:connect_init(S, Localhost, 12345, []), + + {ok,Sb} = gen_sctp:open(Pb), + {ok,Sa} = gen_sctp:open(), + case gen_sctp:connect_init(Sa, localhost, Pb, []) of + {error,econnrefused} -> + {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} = + recv_event(log_ok(gen_sctp:recv(Sa, infinity))); + ok -> + {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} = + recv_event(log_ok(gen_sctp:recv(Sa, infinity))) + end, + ok = gen_sctp:listen(Sb, true), + case gen_sctp:connect_init(Sa, localhost, Pb, []) of + ok -> + {Localhost,Pb,#sctp_assoc_change{state=comm_up}} = + recv_event(log_ok(gen_sctp:recv(Sa, infinity))) + end, + ok = gen_sctp:close(Sa), + ok = gen_sctp:close(Sb), ok. recv_event({Addr,Port,[],#sctp_assoc_change{}=AssocChange}) -> @@ -703,94 +715,86 @@ recv_event({Addr,Port, #sctp_shutdown_event{assoc_id=Assoc}=ShutdownEvent}) -> {Addr,Port,ShutdownEvent}. -api_opts(doc) -> - "Test socket options"; -api_opts(suite) -> - []; +%% Test socket options. api_opts(Config) when is_list(Config) -> - ?line Sndbuf = 32768, - ?line Recbuf = 65536, - ?line {ok,S} = gen_sctp:open(0), - ?line OSType = os:type(), - ?line case {inet:setopts(S, [{linger,{true,2}}]),OSType} of - {ok,_} -> - ok; - {{error,einval},{unix,sunos}} -> - ok - end, - ?line ok = inet:setopts(S, [{sndbuf,Sndbuf}]), - ?line ok = inet:setopts(S, [{recbuf,Recbuf}]), - ?line case inet:getopts(S, [sndbuf]) of - {ok,[{sndbuf,SB}]} when SB >= Sndbuf -> ok - end, - ?line case inet:getopts(S, [recbuf]) of - {ok,[{recbuf,RB}]} when RB >= Recbuf -> ok - end. + Sndbuf = 32768, + Recbuf = 65536, + {ok,S} = gen_sctp:open(0), + OSType = os:type(), + case {inet:setopts(S, [{linger,{true,2}}]),OSType} of + {ok,_} -> + ok; + {{error,einval},{unix,sunos}} -> + ok + end, + ok = inet:setopts(S, [{sndbuf,Sndbuf}]), + ok = inet:setopts(S, [{recbuf,Recbuf}]), + case inet:getopts(S, [sndbuf]) of + {ok,[{sndbuf,SB}]} when SB >= Sndbuf -> ok + end, + case inet:getopts(S, [recbuf]) of + {ok,[{recbuf,RB}]} when RB >= Recbuf -> ok + end. implicit_inet6(Config) when is_list(Config) -> - ?line Hostname = log_ok(inet:gethostname()), - ?line - case gen_sctp:open(0, [inet6]) of - {ok,S1} -> - ?line - case inet:getaddr(Hostname, inet6) of - {ok,Host} -> - ?line Loopback = {0,0,0,0,0,0,0,1}, - ?line io:format("~s ~p~n", ["Loopback",Loopback]), - ?line implicit_inet6(S1, Loopback), - ?line ok = gen_sctp:close(S1), - %% - ?line Localhost = - log_ok(inet:getaddr("localhost", inet6)), - ?line io:format("~s ~p~n", ["localhost",Localhost]), - ?line S2 = - log_ok(gen_sctp:open(0, [{ip,Localhost}])), - ?line implicit_inet6(S2, Localhost), - ?line ok = gen_sctp:close(S2), - %% - ?line io:format("~s ~p~n", [Hostname,Host]), - ?line S3 = - log_ok(gen_sctp:open(0, [{ifaddr,Host}])), - ?line implicit_inet6(S3, Host), - ?line ok = gen_sctp:close(S1); - {error,eafnosupport} -> - ?line ok = gen_sctp:close(S1), - {skip,"Can not look up IPv6 address"} - end; - _ -> - {skip,"IPv6 not supported"} - end. + Hostname = log_ok(inet:gethostname()), + case gen_sctp:open(0, [inet6]) of + {ok,S1} -> + case inet:getaddr(Hostname, inet6) of + {ok,Host} -> + Loopback = {0,0,0,0,0,0,0,1}, + io:format("~s ~p~n", ["Loopback",Loopback]), + implicit_inet6(S1, Loopback), + ok = gen_sctp:close(S1), + %% + Localhost = + log_ok(inet:getaddr("localhost", inet6)), + io:format("~s ~p~n", ["localhost",Localhost]), + S2 = + log_ok(gen_sctp:open(0, [{ip,Localhost}])), + implicit_inet6(S2, Localhost), + ok = gen_sctp:close(S2), + %% + io:format("~s ~p~n", [Hostname,Host]), + S3 = + log_ok(gen_sctp:open(0, [{ifaddr,Host}])), + implicit_inet6(S3, Host), + ok = gen_sctp:close(S1); + {error,eafnosupport} -> + ok = gen_sctp:close(S1), + {skip,"Can not look up IPv6 address"} + end; + _ -> + {skip,"IPv6 not supported"} + end. implicit_inet6(S1, Addr) -> - ?line ok = gen_sctp:listen(S1, true), - ?line P1 = log_ok(inet:port(S1)), - ?line S2 = log_ok(gen_sctp:open(0, [inet6])), - ?line P2 = log_ok(inet:port(S2)), - ?line #sctp_assoc_change{state=comm_up} = + ok = gen_sctp:listen(S1, true), + P1 = log_ok(inet:port(S1)), + S2 = log_ok(gen_sctp:open(0, [inet6])), + P2 = log_ok(inet:port(S2)), + #sctp_assoc_change{state=comm_up} = log_ok(gen_sctp:connect(S2, Addr, P1, [])), - ?line case recv_event(log_ok(gen_sctp:recv(S1))) of - {Addr,P2,#sctp_assoc_change{state=comm_up}} -> - ok; - {Addr,P2,#sctp_paddr_change{state=addr_confirmed, - addr={Addr,P2}, - error=0}} -> - {Addr,P2,#sctp_assoc_change{state=comm_up}} = - recv_event(log_ok(gen_sctp:recv(S1))) - end, - ?line case log_ok(inet:sockname(S1)) of - {Addr,P1} -> ok; - {{0,0,0,0,0,0,0,0},P1} -> ok - end, - ?line case log_ok(inet:sockname(S2)) of - {Addr,P2} -> ok; - {{0,0,0,0,0,0,0,0},P2} -> ok - end, - ?line ok = gen_sctp:close(S2). - -active_n(doc) -> - "Verify {active,N} socket management"; -active_n(suite) -> - []; + case recv_event(log_ok(gen_sctp:recv(S1))) of + {Addr,P2,#sctp_assoc_change{state=comm_up}} -> + ok; + {Addr,P2,#sctp_paddr_change{state=addr_confirmed, + addr={Addr,P2}, + error=0}} -> + {Addr,P2,#sctp_assoc_change{state=comm_up}} = + recv_event(log_ok(gen_sctp:recv(S1))) + end, + case log_ok(inet:sockname(S1)) of + {Addr,P1} -> ok; + {{0,0,0,0,0,0,0,0},P1} -> ok + end, + case log_ok(inet:sockname(S2)) of + {Addr,P2} -> ok; + {{0,0,0,0,0,0,0,0},P2} -> ok + end, + ok = gen_sctp:close(S2). + +%% Verify {active,N} socket management. active_n(Config) when is_list(Config) -> N = 3, S1 = ok(gen_sctp:open([{active,N}])), @@ -887,51 +891,45 @@ active_n(Config) when is_list(Config) -> ok = gen_sctp:close(S1), ok. -basic_stream(doc) -> - "Hello world stream socket"; -basic_stream(suite) -> - []; +%% Hello world stream socket. basic_stream(Config) when is_list(Config) -> - ?line {ok,S} = gen_sctp:open([{type,stream}]), - ?line ok = gen_sctp:listen(S, true), - ?line ok = + {ok,S} = gen_sctp:open([{type,stream}]), + ok = gen_sctp:listen(S, true), + ok = do_from_other_process( fun () -> gen_sctp:listen(S, 10) end), - ?line ok = gen_sctp:close(S), + ok = gen_sctp:close(S), ok. -xfer_stream_min(doc) -> - "Minimal data transfer"; -xfer_stream_min(suite) -> - []; +%% Minimal data transfer. xfer_stream_min(Config) when is_list(Config) -> - ?line Stream = 0, - ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, - ?line Loopback = {127,0,0,1}, - ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]), - ?line ?LOGVAR(Sb), - ?line {ok,Pb} = inet:port(Sb), - ?line ?LOGVAR(Pb), - ?line ok = gen_sctp:listen(Sb, true), - - ?line {ok,Sa} = gen_sctp:open([{type,stream}]), - ?line ?LOGVAR(Sa), - ?line {ok,Pa} = inet:port(Sa), - ?line ?LOGVAR(Pa), - ?line #sctp_assoc_change{state=comm_up, - error=0, - outbound_streams=SaOutboundStreams, - inbound_streams=SaInboundStreams, - assoc_id=SaAssocId_X} = + Stream = 0, + Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, + Loopback = {127,0,0,1}, + {ok,Sb} = gen_sctp:open([{type,seqpacket}]), + ?LOGVAR(Sb), + {ok,Pb} = inet:port(Sb), + ?LOGVAR(Pb), + ok = gen_sctp:listen(Sb, true), + + {ok,Sa} = gen_sctp:open([{type,stream}]), + ?LOGVAR(Sa), + {ok,Pa} = inet:port(Sa), + ?LOGVAR(Pa), + #sctp_assoc_change{state=comm_up, + error=0, + outbound_streams=SaOutboundStreams, + inbound_streams=SaInboundStreams, + assoc_id=SaAssocId_X} = log_ok(gen_sctp:connect(Sa, Loopback, Pb, [])), - ?line ?LOGVAR(SaAssocId_X), - ?line [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] = + ?LOGVAR(SaAssocId_X), + [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] = log_ok(inet:getopts(Sa, [{sctp_get_peer_addr_info, #sctp_paddrinfo{address={Loopback,Pb}}}])), - ?line ?LOGVAR(SaAssocId), - ?line match_unless_solaris(SaAssocId_X, SaAssocId), + ?LOGVAR(SaAssocId), + match_unless_solaris(SaAssocId_X, SaAssocId), - ?line {SbOutboundStreams,SbInboundStreams,SbAssocId} = + {SbOutboundStreams,SbInboundStreams,SbAssocId} = case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of {Loopback,Pa, #sctp_assoc_change{state=comm_up, @@ -946,87 +944,87 @@ xfer_stream_min(Config) when is_list(Config) -> error=0, assoc_id=AI}} -> {Loopback,Pa, - ?line #sctp_assoc_change{state=comm_up, - error=0, - outbound_streams=OS, - inbound_streams=IS, - assoc_id=AI}} = + #sctp_assoc_change{state=comm_up, + error=0, + outbound_streams=OS, + inbound_streams=IS, + assoc_id=AI}} = recv_event(log_ok(gen_sctp:recv(Sb, infinity))), {OS,IS,AI} end, - ?line ?LOGVAR(SbAssocId), - ?line SaOutboundStreams = SbInboundStreams, - ?line ?LOGVAR(SaOutboundStreams), - ?line SbOutboundStreams = SaInboundStreams, - ?line ?LOGVAR(SbOutboundStreams), - ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data), - ?line case log_ok(gen_sctp:recv(Sb, infinity)) of - {Loopback, - Pa, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - Data} -> ok; - {Loopback, - Pa,[], - #sctp_paddr_change{addr = {Loopback,_}, - state = addr_available, - error = 0, - assoc_id = SbAssocId}} -> - {Loopback, - Pa, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - Data} = log_ok(gen_sctp:recv(Sb, infinity)); - {Loopback, - Pa, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - #sctp_paddr_change{addr = {Loopback,_}, - state = addr_confirmed, - error = 0, - assoc_id = SbAssocId}} -> - {Loopback, - Pa, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SbAssocId}], - Data} = log_ok(gen_sctp:recv(Sb, infinity)) - end, - ?line ok = + ?LOGVAR(SbAssocId), + SaOutboundStreams = SbInboundStreams, + ?LOGVAR(SaOutboundStreams), + SbOutboundStreams = SaInboundStreams, + ?LOGVAR(SbOutboundStreams), + ok = gen_sctp:send(Sa, SaAssocId, 0, Data), + case log_ok(gen_sctp:recv(Sb, infinity)) of + {Loopback, + Pa, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + Data} -> ok; + {Loopback, + Pa,[], + #sctp_paddr_change{addr = {Loopback,_}, + state = addr_available, + error = 0, + assoc_id = SbAssocId}} -> + {Loopback, + Pa, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + Data} = log_ok(gen_sctp:recv(Sb, infinity)); + {Loopback, + Pa, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + #sctp_paddr_change{addr = {Loopback,_}, + state = addr_confirmed, + error = 0, + assoc_id = SbAssocId}} -> + {Loopback, + Pa, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SbAssocId}], + Data} = log_ok(gen_sctp:recv(Sb, infinity)) + end, + ok = do_from_other_process( fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end), - ?line case log_ok(gen_sctp:recv(Sa, infinity)) of - {Loopback,Pb, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SaAssocId}], - Data} -> ok; - Event1 -> - ?line {Loopback,Pb, - #sctp_paddr_change{state=addr_confirmed, - addr={_,Pb}, - error=0, - assoc_id=SaAssocId}} = - recv_event(Event1), - ?line {Loopback,Pb, - [#sctp_sndrcvinfo{stream=Stream, - assoc_id=SaAssocId}], - Data} = - log_ok(gen_sctp:recv(Sa, infinity)) - end, - ?line ok = gen_sctp:close(Sa), - ?line {Loopback,Pa, - #sctp_shutdown_event{assoc_id=SbAssocId}} = + case log_ok(gen_sctp:recv(Sa, infinity)) of + {Loopback,Pb, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SaAssocId}], + Data} -> ok; + Event1 -> + {Loopback,Pb, + #sctp_paddr_change{state=addr_confirmed, + addr={_,Pb}, + error=0, + assoc_id=SaAssocId}} = + recv_event(Event1), + {Loopback,Pb, + [#sctp_sndrcvinfo{stream=Stream, + assoc_id=SaAssocId}], + Data} = + log_ok(gen_sctp:recv(Sa, infinity)) + end, + ok = gen_sctp:close(Sa), + {Loopback,Pa, + #sctp_shutdown_event{assoc_id=SbAssocId}} = recv_event(log_ok(gen_sctp:recv(Sb, infinity))), - ?line {Loopback,Pa, - #sctp_assoc_change{state=shutdown_comp, - error=0, - assoc_id=SbAssocId}} = + {Loopback,Pa, + #sctp_assoc_change{state=shutdown_comp, + error=0, + assoc_id=SbAssocId}} = recv_event(log_ok(gen_sctp:recv(Sb, infinity))), - ?line ok = gen_sctp:close(Sb), + ok = gen_sctp:close(Sb), - ?line receive - Msg -> test_server:fail({received,Msg}) - after 17 -> ok - end, + receive + Msg -> ct:fail({received,Msg}) + after 17 -> ok + end, ok. @@ -1058,205 +1056,186 @@ do_from_other_process(Fun) -> end. -peeloff_active_once(doc) -> - "Peel off an SCTP stream socket ({active,once})"; -peeloff_active_once(suite) -> - []; +%% Peel off an SCTP stream socket ({active,once}). peeloff_active_once(Config) -> peeloff(Config, [{active,once}]). -peeloff_active_true(doc) -> - "Peel off an SCTP stream socket ({active,true})"; -peeloff_active_true(suite) -> - []; +%% Peel off an SCTP stream socket ({active,true}). peeloff_active_true(Config) -> peeloff(Config, [{active,true}]). -peeloff_active_n(doc) -> - "Peel off an SCTP stream socket ({active,N})"; -peeloff_active_n(suite) -> - []; +%% Peel off an SCTP stream socket ({active,N}). peeloff_active_n(Config) -> peeloff(Config, [{active,1}]). peeloff(Config, SockOpts) when is_list(Config) -> - ?line Addr = {127,0,0,1}, - ?line Stream = 0, - ?line Timeout = 333, - ?line S1 = socket_open([{ifaddr,Addr}|SockOpts], Timeout), - ?line ?LOGVAR(S1), - ?line P1 = socket_call(S1, get_port), - ?line ?LOGVAR(P1), - ?line Socket1 = socket_call(S1, get_socket), - ?line ?LOGVAR(Socket1), - ?line socket_call(S1, {listen,true}), - ?line S2 = socket_open([{ifaddr,Addr}|SockOpts], Timeout), - ?line ?LOGVAR(S2), - ?line P2 = socket_call(S2, get_port), - ?line ?LOGVAR(P2), - ?line Socket2 = socket_call(S2, get_socket), - ?line ?LOGVAR(Socket2), + Addr = {127,0,0,1}, + Stream = 0, + Timeout = 333, + StartTime = timestamp(), + S1 = socket_open([{ifaddr,Addr}|SockOpts], Timeout), + ?LOGVAR(S1), + P1 = socket_call(S1, get_port), + ?LOGVAR(P1), + Socket1 = socket_call(S1, get_socket), + ?LOGVAR(Socket1), + socket_call(S1, {listen,true}), + S2 = socket_open([{ifaddr,Addr}|SockOpts], Timeout), + ?LOGVAR(S2), + P2 = socket_call(S2, get_port), + ?LOGVAR(P2), + Socket2 = socket_call(S2, get_socket), + ?LOGVAR(Socket2), %% - ?line socket_call(S2, {connect_init,Addr,P1,[]}), - ?line S2Ai = + socket_call(S2, {connect_init,Addr,P1,[]}), + S2Ai = receive {S2,{Addr,P1, #sctp_assoc_change{ - state=comm_up, - assoc_id=AssocId2}}} -> AssocId2 + state=comm_up, + assoc_id=AssocId2}}} -> AssocId2 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, - ?line ?LOGVAR(S2Ai), - ?line S1Ai = + ?LOGVAR(S2Ai), + S1Ai = receive {S1,{Addr,P2, #sctp_assoc_change{ - state=comm_up, - assoc_id=AssocId1}}} -> AssocId1 + state=comm_up, + assoc_id=AssocId1}}} -> AssocId1 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, - ?line ?LOGVAR(S1Ai), + ?LOGVAR(S1Ai), %% - ?line socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}), - ?line - receive - {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok - after Timeout -> - socket_bailout([S1,S2]) - end, - ?line socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}), - ?line - receive - {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok - after Timeout -> - socket_bailout([S1,S2]) - end, + socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}), + receive + {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok + after Timeout -> + socket_bailout([S1,S2], StartTime) + end, + socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}), + receive + {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok + after Timeout -> + socket_bailout([S1,S2], StartTime) + end, %% - ?line S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout), - ?line ?LOGVAR(S3), - ?line P3_X = socket_call(S3, get_port), - ?line ?LOGVAR(P3_X), - ?line P3 = case P3_X of 0 -> P1; _ -> P3_X end, - ?line [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] = + S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout), + ?LOGVAR(S3), + P3_X = socket_call(S3, get_port), + ?LOGVAR(P3_X), + P3 = case P3_X of 0 -> P1; _ -> P3_X end, + [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] = socket_call(S3, {getopts,[{sctp_get_peer_addr_info, #sctp_paddrinfo{address={Addr,P2}}}]}), - %%?line S3Ai = S1Ai, - ?line ?LOGVAR(S3Ai), + %%S3Ai = S1Ai, + ?LOGVAR(S3Ai), %% - ?line socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}), - ?line - receive - {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok - after Timeout -> - socket_bailout([S1,S2,S3]) - end, - ?line socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}), - ?line - receive - {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok - after Timeout -> - socket_bailout([S1,S2,S3]) - end, + socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}), + receive + {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok + after Timeout -> + socket_bailout([S1,S2,S3], StartTime) + end, + socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}), + receive + {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok + after Timeout -> + socket_bailout([S1,S2,S3], StartTime) + end, %% - ?line inet:i(sctp), - ?line socket_close_verbose(S1), - ?line socket_close_verbose(S2), - ?line - receive - {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} -> - ?line match_unless_solaris(S3Ai, S3Ai_X) - after Timeout -> - socket_bailout([S3]) - end, - ?line - receive - {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp, - assoc_id=S3Ai}}} -> ok - after Timeout -> - socket_bailout([S3]) - end, - ?line socket_close_verbose(S3), - ?line [] = flush(), + inet:i(sctp), + socket_close_verbose(S1, StartTime), + socket_close_verbose(S2, StartTime), + receive + {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} -> + match_unless_solaris(S3Ai, S3Ai_X) + after Timeout -> + socket_bailout([S3], StartTime) + end, + receive + {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp, + assoc_id=S3Ai}}} -> ok + after Timeout -> + socket_bailout([S3], StartTime) + end, + socket_close_verbose(S3, StartTime), + [] = flush(), ok. -buffers(doc) -> - ["Check sndbuf and recbuf behaviour"]; -buffers(suite) -> - []; +%% Check sndbuf and recbuf behaviour. buffers(Config) when is_list(Config) -> - ?line Limit = 4096, - ?line Addr = {127,0,0,1}, - ?line Stream = 1, - ?line Timeout = 3333, - ?line S1 = socket_open([{ip,Addr}], Timeout), - ?line ?LOGVAR(S1), - ?line P1 = socket_call(S1, get_port), - ?line ?LOGVAR(P1), - ?line ok = socket_call(S1, {listen,true}), - ?line S2 = socket_open([{ip,Addr}], Timeout), - ?line ?LOGVAR(S2), - ?line P2 = socket_call(S2, get_port), - ?line ?LOGVAR(P2), + Limit = 4096, + Addr = {127,0,0,1}, + Stream = 1, + Timeout = 3333, + StartTime = timestamp(), + S1 = socket_open([{ip,Addr}], Timeout), + ?LOGVAR(S1), + P1 = socket_call(S1, get_port), + ?LOGVAR(P1), + ok = socket_call(S1, {listen,true}), + S2 = socket_open([{ip,Addr}], Timeout), + ?LOGVAR(S2), + P2 = socket_call(S2, get_port), + ?LOGVAR(P2), %% - ?line socket_call(S2, {connect_init,Addr,P1,[]}), - ?line S2Ai = + socket_call(S2, {connect_init,Addr,P1,[]}), + S2Ai = receive {S2,{Addr,P1, #sctp_assoc_change{ - state=comm_up, - assoc_id=AssocId2}}} -> AssocId2 + state=comm_up, + assoc_id=AssocId2}}} -> AssocId2 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, - ?line S1Ai = + S1Ai = receive {S1,{Addr,P2, #sctp_assoc_change{ - state=comm_up, - assoc_id=AssocId1}}} -> AssocId1 + state=comm_up, + assoc_id=AssocId1}}} -> AssocId1 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, %% - ?line socket_call(S1, {setopts,[{recbuf,Limit}]}), - ?line Recbuf = + socket_call(S1, {setopts,[{recbuf,Limit}]}), + Recbuf = case socket_call(S1, {getopts,[recbuf]}) of [{recbuf,RB1}] when RB1 >= Limit -> RB1 end, - ?line Data = mk_data(Recbuf+Limit), - ?line socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}), - ?line socket_call(S2, {send,S2Ai,Stream,Data}), - ?line - receive - {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok - after Timeout -> - socket_bailout([S1,S2]) - end, + Data = mk_data(Recbuf+Limit), + socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}), + socket_call(S2, {send,S2Ai,Stream,Data}), + receive + {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok + after Timeout -> + socket_bailout([S1,S2], StartTime) + end, %% - ?line socket_close_verbose(S1), - ?line - receive - {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok - after Timeout -> - socket_bailout([S2]) - end, - ?line - receive - {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp, - assoc_id=S2Ai}}} -> ok - after Timeout -> - socket_bailout([S2]) - end, - ?line socket_close_verbose(S2), - ?line [] = flush(), + socket_close_verbose(S1, StartTime), + receive + {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok + after Timeout -> + socket_bailout([S2], StartTime) + end, + receive + {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp, + assoc_id=S2Ai}}} -> ok + after Timeout -> + socket_bailout([S2], StartTime) + end, + socket_close_verbose(S2, StartTime), + [] = flush(), ok. mk_data(Bytes) -> @@ -1269,153 +1248,129 @@ mk_data(_, _, Bin) -> -open_multihoming_ipv4_socket(doc) -> - "Test opening a multihoming ipv4 socket"; -open_multihoming_ipv4_socket(suite) -> - []; +%% Test opening a multihoming ipv4 socket. open_multihoming_ipv4_socket(Config) when is_list(Config) -> - ?line case get_addrs_by_family(inet, 2) of - {ok, [Addr1, Addr2]} -> - ?line do_open_and_connect([Addr1, Addr2], Addr1); - {error, Reason} -> - {skip, Reason} - end. - -open_unihoming_ipv6_socket(doc) -> - %% This test is mostly aimed to indicate - %% whether host has a non-working ipv6 setup - "Test opening a unihoming (non-multihoming) ipv6 socket"; -open_unihoming_ipv6_socket(suite) -> - []; + case get_addrs_by_family(inet, 2) of + {ok, [Addr1, Addr2]} -> + do_open_and_connect([Addr1, Addr2], Addr1); + {error, Reason} -> + {skip, Reason} + end. + +%% This test is mostly aimed to indicate whether host has a +%% non-working ipv6 setup. Test opening a unihoming (non-multihoming) +%% ipv6 socket. open_unihoming_ipv6_socket(Config) when is_list(Config) -> - ?line case get_addrs_by_family(inet6, 1) of - {ok, [Addr]} -> - ?line do_open_and_connect([Addr], Addr); - {error, Reason} -> - {skip, Reason} - end. + case get_addrs_by_family(inet6, 1) of + {ok, [Addr]} -> + do_open_and_connect([Addr], Addr); + {error, Reason} -> + {skip, Reason} + end. -open_multihoming_ipv6_socket(doc) -> - "Test opening a multihoming ipv6 socket"; -open_multihoming_ipv6_socket(suite) -> - []; +%% Test opening a multihoming ipv6 socket. open_multihoming_ipv6_socket(Config) when is_list(Config) -> - ?line case get_addrs_by_family(inet6, 2) of - {ok, [Addr1, Addr2]} -> - ?line do_open_and_connect([Addr1, Addr2], Addr1); - {error, Reason} -> - {skip, Reason} - end. - -open_multihoming_ipv4_and_ipv6_socket(doc) -> - "Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses"; -open_multihoming_ipv4_and_ipv6_socket(suite) -> - []; + case get_addrs_by_family(inet6, 2) of + {ok, [Addr1, Addr2]} -> + do_open_and_connect([Addr1, Addr2], Addr1); + {error, Reason} -> + {skip, Reason} + end. + +%% Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses. open_multihoming_ipv4_and_ipv6_socket(Config) when is_list(Config) -> - ?line case get_addrs_by_family(inet_and_inet6, 2) of - {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} -> - %% Connect to the first address to test bind - ?line do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2], - InetAddr1), - ?line do_open_and_connect([Inet6Addr1, InetAddr1], - Inet6Addr1), - - %% Connect an address, not the first, - %% to test sctp_bindx - ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], - Inet6Addr2), - ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], - InetAddr1); - {error, Reason} -> - {skip, Reason} - end. - -names_unihoming_ipv4(doc) -> - "Test inet:socknames/peernames on unihoming IPv4 sockets"; -names_unihoming_ipv4(suite) -> - []; + case get_addrs_by_family(inet_and_inet6, 2) of + {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} -> + %% Connect to the first address to test bind + do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2], + InetAddr1), + do_open_and_connect([Inet6Addr1, InetAddr1], + Inet6Addr1), + + %% Connect an address, not the first, + %% to test sctp_bindx + do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], + Inet6Addr2), + do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], + InetAddr1); + {error, Reason} -> + {skip, Reason} + end. + +%% Test inet:socknames/peernames on unihoming IPv4 sockets. names_unihoming_ipv4(Config) when is_list(Config) -> - ?line do_names(Config, inet, 1). + do_names(Config, inet, 1). -names_unihoming_ipv6(doc) -> - "Test inet:socknames/peernames on unihoming IPv6 sockets"; -names_unihoming_ipv6(suite) -> - []; +%% Test inet:socknames/peernames on unihoming IPv6 sockets. names_unihoming_ipv6(Config) when is_list(Config) -> - ?line do_names(Config, inet6, 1). + do_names(Config, inet6, 1). -names_multihoming_ipv4(doc) -> - "Test inet:socknames/peernames on multihoming IPv4 sockets"; -names_multihoming_ipv4(suite) -> - []; +%% Test inet:socknames/peernames on multihoming IPv4 sockets. names_multihoming_ipv4(Config) when is_list(Config) -> - ?line do_names(Config, inet, 2). + do_names(Config, inet, 2). -names_multihoming_ipv6(doc) -> - "Test inet:socknames/peernames on multihoming IPv6 sockets"; -names_multihoming_ipv6(suite) -> - []; +%% Test inet:socknames/peernames on multihoming IPv6 sockets. names_multihoming_ipv6(Config) when is_list(Config) -> - ?line do_names(Config, inet6, 2). + do_names(Config, inet6, 2). do_names(_, FamilySpec, AddressCount) -> Fun = fun (ServerSocket, _, ServerAssoc, ClientSocket, _, ClientAssoc) -> - ?line ServerSocknamesNoassoc = + ServerSocknamesNoassoc = lists:sort(ok(inet:socknames(ServerSocket))), - ?line ?LOGVAR(ServerSocknamesNoassoc), - ?line ServerSocknames = + ?LOGVAR(ServerSocknamesNoassoc), + ServerSocknames = lists:sort(ok(inet:socknames(ServerSocket, ServerAssoc))), - ?line ?LOGVAR(ServerSocknames), - ?line [_|_] = + ?LOGVAR(ServerSocknames), + [_|_] = ordsets:intersection (ServerSocknamesNoassoc, ServerSocknames), - ?line ClientSocknamesNoassoc = + ClientSocknamesNoassoc = lists:sort(ok(inet:socknames(ClientSocket))), - ?line ?LOGVAR(ClientSocknamesNoassoc), - ?line ClientSocknames = + ?LOGVAR(ClientSocknamesNoassoc), + ClientSocknames = lists:sort(ok(inet:socknames(ClientSocket, ClientAssoc))), - ?line ?LOGVAR(ClientSocknames), - ?line [_|_] = + ?LOGVAR(ClientSocknames), + [_|_] = ordsets:intersection (ClientSocknamesNoassoc, ClientSocknames), - ?line err([einval,enotconn], inet:peernames(ServerSocket)), - ?line ServerPeernames = + err([einval,enotconn], inet:peernames(ServerSocket)), + ServerPeernames = lists:sort(ok(inet:peernames(ServerSocket, ServerAssoc))), - ?line ?LOGVAR(ServerPeernames), - ?line err([einval,enotconn], inet:peernames(ClientSocket)), - ?line ClientPeernames = + ?LOGVAR(ServerPeernames), + err([einval,enotconn], inet:peernames(ClientSocket)), + ClientPeernames = lists:sort(ok(inet:peernames(ClientSocket, ClientAssoc))), - ?line ?LOGVAR(ClientPeernames), - ?line ServerSocknames = ClientPeernames, - ?line ClientSocknames = ServerPeernames, - ?line {ok,Socket} = + ?LOGVAR(ClientPeernames), + ServerSocknames = ClientPeernames, + ClientSocknames = ServerPeernames, + {ok,Socket} = gen_sctp:peeloff(ServerSocket, ServerAssoc), - ?line SocknamesNoassoc = + SocknamesNoassoc = lists:sort(ok(inet:socknames(Socket))), - ?line ?LOGVAR(SocknamesNoassoc), - ?line Socknames = + ?LOGVAR(SocknamesNoassoc), + Socknames = lists:sort(ok(inet:socknames(Socket, ServerAssoc))), - ?line ?LOGVAR(Socknames), - ?line true = + ?LOGVAR(Socknames), + true = ordsets:is_subset(SocknamesNoassoc, Socknames), - ?line Peernames = + Peernames = lists:sort(ok(inet:peernames(Socket, ServerAssoc))), - ?line ?LOGVAR(Peernames), - ?line ok = gen_sctp:close(Socket), - ?line Socknames = ClientPeernames, - ?line ClientSocknames = Peernames, + ?LOGVAR(Peernames), + ok = gen_sctp:close(Socket), + Socknames = ClientPeernames, + ClientSocknames = Peernames, ok end, - ?line case get_addrs_by_family(FamilySpec, AddressCount) of - {ok, Addresses} when length(Addresses) =:= AddressCount -> - ?line do_open_and_connect(Addresses, hd(Addresses), Fun); - {error, Reason} -> - {skip, Reason} - end. + case get_addrs_by_family(FamilySpec, AddressCount) of + {ok, Addresses} when length(Addresses) =:= AddressCount -> + do_open_and_connect(Addresses, hd(Addresses), Fun); + {error, Reason} -> + {skip, Reason} + end. @@ -1451,29 +1406,28 @@ get_addrs_by_family(Family, NumAddrs) -> get_addrs_by_family_aux(Family, NumAddrs) when Family =:= inet; Family =:= inet6 -> - ?line - case inet:getaddr(localhost, Family) of - {error,eafnosupport} -> - {skip, f("No support for ~p", Family)}; - {ok, _} -> - ?line IfAddrs = ok(inet:getifaddrs()), - ?line case filter_addrs_by_family(IfAddrs, Family) of - Addrs when length(Addrs) >= NumAddrs -> - {ok, lists:sublist(Addrs, NumAddrs)}; - [] -> - {error, f("Need ~p ~p address(es) found none~n", - [NumAddrs, Family])}; - Addrs -> - {error, - f("Need ~p ~p address(es) found only ~p: ~p~n", - [NumAddrs, Family, length(Addrs), Addrs])} - end - end; + case inet:getaddr(localhost, Family) of + {error,eafnosupport} -> + {skip, f("No support for ~p", Family)}; + {ok, _} -> + IfAddrs = ok(inet:getifaddrs()), + case filter_addrs_by_family(IfAddrs, Family) of + Addrs when length(Addrs) >= NumAddrs -> + {ok, lists:sublist(Addrs, NumAddrs)}; + [] -> + {error, f("Need ~p ~p address(es) found none~n", + [NumAddrs, Family])}; + Addrs -> + {error, + f("Need ~p ~p address(es) found only ~p: ~p~n", + [NumAddrs, Family, length(Addrs), Addrs])} + end + end; get_addrs_by_family_aux(inet_and_inet6, NumAddrs) -> - ?line catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of - {ok, Addrs} -> Addrs; - {error, Reason} -> throw({error, Reason}) - end || Family <- [inet, inet6]]}. + catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of + {ok, Addrs} -> Addrs; + {error, Reason} -> throw({error, Reason}) + end || Family <- [inet, inet6]]}. filter_addrs_by_family(IfAddrs, Family) -> lists:flatten([[Addr || {addr, Addr} <- Info, @@ -1502,21 +1456,21 @@ f(F, A) -> lists:flatten(io_lib:format(F, A)). do_open_and_connect(ServerAddresses, AddressToConnectTo) -> - ?line Fun = fun (_, _, _, _, _, _) -> ok end, - ?line do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun). + Fun = fun (_, _, _, _, _, _) -> ok end, + do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun). %% do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun) -> - ?line ServerFamily = get_family_by_addrs(ServerAddresses), - ?line io:format("Serving ~p addresses: ~p~n", - [ServerFamily, ServerAddresses]), - ?line S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++ - [ServerFamily])), - ?line ok = gen_sctp:listen(S1, true), - ?line P1 = ok(inet:port(S1)), - ?line ClientFamily = get_family_by_addr(AddressToConnectTo), - ?line io:format("Connecting to ~p ~p~n", - [ClientFamily, AddressToConnectTo]), - ?line ClientOpts = + ServerFamily = get_family_by_addrs(ServerAddresses), + io:format("Serving ~p addresses: ~p~n", + [ServerFamily, ServerAddresses]), + S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++ + [ServerFamily])), + ok = gen_sctp:listen(S1, true), + P1 = ok(inet:port(S1)), + ClientFamily = get_family_by_addr(AddressToConnectTo), + io:format("Connecting to ~p ~p~n", + [ClientFamily, AddressToConnectTo]), + ClientOpts = [ClientFamily | case ClientFamily of inet6 -> @@ -1524,39 +1478,39 @@ do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun) -> _ -> [] end], - ?line S2 = ok(gen_sctp:open(0, ClientOpts)), + S2 = ok(gen_sctp:open(0, ClientOpts)), log(open), %% Verify client can connect - ?line #sctp_assoc_change{state=comm_up} = S2Assoc = + #sctp_assoc_change{state=comm_up} = S2Assoc = ok(gen_sctp:connect(S2, AddressToConnectTo, P1, [])), log(comm_up), %% verify server side also receives comm_up from client - ?line S1Assoc = recv_comm_up_eventually(S1), - ?line Result = Fun(S1, ServerFamily, S1Assoc, S2, ClientFamily, S2Assoc), - ?line ok = gen_sctp:close(S2), - ?line ok = gen_sctp:close(S1), + S1Assoc = recv_comm_up_eventually(S1), + Result = Fun(S1, ServerFamily, S1Assoc, S2, ClientFamily, S2Assoc), + ok = gen_sctp:close(S2), + ok = gen_sctp:close(S1), Result. %% If at least one of the addresses is an ipv6 address, return inet6, else inet. get_family_by_addrs(Addresses) -> - ?line case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of - [inet, inet6] -> inet6; - [inet] -> inet; - [inet6] -> inet6 - end. + case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of + [inet, inet6] -> inet6; + [inet] -> inet; + [inet6] -> inet6 + end. get_family_by_addr(Addr) when tuple_size(Addr) =:= 4 -> inet; get_family_by_addr(Addr) when tuple_size(Addr) =:= 8 -> inet6. recv_comm_up_eventually(S) -> - ?line case ok(gen_sctp:recv(S)) of - {_Addr, _Port, _Info, - #sctp_assoc_change{state=comm_up} = Assoc} -> - Assoc; - {_Addr, _Port, _Info, _OtherSctpMsg} = Msg -> - ?line log({unexpected,Msg}), - ?line recv_comm_up_eventually(S) - end. + case ok(gen_sctp:recv(S)) of + {_Addr, _Port, _Info, + #sctp_assoc_change{state=comm_up} = Assoc} -> + Assoc; + {_Addr, _Port, _Info, _OtherSctpMsg} = Msg -> + log({unexpected,Msg}), + recv_comm_up_eventually(S) + end. %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% socket gen_server ultra light @@ -1589,8 +1543,8 @@ socket_peeloff(Socket, AssocId, SocketOpts, Timeout) -> end, s_start(Starter, Timeout). -socket_close_verbose(S) -> - History = socket_history(socket_close(S)), +socket_close_verbose(S, StartTime) -> + History = socket_history(socket_close(S), StartTime), io:format("socket_close ~p:~n ~p.~n", [S,History]), History. @@ -1603,19 +1557,19 @@ socket_call(S, Request) -> %% socket_get(S, Key) -> %% s_req(S, {get,Key}). -socket_bailout([S|Ss]) -> - History = socket_history(socket_close(S)), +socket_bailout([S|Ss], StartTime) -> + History = socket_history(socket_close(S), StartTime), io:format("bailout ~p:~n ~p.~n", [S,History]), - socket_bailout(Ss); -socket_bailout([]) -> + socket_bailout(Ss, StartTime); +socket_bailout([], _) -> io:format("flush: ~p.~n", [flush()]), - test_server:fail(socket_bailout). + ct:fail(socket_bailout). -socket_history({State,Flush}) -> +socket_history({State,Flush}, StartTime) -> {lists:keysort( 2, lists:flatten( - [[{Key,Val} || Val <- Vals] + [[{Key,{TS-StartTime,Val}} || {TS,Val} <- Vals] || {Key,Vals} <- gb_trees:to_list(State)])), Flush}. @@ -1678,14 +1632,12 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> {Parent,Ref,exit} -> ok = gen_sctp:close(Socket), Key = exit, - Val = {now(),Socket}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, Socket, State), Parent ! {self(),Ref,{NewState,flush()}}; {Parent,Ref,{Msg}} -> Result = Handler(Msg), Key = req, - Val = {now(),{Msg,Result}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Msg,Result}, State), Parent ! {self(),Ref,Result}, s_loop(Socket, Timeout, Parent, Handler, NewState); %% {Parent,Ref,{get,Key}} -> @@ -1695,16 +1647,15 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> {[#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}=SRI],Data}} when not is_tuple(Data) -> case gb_get({assoc_change,AssocId}, State) of - [{_,{Addr,Port, - #sctp_assoc_change{ - state=comm_up, - inbound_streams=Is}}}|_] + [{Addr,Port, + #sctp_assoc_change{ + state=comm_up, + inbound_streams=Is}}|_] when 0 =< Stream, Stream < Is-> ok; [] -> ok end, Key = {msg,AssocId,Stream}, - Val = {now(),{Addr,Port,SRI,Data}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port,SRI,Data}, State), Parent ! {self(),{Addr,Port,AssocId,Stream,Data}}, again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); @@ -1715,13 +1666,12 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> [] -> ok end, Key = {assoc_change,AssocId}, - Val = {now(),{Addr,Port,SAC}}, case {gb_get(Key, State),St} of {[],_} -> ok; - {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_} + {[{Addr,Port,#sctp_assoc_change{state=comm_up}}|_],_} when St =:= comm_lost; St =:= shutdown_comp -> ok end, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port,SAC}, State), Parent ! {self(),{Addr,Port,SAC}}, again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); @@ -1735,14 +1685,13 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> [] -> ok end, case {gb_get({assoc_change,AssocId}, State),St} of - {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_} + {[{Addr,Port,#sctp_assoc_change{state=comm_up}}|_],_} when St =:= addr_available; St =:= addr_confirmed -> ok; {[],addr_confirmed} -> ok end, Key = {paddr_change,AssocId}, - Val = {now(),{Addr,Port,SPC}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port,SPC}, State), again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); {sctp,Socket,Addr,Port, @@ -1752,12 +1701,11 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> [] -> ok end, case gb_get({assoc_change,AssocId}, State) of - [{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_] -> ok; + [{Addr,Port,#sctp_assoc_change{state=comm_up}}|_] -> ok; [] -> ok end, Key = {shutdown_event,AssocId}, - Val = {now(),{Addr,Port}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port}, State), Parent ! {self(), {Addr,Port,SSE}}, again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); @@ -1775,11 +1723,12 @@ again(Socket) -> end. gb_push(Key, Val, GBT) -> + TS = timestamp(), case gb_trees:lookup(Key, GBT) of none -> - gb_trees:insert(Key, [Val], GBT); + gb_trees:insert(Key, [{TS,Val}], GBT); {value,V} -> - gb_trees:update(Key, [Val|V], GBT) + gb_trees:update(Key, [{TS,Val}|V], GBT) end. gb_get(Key, GBT) -> @@ -1787,7 +1736,7 @@ gb_get(Key, GBT) -> none -> []; {value,V} -> - V + [Val || {_TS,Val} <- V] end. match_unless_solaris(A, B) -> @@ -1795,3 +1744,6 @@ match_unless_solaris(A, B) -> {unix,sunos} -> B; _ -> A = B end. + +timestamp() -> + erlang:monotonic_time(). diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index a051d504b2..12d22519ce 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. 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. @@ -31,24 +31,37 @@ init_per_testcase/2, end_per_testcase/2, t_connect_timeout/1, t_accept_timeout/1, t_connect_bad/1, - t_recv_timeout/1, t_recv_eof/1, + t_recv_timeout/1, t_recv_eof/1, t_recv_delim/1, t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1, t_shutdown_async/1, - t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1]). + t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1, + t_local_basic/1, t_local_unbound/1, t_local_fdopen/1, + t_local_fdopen_listen/1, t_local_fdopen_listen_unbound/1, + t_local_fdopen_connect/1, t_local_fdopen_connect_unbound/1, + t_local_abstract/1, t_accept_inet6_tclass/1]). -export([getsockfd/0,closesockfd/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [{group, t_accept}, {group, t_connect}, {group, t_recv}, t_shutdown_write, t_shutdown_both, t_shutdown_error, - t_shutdown_async, t_fdopen, t_fdconnect, t_implicit_inet6]. + t_shutdown_async, t_fdopen, t_fdconnect, t_implicit_inet6, + t_accept_inet6_tclass, + {group, t_local}]. groups() -> [{t_accept, [], [t_accept_timeout]}, {t_connect, [], [t_connect_timeout, t_connect_bad]}, - {t_recv, [], [t_recv_timeout, t_recv_eof]}]. + {t_recv, [], [t_recv_timeout, t_recv_eof, t_recv_delim]}, + {t_local, [], + [t_local_basic, t_local_unbound, t_local_fdopen, + t_local_fdopen_listen, t_local_fdopen_listen_unbound, + t_local_fdopen_connect, t_local_fdopen_connect_unbound, + t_local_abstract]}]. @@ -58,172 +71,199 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ok. +init_per_group(t_local, Config) -> + case gen_tcp:connect({local,<<"/">>}, 0, []) of + {error,eafnosupport} -> + {skip, "AF_LOCAL not supported"}; + {error,_} -> + Config + end; init_per_group(_GroupName, Config) -> Config. -end_per_group(_,_Config) -> +end_per_group(t_local, _Config) -> + delete_local_filenames(); +end_per_group(_, _Config) -> ok. + +init_per_testcase(Func, Config) + when Func =:= undefined -> % Insert your testcase name here + dbg:tracer(), + dbg:p(self(), c), + dbg:tpl(prim_inet, cx), + dbg:tpl(local_tcp, cx), + dbg:tpl(inet, cx), + dbg:tpl(gen_tcp, cx), + Config; init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(60)), - [{watchdog, Dog}|Config]. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). + Config. + +end_per_testcase(_Func, _Config) -> + dbg:stop(). %%% gen_tcp:accept/1,2 -t_accept_timeout(doc) -> "Test that gen_tcp:accept/2 (with timeout) works."; -t_accept_timeout(suite) -> []; +%% Test that gen_tcp:accept/2 (with timeout) works. t_accept_timeout(Config) when is_list(Config) -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line timeout({gen_tcp, accept, [L, 200]}, 0.2, 1.0). + {ok, L} = gen_tcp:listen(0, []), + timeout({gen_tcp, accept, [L, 200]}, 0.2, 1.0). %%% gen_tcp:connect/X -t_connect_timeout(doc) -> "Test that gen_tcp:connect/4 (with timeout) works."; +%% Test that gen_tcp:connect/4 (with timeout) works. t_connect_timeout(Config) when is_list(Config) -> - %%?line BadAddr = {134,138,177,16}, - %%?line TcpPort = 80, - ?line {ok, BadAddr} = unused_ip(), - ?line TcpPort = 45638, - ?line ok = io:format("Connecting to ~p, port ~p", [BadAddr, TcpPort]), - ?line connect_timeout({gen_tcp,connect,[BadAddr,TcpPort,[],200]}, 0.2, 5.0). - -t_connect_bad(doc) -> - ["Test that gen_tcp:connect/3 handles non-existings hosts, and other ", - "invalid things."]; -t_connect_bad(suite) -> []; + %%BadAddr = {134,138,177,16}, + %%TcpPort = 80, + {ok, BadAddr} = unused_ip(), + TcpPort = 45638, + ok = io:format("Connecting to ~p, port ~p", [BadAddr, TcpPort]), + connect_timeout({gen_tcp,connect,[BadAddr,TcpPort,[],200]}, 0.2, 5.0). + +%% Test that gen_tcp:connect/3 handles non-existings hosts, and other +%% invalid things. t_connect_bad(Config) when is_list(Config) -> - ?line NonExistingPort = 45638, % Not in use, I hope. - ?line {error, Reason1} = gen_tcp:connect(localhost, NonExistingPort, []), - ?line io:format("Error for connection attempt to port not in use: ~p", - [Reason1]), - - ?line {error, Reason2} = gen_tcp:connect("non-existing-host-xxx", 7, []), - ?line io:format("Error for connection attempt to non-existing host: ~p", - [Reason2]), + NonExistingPort = 45638, % Not in use, I hope. + {error, Reason1} = gen_tcp:connect(localhost, NonExistingPort, []), + io:format("Error for connection attempt to port not in use: ~p", + [Reason1]), + + {error, Reason2} = gen_tcp:connect("non-existing-host-xxx", 7, []), + io:format("Error for connection attempt to non-existing host: ~p", + [Reason2]), ok. %%% gen_tcp:recv/X -t_recv_timeout(doc) -> "Test that gen_tcp:recv/3 (with timeout works)."; -t_recv_timeout(suite) -> []; +%% Test that gen_tcp:recv/3 (with timeout works). t_recv_timeout(Config) when is_list(Config) -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line {ok, Port} = inet:port(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), - ?line {ok, _A} = gen_tcp:accept(L), - ?line timeout({gen_tcp, recv, [Client, 0, 200]}, 0.2, 5.0). - -t_recv_eof(doc) -> "Test that end of file on a socket is reported correctly."; -t_recv_eof(suite) -> []; + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), + {ok, _A} = gen_tcp:accept(L), + timeout({gen_tcp, recv, [Client, 0, 200]}, 0.2, 5.0). + +%% Test that end of file on a socket is reported correctly. t_recv_eof(Config) when is_list(Config) -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line {ok, Port} = inet:port(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), - ?line {ok, A} = gen_tcp:accept(L), - ?line ok = gen_tcp:close(A), - ?line {error, closed} = gen_tcp:recv(Client, 0), + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:close(A), + {error, closed} = gen_tcp:recv(Client, 0), + ok. + +%% Test using message delimiter $X. +t_recv_delim(Config) when is_list(Config) -> + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + Opts = [{active,false},{packet,line},{line_delimiter,$X}], + {ok, Client} = gen_tcp:connect(localhost, Port, Opts), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:send(A, "abcXefgX"), + {ok, "abcX"} = gen_tcp:recv(Client, 0, 200), + {ok, "efgX"} = gen_tcp:recv(Client, 0, 200), + ok = gen_tcp:close(Client), + ok = gen_tcp:close(A), ok. %%% gen_tcp:shutdown/2 t_shutdown_write(Config) when is_list(Config) -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line {ok, Port} = inet:port(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), - ?line {ok, A} = gen_tcp:accept(L), - ?line ok = gen_tcp:shutdown(A, write), - ?line {error, closed} = gen_tcp:recv(Client, 0), + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:shutdown(A, write), + {error, closed} = gen_tcp:recv(Client, 0), ok. t_shutdown_both(Config) when is_list(Config) -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line {ok, Port} = inet:port(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), - ?line {ok, A} = gen_tcp:accept(L), - ?line ok = gen_tcp:shutdown(A, read_write), - ?line {error, closed} = gen_tcp:recv(Client, 0), + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:shutdown(A, read_write), + {error, closed} = gen_tcp:recv(Client, 0), ok. t_shutdown_error(Config) when is_list(Config) -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line {error, enotconn} = gen_tcp:shutdown(L, read_write), - ?line ok = gen_tcp:close(L), - ?line {error, closed} = gen_tcp:shutdown(L, read_write), + {ok, L} = gen_tcp:listen(0, []), + {error, enotconn} = gen_tcp:shutdown(L, read_write), + ok = gen_tcp:close(L), + {error, closed} = gen_tcp:shutdown(L, read_write), ok. t_shutdown_async(Config) when is_list(Config) -> - ?line {OS, _} = os:type(), - ?line {ok, L} = gen_tcp:listen(0, [{sndbuf, 4096}]), - ?line {ok, Port} = inet:port(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, - [{recbuf, 4096}, - {active, false}]), - ?line {ok, S} = gen_tcp:accept(L), - ?line PayloadSize = 1024 * 1024, - ?line Payload = lists:duplicate(PayloadSize, $.), - ?line ok = gen_tcp:send(S, Payload), - ?line case erlang:port_info(S, queue_size) of - {queue_size, N} when N > 0 -> ok; - {queue_size, 0} when OS =:= win32 -> ok; - {queue_size, 0} = T -> ?t:fail({unexpected, T}) - end, - - ?line ok = gen_tcp:shutdown(S, write), - ?line {ok, Buf} = gen_tcp:recv(Client, PayloadSize), - ?line {error, closed} = gen_tcp:recv(Client, 0), - ?line case length(Buf) of - PayloadSize -> ok; - Sz -> ?t:fail({payload_size, - {expected, PayloadSize}, - {received, Sz}}) - end. + {OS, _} = os:type(), + {ok, L} = gen_tcp:listen(0, [{sndbuf, 4096}]), + {ok, Port} = inet:port(L), + {ok, Client} = gen_tcp:connect(localhost, Port, + [{recbuf, 4096}, + {active, false}]), + {ok, S} = gen_tcp:accept(L), + PayloadSize = 1024 * 1024, + Payload = lists:duplicate(PayloadSize, $.), + ok = gen_tcp:send(S, Payload), + case erlang:port_info(S, queue_size) of + {queue_size, N} when N > 0 -> ok; + {queue_size, 0} when OS =:= win32 -> ok; + {queue_size, 0} = T -> ct:fail({unexpected, T}) + end, + + ok = gen_tcp:shutdown(S, write), + {ok, Buf} = gen_tcp:recv(Client, PayloadSize), + {error, closed} = gen_tcp:recv(Client, 0), + case length(Buf) of + PayloadSize -> ok; + Sz -> ct:fail({payload_size, + {expected, PayloadSize}, + {received, Sz}}) + end. %%% gen_tcp:fdopen/2 t_fdopen(Config) when is_list(Config) -> - ?line Question = "Aaaa... Long time ago in a small town in Germany,", - ?line Question1 = list_to_binary(Question), - ?line Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ", - ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]], - ?line Question1 = iolist_to_binary(Question2), - ?line Answer = "there was a shoemaker, Schumacher was his name.", - ?line {ok, L} = gen_tcp:listen(0, [{active, false}]), - ?line {ok, Port} = inet:port(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), - ?line {ok, A} = gen_tcp:accept(L), - ?line {ok, FD} = prim_inet:getfd(A), - ?line {ok, Server} = gen_tcp:fdopen(FD, []), - ?line ok = gen_tcp:send(Client, Question), - ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), - ?line ok = gen_tcp:send(Client, Question1), - ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), - ?line ok = gen_tcp:send(Client, Question2), - ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), - ?line ok = gen_tcp:send(Server, Answer), - ?line {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000), - ?line ok = gen_tcp:close(Client), - ?line {error,closed} = gen_tcp:recv(A, 1, 2000), - ?line ok = gen_tcp:close(Server), - ?line ok = gen_tcp:close(A), - ?line ok = gen_tcp:close(L), + Question = "Aaaa... Long time ago in a small town in Germany,", + Question1 = list_to_binary(Question), + Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ", + ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]], + Question1 = iolist_to_binary(Question2), + Answer = "there was a shoemaker, Schumacher was his name.", + {ok, L} = gen_tcp:listen(0, [{active, false}]), + {ok, Port} = inet:port(L), + {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]), + {ok, A} = gen_tcp:accept(L), + {ok, FD} = prim_inet:getfd(A), + {ok, Server} = gen_tcp:fdopen(FD, []), + ok = gen_tcp:send(Client, Question), + {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ok = gen_tcp:send(Client, Question1), + {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ok = gen_tcp:send(Client, Question2), + {ok, Question} = gen_tcp:recv(Server, length(Question), 2000), + ok = gen_tcp:send(Server, Answer), + {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000), + ok = gen_tcp:close(Client), + {error,closed} = gen_tcp:recv(A, 1, 2000), + ok = gen_tcp:close(Server), + ok = gen_tcp:close(A), + ok = gen_tcp:close(L), ok. t_fdconnect(Config) when is_list(Config) -> Question = "Aaaa... Long time ago in a small town in Germany,", Question1 = list_to_binary(Question), Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ", - ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]], + ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]], Question1 = iolist_to_binary(Question2), Answer = "there was a shoemaker, Schumacher was his name.", - Path = ?config(data_dir, Config), + Path = proplists:get_value(data_dir, Config), Lib = "gen_tcp_api_SUITE", ok = erlang:load_nif(filename:join(Path,Lib), []), {ok, L} = gen_tcp:listen(0, [{active, false}]), @@ -251,53 +291,253 @@ t_fdconnect(Config) when is_list(Config) -> %%% implicit inet6 option to api functions t_implicit_inet6(Config) when is_list(Config) -> - ?line Host = ok(inet:gethostname()), - ?line - case inet:getaddr(Host, inet6) of - {ok,Addr} -> - ?line t_implicit_inet6(Host, Addr); - {error,Reason} -> - {skip, - "Can not look up IPv6 address: " - ++atom_to_list(Reason)} - end. + Host = ok(inet:gethostname()), + case inet:getaddr(Host, inet6) of + {ok,Addr} -> + t_implicit_inet6(Host, Addr); + {error,Reason} -> + {skip, + "Can not look up IPv6 address: " + ++atom_to_list(Reason)} + end. t_implicit_inet6(Host, Addr) -> - ?line - case gen_tcp:listen(0, [inet6]) of - {ok,S1} -> - ?line Loopback = {0,0,0,0,0,0,0,1}, - ?line io:format("~s ~p~n", ["::1",Loopback]), - ?line implicit_inet6(S1, Loopback), - ?line ok = gen_tcp:close(S1), - %% - ?line Localhost = "localhost", - ?line Localaddr = ok(inet:getaddr(Localhost, inet6)), - ?line io:format("~s ~p~n", [Localhost,Localaddr]), - ?line S2 = ok(gen_tcp:listen(0, [{ip,Localaddr}])), - ?line implicit_inet6(S2, Localaddr), - ?line ok = gen_tcp:close(S2), - %% - ?line io:format("~s ~p~n", [Host,Addr]), - ?line S3 = ok(gen_tcp:listen(0, [{ifaddr,Addr}])), - ?line implicit_inet6(S3, Addr), - ?line ok = gen_tcp:close(S3); - {error,_} -> - {skip,"IPv6 not supported"} - end. + Loopback = {0,0,0,0,0,0,0,1}, + case gen_tcp:listen(0, [inet6, {ip,Loopback}]) of + {ok,S1} -> + io:format("~s ~p~n", ["::1",Loopback]), + implicit_inet6(S1, Loopback), + ok = gen_tcp:close(S1), + %% + Localaddr = ok(get_localaddr()), + S2 = ok(gen_tcp:listen(0, [{ip,Localaddr}])), + implicit_inet6(S2, Localaddr), + ok = gen_tcp:close(S2), + %% + io:format("~s ~p~n", [Host,Addr]), + S3 = ok(gen_tcp:listen(0, [{ifaddr,Addr}])), + implicit_inet6(S3, Addr), + ok = gen_tcp:close(S3); + {error,_} -> + {skip,"IPv6 not supported"} + end. implicit_inet6(S, Addr) -> - ?line P = ok(inet:port(S)), - ?line S2 = ok(gen_tcp:connect(Addr, P, [])), - ?line P2 = ok(inet:port(S2)), - ?line S1 = ok(gen_tcp:accept(S)), - ?line P1 = P = ok(inet:port(S1)), - ?line {Addr,P2} = ok(inet:peername(S1)), - ?line {Addr,P1} = ok(inet:peername(S2)), - ?line {Addr,P1} = ok(inet:sockname(S1)), - ?line {Addr,P2} = ok(inet:sockname(S2)), - ?line ok = gen_tcp:close(S2), - ?line ok = gen_tcp:close(S1). + P = ok(inet:port(S)), + S2 = ok(gen_tcp:connect(Addr, P, [])), + P2 = ok(inet:port(S2)), + S1 = ok(gen_tcp:accept(S)), + P1 = P = ok(inet:port(S1)), + {Addr,P2} = ok(inet:peername(S1)), + {Addr,P1} = ok(inet:peername(S2)), + {Addr,P1} = ok(inet:sockname(S1)), + {Addr,P2} = ok(inet:sockname(S2)), + ok = gen_tcp:close(S2), + ok = gen_tcp:close(S1). + + + +t_local_basic(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + CFile = local_filename(client), + CAddr = {local,bin_filename(CFile)}, + _ = file:delete(SFile), + _ = file:delete(CFile), + %% + L = + ok( + gen_tcp:listen(0, [{ifaddr,{local,SFile}},{active,false}])), + C = + ok( + gen_tcp:connect( + {local,SFile}, 0, [{ifaddr,{local,CFile}},{active,false}])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, CAddr), + ok = gen_tcp:close(L), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + %% + ok = file:delete(SFile), + ok = file:delete(CFile), + ok. + +t_local_unbound(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + %% + L = ok(gen_tcp:listen(0, [{ifaddr,SAddr},{active,false}])), + C = ok(gen_tcp:connect(SAddr, 0, [{active,false}])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, {local,<<>>}), + ok = gen_tcp:close(L), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok = file:delete(SFile), + ok. + +t_local_fdopen(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + %% + L = ok(gen_tcp:listen(0, [{ifaddr,SAddr},{active,false}])), + C0 = ok(gen_tcp:connect(SAddr, 0, [{active,false}])), + Fd = ok(prim_inet:getfd(C0)), + ok = prim_inet:ignorefd(C0, true), + C = ok(gen_tcp:fdopen(Fd, [local])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, {local,<<>>}), + ok = gen_tcp:close(L), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok = gen_tcp:close(C0), + ok = file:delete(SFile), + ok. + +t_local_fdopen_listen(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + L0 = ok(gen_tcp:listen(0, [{ifaddr,SAddr},{active,false}])), + Fd = ok(prim_inet:getfd(L0)), + L = ok(gen_tcp:listen(0, [{fd,Fd},local,{active,false}])), + C = ok(gen_tcp:connect(SAddr, 0, [{active,false}])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, {local,<<>>}), + ok = gen_tcp:close(L), + ok = gen_tcp:close(L0), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok = file:delete(SFile), + ok. + +t_local_fdopen_listen_unbound(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + P = ok(prim_inet:open(tcp, local, stream)), + Fd = ok(prim_inet:getfd(P)), + L = + ok(gen_tcp:listen( + 0, [{fd,Fd},{ifaddr,SAddr},{active,false}])), + C = ok(gen_tcp:connect(SAddr, 0, [{active,false}])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, {local,<<>>}), + ok = gen_tcp:close(L), + ok = gen_tcp:close(P), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok = file:delete(SFile), + ok. + +t_local_fdopen_connect(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + CFile = local_filename(client), + CAddr = {local,bin_filename(CFile)}, + _ = file:delete(SFile), + _ = file:delete(CFile), + L = ok(gen_tcp:listen(0, [{ifaddr,SAddr},{active,false}])), + P = ok(prim_inet:open(tcp, local, stream)), + Fd = ok(prim_inet:getfd(P)), + C = + ok(gen_tcp:connect( + SAddr, 0, [{fd,Fd},{ifaddr,CAddr},{active,false}])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, CAddr), + ok = gen_tcp:close(L), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok = gen_tcp:close(P), + ok = file:delete(SFile), + ok. + +t_local_fdopen_connect_unbound(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + L = ok(gen_tcp:listen(0, [{ifaddr,SAddr},{active,false}])), + P = ok(prim_inet:open(tcp, local, stream)), + Fd = ok(prim_inet:getfd(P)), + C = ok(gen_tcp:connect(SAddr, 0, [{fd,Fd},{active,false}])), + S = ok(gen_tcp:accept(L)), + SAddr = ok(inet:sockname(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, {local,<<>>}), + ok = gen_tcp:close(L), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok = gen_tcp:close(P), + ok = file:delete(SFile), + ok. + +t_local_abstract(_Config) -> + case os:type() of + {unix,linux} -> + AbstAddr = {local,<<>>}, + L = + ok(gen_tcp:listen( + 0, [{ifaddr,AbstAddr},{active,false}])), + {local,_} = SAddr = ok(inet:sockname(L)), + C = + ok(gen_tcp:connect( + SAddr, 0, [{ifaddr,AbstAddr},{active,false}])), + {local,_} = CAddr = ok(inet:sockname(C)), + S = ok(gen_tcp:accept(L)), + {error,enotconn} = inet:peername(L), + local_handshake(S, SAddr, C, CAddr), + ok = gen_tcp:close(L), + ok = gen_tcp:close(S), + ok = gen_tcp:close(C), + ok; + _ -> + {skip,"AF_LOCAL Abstract Addresses only supported on Linux"} + end. + + +local_handshake(S, SAddr, C, CAddr) -> + SData = "9876543210", + CData = "0123456789", + SAddr = ok(inet:sockname(S)), + CAddr = ok(inet:sockname(C)), + CAddr = ok(inet:peername(S)), + SAddr = ok(inet:peername(C)), + ok = gen_tcp:send(C, CData), + ok = gen_tcp:send(S, SData), + CData = ok(gen_tcp:recv(S, length(CData))), + SData = ok(gen_tcp:recv(C, length(SData))), + ok. + +t_accept_inet6_tclass(Config) when is_list(Config) -> + TClassOpt = {tclass,8#56 bsl 2}, % Expedited forwarding + Loopback = {0,0,0,0,0,0,0,1}, + case gen_tcp:listen(0, [inet6, {ip, Loopback}, TClassOpt]) of + {ok,L} -> + LPort = ok(inet:port(L)), + Sa = ok(gen_tcp:connect(Loopback, LPort, [])), + Sb = ok(gen_tcp:accept(L)), + [TClassOpt] = ok(inet:getopts(Sb, [tclass])), + ok = gen_tcp:close(Sb), + ok = gen_tcp:close(Sa), + ok = gen_tcp:close(L), + ok; + {error,_} -> + {skip,"IPv6 TCLASS not supported"} + end. %%% Utilities @@ -308,13 +548,13 @@ implicit_inet6(S, Addr) -> timeout({M,F,A}, Lower, Upper) -> case test_server:timecall(M, F, A) of {Time, Result} when Time < Lower -> - test_server:fail({too_short_time, Time, Result}); + ct:fail({too_short_time, Time, Result}); {Time, Result} when Time > Upper -> - test_server:fail({too_long_time, Time, Result}); + ct:fail({too_long_time, Time, Result}); {_, {error, timeout}} -> ok; {_, Result} -> - test_server:fail({unexpected_result, Result}) + ct:fail({unexpected_result, Result}) end. connect_timeout({M,F,A}, Lower, Upper) -> @@ -329,28 +569,28 @@ connect_timeout({M,F,A}, Lower, Upper) -> Pinfo = erlang:port_info(Socket), Db = inet_db:lookup_socket(Socket), Peer = inet:peername(Socket), - test_server:fail({too_short_time, Time, - [Result,Pinfo,Db,Peer]}); + ct:fail({too_short_time, Time, + [Result,Pinfo,Db,Peer]}); _ -> - test_server:fail({too_short_time, Time, Result}) + ct:fail({too_short_time, Time, Result}) end; {Time, Result} when Time > Upper -> - test_server:fail({too_long_time, Time, Result}); + ct:fail({too_long_time, Time, Result}); {_, {error, timeout}} -> ok; {_, Result} -> - test_server:fail({unexpected_result, Result}) + ct:fail({unexpected_result, Result}) end. %% Try to obtain an unused IP address in the local network. unused_ip() -> - ?line {ok, Host} = inet:gethostname(), - ?line {ok, Hent} = inet:gethostbyname(Host), - ?line #hostent{h_addr_list=[{A, B, C, _D}|_]} = Hent, + {ok, Host} = inet:gethostname(), + {ok, Hent} = inet:gethostbyname(Host), + #hostent{h_addr_list=[{A, B, C, _D}|_]} = Hent, %% Note: In our net, addresses below 16 are reserved for routers and %% other strange creatures. - ?line IP = unused_ip(A, B, C, 16), + IP = unused_ip(A, B, C, 16), io:format("we = ~p, unused_ip = ~p~n", [Hent, IP]), IP. @@ -361,8 +601,42 @@ unused_ip(A, B, C, D) -> {error, _} -> {ok, {A, B, C, D}} end. -ok({ok,V}) -> V. +ok({ok,V}) -> V; +ok(NotOk) -> + try throw(not_ok) + catch + Thrown -> + erlang:raise( + error, {Thrown, NotOk}, tl(erlang:get_stacktrace())) + end. +get_localaddr() -> + get_localaddr(["localhost", "localhost6", "ip6-localhost"]). + +get_localaddr([]) -> + {error, localaddr_not_found}; +get_localaddr([Localhost|Ls]) -> + case inet:getaddr(Localhost, inet6) of + {ok, LocalAddr} -> + io:format("~s ~p~n", [Localhost, LocalAddr]), + {ok, LocalAddr}; + _ -> + get_localaddr(Ls) + end. getsockfd() -> undefined. closesockfd(_FD) -> undefined. + +local_filename(Tag) -> + "/tmp/" ?MODULE_STRING "_" ++ os:getpid() ++ "_" ++ atom_to_list(Tag). + +bin_filename(String) -> + unicode:characters_to_binary(String, file:native_name_encoding()). + +delete_local_filenames() -> + _ = + [file:delete(F) || + F <- + filelib:wildcard( + "/tmp/" ?MODULE_STRING "_" ++ os:getpid() ++ "_*")], + ok. diff --git a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c index ca8eacdf40..b91dca61d4 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c +++ b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2013. All Rights Reserved. + * Copyright Ericsson AB 2009-2016. 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. @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include <erl_nif.h> #include <stdio.h> #include <string.h> diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl index 6dcb21758b..57525f8015 100644 --- a/lib/kernel/test/gen_tcp_echo_SUITE.erl +++ b/lib/kernel/test/gen_tcp_echo_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. 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. @@ -19,7 +19,7 @@ %% -module(gen_tcp_echo_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %%-compile(export_all). @@ -34,7 +34,9 @@ -define(TPKT_VRSN, 3). -define(LINE_LENGTH, 1023). % (default value of gen_tcp option 'recbuf') - 1 -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,5}}]. all() -> [active_echo, passive_echo, active_once_echo, @@ -59,94 +61,75 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:minutes(5)), - [{watchdog, Dog}|Config]. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). - -active_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in active mode)."]; -active_echo(suite) -> []; + Config. + +end_per_testcase(_Func, _Config) -> + ok. + +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in active mode). active_echo(Config) when is_list(Config) -> - ?line echo_test([], fun active_echo/4, [{echo, fun echo_server/0}]). + echo_test([], fun active_echo/4, [{echo, fun echo_server/0}]). -passive_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in passive mode)."]; -passive_echo(suite) -> []; +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in passive mode). passive_echo(Config) when is_list(Config) -> - ?line echo_test([{active, false}], fun passive_echo/4, - [{echo, fun echo_server/0}]). + echo_test([{active, false}], fun passive_echo/4, + [{echo, fun echo_server/0}]). -active_once_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in active once mode)."]; -active_once_echo(suite) -> []; +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in active once mode). active_once_echo(Config) when is_list(Config) -> - ?line echo_test([{active, once}], fun active_once_echo/4, - [{echo, fun echo_server/0}]). - -slow_active_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in active mode). ", - "The echo server is a special one that delays between every character."]; -slow_active_echo(suite) -> []; + echo_test([{active, once}], fun active_once_echo/4, + [{echo, fun echo_server/0}]). + +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in active mode). +%% The echo server is a special one that delays between every character. slow_active_echo(Config) when is_list(Config) -> - ?line echo_test([], fun active_echo/4, - [slow_echo, {echo, fun slow_echo_server/0}]). - -slow_passive_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to an echo server and receiving them again (socket in passive mode).", - "The echo server is a special one that delays between every character."]; -slow_passive_echo(suite) -> []; + echo_test([], fun active_echo/4, + [slow_echo, {echo, fun slow_echo_server/0}]). + +%% Test sending packets of various sizes and various packet types +%% to an echo server and receiving them again (socket in passive mode). +%% The echo server is a special one that delays between every character. slow_passive_echo(Config) when is_list(Config) -> - ?line echo_test([{active, false}], fun passive_echo/4, - [slow_echo, {echo, fun slow_echo_server/0}]). - -limit_active_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in active mode) " - "with packet_size limitation."]; -limit_active_echo(suite) -> []; + echo_test([{active, false}], fun passive_echo/4, + [slow_echo, {echo, fun slow_echo_server/0}]). + +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in active mode) +%% with packet_size limitation. limit_active_echo(Config) when is_list(Config) -> - ?line echo_test([{packet_size, 10}], - fun active_echo/4, - [{packet_size, 10}, {echo, fun echo_server/0}]). - -limit_passive_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in passive mode) ", - "with packet_size limitation."]; -limit_passive_echo(suite) -> []; + echo_test([{packet_size, 10}], + fun active_echo/4, + [{packet_size, 10}, {echo, fun echo_server/0}]). + +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in passive mode) +%% with packet_size limitation. limit_passive_echo(Config) when is_list(Config) -> - ?line echo_test([{packet_size, 10},{active, false}], - fun passive_echo/4, - [{packet_size, 10}, {echo, fun echo_server/0}]). - -large_limit_active_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in active mode) " - "with large packet_size limitation."]; -large_limit_active_echo(suite) -> []; + echo_test([{packet_size, 10},{active, false}], + fun passive_echo/4, + [{packet_size, 10}, {echo, fun echo_server/0}]). + +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in active mode) +%% with large packet_size limitation. large_limit_active_echo(Config) when is_list(Config) -> - ?line echo_test([{packet_size, 10}], - fun active_echo/4, - [{packet_size, (1 bsl 32)-1}, - {echo, fun echo_server/0}]). - -large_limit_passive_echo(doc) -> - ["Test sending packets of various sizes and various packet types ", - "to the echo port and receiving them again (socket in passive mode) ", - "with large packet_size limitation."]; -large_limit_passive_echo(suite) -> []; + echo_test([{packet_size, 10}], + fun active_echo/4, + [{packet_size, (1 bsl 32)-1}, + {echo, fun echo_server/0}]). + +%% Test sending packets of various sizes and various packet types +%% to the echo port and receiving them again (socket in passive mode) +%% with large packet_size limitation. large_limit_passive_echo(Config) when is_list(Config) -> - ?line echo_test([{packet_size, 10},{active, false}], - fun passive_echo/4, - [{packet_size, (1 bsl 32) -1}, - {echo, fun echo_server/0}]). + echo_test([{packet_size, 10},{active, false}], + fun passive_echo/4, + [{packet_size, (1 bsl 32) -1}, + {echo, fun echo_server/0}]). echo_test(SockOpts, EchoFun, Config0) -> echo_test_1(SockOpts, EchoFun, Config0), @@ -154,53 +137,53 @@ echo_test(SockOpts, EchoFun, Config0) -> echo_test_1([{delay_send,true}|SockOpts], EchoFun, Config0). echo_test_1(SockOpts, EchoFun, Config0) -> - ?line EchoSrvFun = ?config(echo, Config0), - ?line {ok, EchoPort} = EchoSrvFun(), - ?line Config = [{echo_port, EchoPort}|Config0], - - ?line echo_packet([{packet, 1}|SockOpts], EchoFun, Config), - ?line echo_packet([{packet, 2}|SockOpts], EchoFun, Config), - ?line echo_packet([{packet, 4}|SockOpts], EchoFun, Config), - ?line echo_packet([{packet, sunrm}|SockOpts], EchoFun, Config), - ?line echo_packet([{packet, cdr}|SockOpts], EchoFun, - [{type, {cdr, big}}|Config]), - ?line echo_packet([{packet, cdr}|SockOpts], EchoFun, - [{type, {cdr, little}}|Config]), - ?line case lists:keymember(packet_size, 1, SockOpts) of - false -> - % This is cheating, we should test that packet_size - % also works for line and http. - echo_packet([{packet, line}|SockOpts], EchoFun, Config), - echo_packet([{packet, http}|SockOpts], EchoFun, Config), - echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config); - - true -> ok - end, - ?line echo_packet([{packet, tpkt}|SockOpts], EchoFun, Config), - - ?line ShortTag = [16#E0], - ?line LongTag = [16#1F, 16#83, 16#27], - ?line echo_packet([{packet, asn1}|SockOpts], EchoFun, - [{type, {asn1, short, ShortTag}}|Config]), - ?line echo_packet([{packet, asn1}|SockOpts], EchoFun, - [{type, {asn1, long, ShortTag}}|Config]), - ?line echo_packet([{packet, asn1}|SockOpts], EchoFun, - [{type, {asn1, short, LongTag}}|Config]), - ?line echo_packet([{packet, asn1}|SockOpts], EchoFun, - [{type, {asn1, long, LongTag}}|Config]), + EchoSrvFun = proplists:get_value(echo, Config0), + {ok, EchoPort} = EchoSrvFun(), + Config = [{echo_port, EchoPort}|Config0], + + echo_packet([{packet, 1}|SockOpts], EchoFun, Config), + echo_packet([{packet, 2}|SockOpts], EchoFun, Config), + echo_packet([{packet, 4}|SockOpts], EchoFun, Config), + echo_packet([{packet, sunrm}|SockOpts], EchoFun, Config), + echo_packet([{packet, cdr}|SockOpts], EchoFun, + [{type, {cdr, big}}|Config]), + echo_packet([{packet, cdr}|SockOpts], EchoFun, + [{type, {cdr, little}}|Config]), + case lists:keymember(packet_size, 1, SockOpts) of + false -> + %% This is cheating, we should test that packet_size + %% also works for line and http. + echo_packet([{packet, line}|SockOpts], EchoFun, Config), + echo_packet([{packet, http}|SockOpts], EchoFun, Config), + echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config); + + true -> ok + end, + echo_packet([{packet, tpkt}|SockOpts], EchoFun, Config), + + ShortTag = [16#E0], + LongTag = [16#1F, 16#83, 16#27], + echo_packet([{packet, asn1}|SockOpts], EchoFun, + [{type, {asn1, short, ShortTag}}|Config]), + echo_packet([{packet, asn1}|SockOpts], EchoFun, + [{type, {asn1, long, ShortTag}}|Config]), + echo_packet([{packet, asn1}|SockOpts], EchoFun, + [{type, {asn1, short, LongTag}}|Config]), + echo_packet([{packet, asn1}|SockOpts], EchoFun, + [{type, {asn1, long, LongTag}}|Config]), ok. echo_packet(SockOpts, EchoFun, Opts) -> Type = case lists:keysearch(type, 1, Opts) of - {value, {type, T}} -> - T; - _ -> - {value, {packet, T}} = lists:keysearch(packet, 1, SockOpts), - T - end, + {value, {type, T}} -> + T; + _ -> + {value, {packet, T}} = lists:keysearch(packet, 1, SockOpts), + T + end, %% Connect to the echo server. - EchoPort = ?config(echo_port, Opts), + EchoPort = proplists:get_value(echo_port, Opts), {ok, Echo} = gen_tcp:connect(localhost, EchoPort, SockOpts), SlowEcho = lists:member(slow_echo, Opts), @@ -223,83 +206,78 @@ echo_packet_http(Echo, Type, EchoFun) -> EchoFun(Echo, Type, P2, http_reply(P2, Type)). echo_packet0(Echo, Type, EchoFun, SlowEcho, Opts) -> - ?line PacketSize = + PacketSize = case lists:keysearch(packet_size, 1, Opts) of {value,{packet_size,Sz}} when Sz < 10 -> Sz; {value,{packet_size,_}} -> 10; false -> 0 end, %% Echo small packets first. - ?line echo_packet1(Echo, Type, EchoFun, 0), - ?line echo_packet1(Echo, Type, EchoFun, 1), - ?line echo_packet1(Echo, Type, EchoFun, 2), - ?line echo_packet1(Echo, Type, EchoFun, 3), - ?line echo_packet1(Echo, Type, EchoFun, 4), - ?line echo_packet1(Echo, Type, EchoFun, 7), + echo_packet1(Echo, Type, EchoFun, 0), + echo_packet1(Echo, Type, EchoFun, 1), + echo_packet1(Echo, Type, EchoFun, 2), + echo_packet1(Echo, Type, EchoFun, 3), + echo_packet1(Echo, Type, EchoFun, 4), + echo_packet1(Echo, Type, EchoFun, 7), if PacketSize =/= 0 -> - ?line echo_packet1(Echo, Type, EchoFun, - {PacketSize-1, PacketSize}), - ?line echo_packet1(Echo, Type, EchoFun, - {PacketSize, PacketSize}), - ?line echo_packet1(Echo, Type, EchoFun, - {PacketSize+1, PacketSize}); + echo_packet1(Echo, Type, EchoFun, + {PacketSize-1, PacketSize}), + echo_packet1(Echo, Type, EchoFun, + {PacketSize, PacketSize}), + echo_packet1(Echo, Type, EchoFun, + {PacketSize+1, PacketSize}); not SlowEcho -> % Go on with bigger packets if not slow echo server. - ?line echo_packet1(Echo, Type, EchoFun, 10), - ?line echo_packet1(Echo, Type, EchoFun, 13), - ?line echo_packet1(Echo, Type, EchoFun, 126), - ?line echo_packet1(Echo, Type, EchoFun, 127), - ?line echo_packet1(Echo, Type, EchoFun, 128), - ?line echo_packet1(Echo, Type, EchoFun, 255), - ?line echo_packet1(Echo, Type, EchoFun, 256), - ?line echo_packet1(Echo, Type, EchoFun, 1023), - ?line echo_packet1(Echo, Type, EchoFun, 3747), - ?line echo_packet1(Echo, Type, EchoFun, 32767), - ?line echo_packet1(Echo, Type, EchoFun, 32768), - ?line echo_packet1(Echo, Type, EchoFun, 65531), - ?line echo_packet1(Echo, Type, EchoFun, 65535), - ?line echo_packet1(Echo, Type, EchoFun, 65536), - ?line echo_packet1(Echo, Type, EchoFun, 70000), - ?line echo_packet1(Echo, Type, EchoFun, infinite); + echo_packet1(Echo, Type, EchoFun, 10), + echo_packet1(Echo, Type, EchoFun, 13), + echo_packet1(Echo, Type, EchoFun, 126), + echo_packet1(Echo, Type, EchoFun, 127), + echo_packet1(Echo, Type, EchoFun, 128), + echo_packet1(Echo, Type, EchoFun, 255), + echo_packet1(Echo, Type, EchoFun, 256), + echo_packet1(Echo, Type, EchoFun, 1023), + echo_packet1(Echo, Type, EchoFun, 3747), + echo_packet1(Echo, Type, EchoFun, 32767), + echo_packet1(Echo, Type, EchoFun, 32768), + echo_packet1(Echo, Type, EchoFun, 65531), + echo_packet1(Echo, Type, EchoFun, 65535), + echo_packet1(Echo, Type, EchoFun, 65536), + echo_packet1(Echo, Type, EchoFun, 70000), + echo_packet1(Echo, Type, EchoFun, infinite); true -> ok end, - ?line gen_tcp:close(Echo), + gen_tcp:close(Echo), ok. echo_packet1(EchoSock, Type, EchoFun, Size) -> - ?line case packet(Size, Type) of - false -> - ok; - Packet -> - ?line io:format("Type ~p, size ~p, time ~p", - [Type, Size, time()]), - ?line - case EchoFun(EchoSock, Type, Packet, [Packet]) of - ok -> - ?line - case Size of - {N, Max} when N > Max -> - ?line - test_server:fail( - {packet_through, {N, Max}}); - _ -> ok - end; - {error, emsgsize} -> - ?line - case Size of - {N, Max} when N > Max -> - io:format(" Blocked!"); - _ -> - ?line - test_server:fail( - {packet_blocked, Size}) - end; - Error -> - ?line test_server:fail(Error) - end - end. + case packet(Size, Type) of + false -> + ok; + Packet -> + io:format("Type ~p, size ~p, time ~p", + [Type, Size, time()]), + case EchoFun(EchoSock, Type, Packet, [Packet]) of + ok -> + case Size of + {N, Max} when N > Max -> + ct:fail( + {packet_through, {N, Max}}); + _ -> ok + end; + {error, emsgsize} -> + case Size of + {N, Max} when N > Max -> + io:format(" Blocked!"); + _ -> + ct:fail( + {packet_blocked, Size}) + end; + Error -> + ct:fail(Error) + end + end. active_echo(Sock, Type, Packet, PacketEchos) -> - ?line ok = gen_tcp:send(Sock, Packet), + ok = gen_tcp:send(Sock, Packet), active_recv(Sock, Type, PacketEchos). active_recv(_, _, []) -> @@ -310,21 +288,21 @@ active_recv(Sock, Type, [PacketEcho|Tail]) -> http_bin -> http; _ -> tcp end, - ?line receive Recv->Recv end, + receive Recv->Recv end, %%io:format("Active received: ~p\n",[Recv]), - ?line case Recv of - {Tag, Sock, PacketEcho} -> - active_recv(Sock, Type, Tail); - {Tag, Sock, Bad} -> - ?line test_server:fail({wrong_data, Bad, expected, PacketEcho}); - {tcp_error, Sock, Reason} -> - {error, Reason}; - Other -> - ?line test_server:fail({unexpected_message, Other, Tag}) - end. + case Recv of + {Tag, Sock, PacketEcho} -> + active_recv(Sock, Type, Tail); + {Tag, Sock, Bad} -> + ct:fail({wrong_data, Bad, expected, PacketEcho}); + {tcp_error, Sock, Reason} -> + {error, Reason}; + Other -> + ct:fail({unexpected_message, Other, Tag}) + end. passive_echo(Sock, _Type, Packet, PacketEchos) -> - ?line ok = gen_tcp:send(Sock, Packet), + ok = gen_tcp:send(Sock, Packet), passive_recv(Sock, PacketEchos). passive_recv(_, []) -> @@ -332,22 +310,22 @@ passive_recv(_, []) -> passive_recv(Sock, [PacketEcho | Tail]) -> Recv = gen_tcp:recv(Sock, 0), %%io:format("Passive received: ~p\n",[Recv]), - ?line case Recv of - {ok, PacketEcho} -> - passive_recv(Sock, Tail); - {ok, Bad} -> - io:format("Expected: ~p\nGot: ~p\n",[PacketEcho,Bad]), - ?line test_server:fail({wrong_data, Bad}); - {error,PacketEcho} -> - passive_recv(Sock, Tail); % expected error - {error, _}=Error -> - Error; - Other -> - ?line test_server:fail({unexpected_message, Other}) - end. + case Recv of + {ok, PacketEcho} -> + passive_recv(Sock, Tail); + {ok, Bad} -> + io:format("Expected: ~p\nGot: ~p\n",[PacketEcho,Bad]), + ct:fail({wrong_data, Bad}); + {error,PacketEcho} -> + passive_recv(Sock, Tail); % expected error + {error, _}=Error -> + Error; + Other -> + ct:fail({unexpected_message, Other}) + end. active_once_echo(Sock, Type, Packet, PacketEchos) -> - ?line ok = gen_tcp:send(Sock, Packet), + ok = gen_tcp:send(Sock, Packet), active_once_recv(Sock, Type, PacketEchos). active_once_recv(_, _, []) -> @@ -358,17 +336,17 @@ active_once_recv(Sock, Type, [PacketEcho | Tail]) -> http_bin -> http; _ -> tcp end, - ?line receive - {Tag, Sock, PacketEcho} -> - inet:setopts(Sock, [{active, once}]), - active_once_recv(Sock, Type, Tail); - {Tag, Sock, Bad} -> - ?line test_server:fail({wrong_data, Bad}); - {tcp_error, Sock, Reason} -> - {error, Reason}; - Other -> - ?line test_server:fail({unexpected_message, Other, expected, {Tag, Sock, PacketEcho}}) - end. + receive + {Tag, Sock, PacketEcho} -> + inet:setopts(Sock, [{active, once}]), + active_once_recv(Sock, Type, Tail); + {Tag, Sock, Bad} -> + ct:fail({wrong_data, Bad}); + {tcp_error, Sock, Reason} -> + {error, Reason}; + Other -> + ct:fail({unexpected_message, Other, expected, {Tag, Sock, PacketEcho}}) + end. %%% Building of random packets. @@ -442,14 +420,7 @@ random_char(Chars) -> lists:nth(uniform(length(Chars)), Chars). uniform(N) -> - case get(random_seed) of - undefined -> - {X, Y, Z} = time(), - random:seed(X, Y, Z); - _ -> - ok - end, - random:uniform(N). + rand:uniform(N). put_int32(X, big, List) -> [ (X bsr 24) band 16#ff, @@ -458,9 +429,9 @@ put_int32(X, big, List) -> (X) band 16#ff | List ]; put_int32(X, little, List) -> [ (X) band 16#ff, - (X bsr 8) band 16#ff, - (X bsr 16) band 16#ff, - (X bsr 24) band 16#ff | List]. + (X bsr 8) band 16#ff, + (X bsr 16) band 16#ff, + (X bsr 24) band 16#ff | List]. put_int16(X, ByteOrder) -> put_int16(X, ByteOrder, []). @@ -470,16 +441,16 @@ put_int16(X, big, List) -> (X) band 16#ff | List ]; put_int16(X, little, List) -> [ (X) band 16#ff, - (X bsr 8) band 16#ff | List ]. + (X bsr 8) band 16#ff | List ]. %%% A normal echo server, for systems that don't have one. echo_server() -> Self = self(), - ?line spawn_link(fun() -> echo_server(Self) end), - ?line receive - {echo_port, Port} -> - {ok, Port} + spawn_link(fun() -> echo_server(Self) end), + receive + {echo_port, Port} -> + {ok, Port} end. echo_server(ReplyTo) -> @@ -512,11 +483,11 @@ echoer_loop(Sock) -> slow_echo_server() -> Self = self(), - ?line spawn_link(fun() -> slow_echo_server(Self) end), - ?line receive - {echo_port, Port} -> - {ok, Port} - end. + spawn_link(fun() -> slow_echo_server(Self) end), + receive + {echo_port, Port} -> + {ok, Port} + end. slow_echo_server(ReplyTo) -> {ok, S} = gen_tcp:listen(0, [{active, false}, {nodelay, true}]), @@ -552,17 +523,17 @@ slow_send(_, []) -> http_request(Uri) -> list_to_binary(["POST ", Uri, <<" HTTP/1.1\r\n" - "Connection: close\r\n" - "Host: localhost:8000\r\n" - "User-Agent: perl post\r\n" - "Content-Length: 4\r\n" - "Content-Type: text/xml; charset=utf-8\r\n" - "Other-Field: with some text\r\n" - "Multi-Line: Once upon a time in a land far far away,\r\n" - " there lived a princess imprisoned in the highest tower\r\n" - " of the most haunted castle.\r\n" - "Invalid line without a colon\r\n" - "\r\n">>]). + "Connection: close\r\n" + "Host: localhost:8000\r\n" + "User-Agent: perl post\r\n" + "Content-Length: 4\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Other-Field: with some text\r\n" + "Multi-Line: Once upon a time in a land far far away,\r\n" + " there lived a princess imprisoned in the highest tower\r\n" + " of the most haunted castle.\r\n" + "Invalid line without a colon\r\n" + "\r\n">>]). http_uri_variants() -> ["*", @@ -575,11 +546,11 @@ http_uri_variants() -> http_response() -> <<"HTTP/1.0 404 Object Not Found\r\n" - "Server: inets/4.7.16\r\n" - "Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 207\r\n" - "\r\n">>. + "Server: inets/4.7.16\r\n" + "Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 207\r\n" + "\r\n">>. http_reply(Bin, Type) -> {ok, Line, Rest} = erlang:decode_packet(Type,Bin,[]), @@ -596,7 +567,3 @@ http_reply(<<>>, Acc, _) -> http_reply(Bin, Acc, HType) -> {ok, Line, Rest} = erlang:decode_packet(HType,Bin,[]), http_reply(Rest, [Line | Acc], HType). - - - - diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 81c6dcd0fd..331864b5de 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2014. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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. @@ -19,15 +19,15 @@ %% -module(gen_tcp_misc_SUITE). --include_lib("test_server/include/test_server.hrl"). - -%-compile(export_all). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, controlling_process/1, controlling_process_self/1, no_accept/1, close_with_pending_output/1, active_n/1, - data_before_close/1, iter_max_socks/1, get_status/1, + data_before_close/1, + iter_max_socks/0, iter_max_socks/1, + get_status/1, passive_sockets/1, accept_closed_by_other_process/1, init_per_testcase/2, end_per_testcase/2, otp_3924/1, otp_3924_sender/4, closed_socket/1, @@ -41,7 +41,7 @@ busy_send/1, busy_disconnect_passive/1, busy_disconnect_active/1, fill_sendq/1, partial_recv_and_close/1, partial_recv_and_close_2/1,partial_recv_and_close_3/1,so_priority/1, - % Accept tests + %% Accept tests primitive_accept/1,multi_accept_close_listen/1,accept_timeout/1, accept_timeouts_in_order/1,accept_timeouts_in_order2/1, accept_timeouts_in_order3/1,accept_timeouts_in_order4/1, @@ -50,49 +50,23 @@ killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1, several_accepts_in_one_go/1, accept_system_limit/1, active_once_closed/1, send_timeout/1, send_timeout_active/1, - otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, wrapping_oct/1, - otp_9389/1]). + otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, + wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1]). %% Internal exports. -export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1, oct_acceptor/1, otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]). -init_per_testcase(wrapping_oct, Config) when is_list(Config) -> - Dog = case os:type() of - {ose,_} -> - test_server:timetrap(test_server:minutes(20)); - _Else -> - test_server:timetrap(test_server:seconds(600)) - end, - [{watchdog, Dog}|Config]; -init_per_testcase(iter_max_socks, Config) when is_list(Config) -> - Dog = case os:type() of - {win32,_} -> - test_server:timetrap(test_server:minutes(30)); - _Else -> - test_server:timetrap(test_server:seconds(240)) - end, - [{watchdog, Dog}|Config]; -init_per_testcase(accept_system_limit, Config) when is_list(Config) -> - case os:type() of - {ose,_} -> - {skip,"Skip in OSE"}; - _ -> - Dog = test_server:timetrap(test_server:seconds(240)), - [{watchdog,Dog}|Config] - end; -init_per_testcase(wrapping_oct, Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(600)), - [{watchdog, Dog}|Config]; -init_per_testcase(_Func, Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(240)), - [{watchdog, Dog}|Config]. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +init_per_testcase(_Func, Config) -> + Config. + +end_per_testcase(_Func, _Config) -> + ok. + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,4}}]. all() -> [controlling_process, controlling_process_self, no_accept, @@ -136,11 +110,13 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. -default_options(doc) -> - ["Tests kernel application variables inet_default_listen_options and " - "inet_default_connect_options"]; -default_options(suite) -> - []; +-define(UNIQ_NODE_NAME, + list_to_atom(?MODULE_STRING ++ "__" ++ + atom_to_list(?FUNCTION_NAME) ++ "_" ++ + integer_to_list(erlang:unique_integer([positive])))). + +%% Tests kernel application variables inet_default_listen_options and +%% inet_default_connect_options. default_options(Config) when is_list(Config) -> %% First check the delay_send option {true,true,true}=do_delay_send_1(), @@ -215,7 +191,7 @@ default_options(Config) when is_list(Config) -> do_delay_on_other_node(XArgs, Function) -> Dir = filename:dirname(code:which(?MODULE)), - {ok,Node} = test_server:start_node(test_default_options_slave,slave, + {ok,Node} = test_server:start_node(?UNIQ_NODE_NAME, slave, [{args,"-pa " ++ Dir ++ " " ++ XArgs}]), Res = rpc:call(Node,erlang,apply,[Function,[]]), test_server:stop_node(Node), @@ -312,11 +288,9 @@ do_delay_send_7() -> gen_tcp:close(LS), {B1,B2,B3}. -controlling_process(doc) -> - ["Open a listen port and change controlling_process for it", - "The result should be ok of done by the owner process," - "Otherwise is should return {error,not_owner} or similar"]; -controlling_process(suite) -> []; +%% Open a listen port and change controlling_process for it +%% The result should be ok of done by the owner process, +%% Otherwise is should return {error,not_owner} or similar. controlling_process(Config) when is_list(Config) -> {ok,S} = gen_tcp:listen(0,[]), Pid2 = spawn(?MODULE,not_owner,[S]), @@ -345,9 +319,8 @@ not_owner(S) -> ok end. -controlling_process_self(doc) -> - ["Open a listen port and assign the controlling process to " - "it self, then exit and make sure the port is closed properly."]; +%% Open a listen port and assign the controlling process to +%% it self, then exit and make sure the port is closed properly. controlling_process_self(Config) when is_list(Config) -> S = self(), process_flag(trap_exit,true), @@ -371,11 +344,9 @@ controlling_process_self(Config) when is_list(Config) -> end. -no_accept(doc) -> - ["Open a listen port and connect to it, then close the listen port ", - "without doing any accept. The connected socket should receive ", - "a tcp_closed message."]; -no_accept(suite) -> []; +%% Open a listen port and connect to it, then close the listen port +%% without doing any accept. The connected socket should receive +%% a tcp_closed message. no_accept(Config) when is_list(Config) -> {ok, L} = gen_tcp:listen(0, []), {ok, {_, Port}} = inet:sockname(L), @@ -385,14 +356,12 @@ no_accept(Config) when is_list(Config) -> {tcp_closed, Client} -> ok after 5000 -> - test_server:fail(never_closed) + ct:fail(never_closed) end. -close_with_pending_output(doc) -> - ["Send several packets to a socket and close it. All packets should arrive ", - "to the other end."]; -close_with_pending_output(suite) -> []; +%% Send several packets to a socket and close it. All packets should +%% arrive to the other end. close_with_pending_output(Config) when is_list(Config) -> {ok, L} = gen_tcp:listen(0, [binary, {active, false}]), {ok, {_, Port}} = inet:sockname(L), @@ -408,16 +377,16 @@ close_with_pending_output(Config) when is_list(Config) -> gen_tcp:close(A), gen_tcp:close(L); {ok, Bin} -> - test_server:fail({small_packet, + ct:fail({small_packet, byte_size(Bin)}); Error -> - test_server:fail({unexpected, Error}) + ct:fail({unexpected, Error}) end, ok; {error, no_remote_hosts} -> {skipped,"No remote hosts"}; {error, Other} -> - ?t:fail({failed_to_start_slave_node, Other}) + ct:fail({failed_to_start_slave_node, Other}) end. sender(Port, Packets, Host) -> @@ -435,9 +404,7 @@ send_loop(Sock, Data, Left) -> send_loop(Sock, Data, Left-1). %% Test {active,N} option -active_n(doc) -> - ["Verify operation of the {active,N} option."]; -active_n(suite) -> []; +%% Verify operation of the {active,N} option. active_n(Config) when is_list(Config) -> N = 3, LS = ok(gen_tcp:listen(0, [{active,N}])), @@ -547,9 +514,7 @@ active_n(Config) when is_list(Config) -> %% I expect propagation of a close to be quite fast %% so 100 ms seems reasonable. -otp_3924(doc) -> - ["Tests that a socket can be closed fast enough."]; -otp_3924(suite) -> []; +%% Tests that a socket can be closed fast enough. otp_3924(Config) when is_list(Config) -> MaxDelay = (case has_superfluous_schedulers() of true -> 4; @@ -567,8 +532,8 @@ otp_3924_1(MaxDelay) -> {ok, Node} = start_node(otp_3924), DataLen = 100*1024, Data = otp_3924_data(DataLen), - % Repeat the test a couple of times to prevent the test from passing - % by chance. + %% Repeat the test a couple of times to prevent the test from passing + %% by chance. repeat(10, fun(N) -> ok = otp_3924(MaxDelay, Node, Data, DataLen, N) end), @@ -607,17 +572,17 @@ otp_3924_receive_data(LSock, Sender, MaxDelay, Len, N) -> process_flag(priority, OP), receive {'EXIT', _, TimeoutRef} -> - test_server:fail({close_not_fast_enough,MaxDelay,N}); + ct:fail({close_not_fast_enough,MaxDelay,N}); {'EXIT', Sender, Reason} -> - test_server:fail({sender_exited, Reason}); + ct:fail({sender_exited, Reason}); {'EXIT', _Other, Reason} -> - test_server:fail({linked_process_exited, Reason}) + ct:fail({linked_process_exited, Reason}) after 0 -> case Data of {'EXIT', {A,B}} -> - test_server:fail({A,B,N}); + ct:fail({A,B,N}); {'EXIT', Failure} -> - test_server:fail(Failure); + ct:fail(Failure); _ -> Data end @@ -676,8 +641,7 @@ otp_3924_sender(Receiver, Host, Port, Data) -> end. -data_before_close(doc) -> - ["Tests that a huge amount of data can be received before a close."]; +%% Tests that a huge amount of data can be received before a close. data_before_close(Config) when is_list(Config) -> {ok, L} = gen_tcp:listen(0, [binary]), {ok, {_, TcpPort}} = inet:sockname(L), @@ -689,7 +653,7 @@ data_before_close(Config) when is_list(Config) -> io:format("Result: ~p", [Result]); {Wrong, Result} -> io:format("Result: ~p", [Result]), - test_server:fail({wrong_count, Wrong}) + ct:fail({wrong_count, Wrong}) end, ok. @@ -714,11 +678,9 @@ make_zero_packet(N) when N rem 2 == 0 -> make_zero_packet(N) -> P = make_zero_packet(N div 2), [0, P|P]. -get_status(doc) -> - ["OTP-2924", - "test that the socket process does not crash when sys:get_status(Pid)", - "is called."]; -get_status(suite) -> []; + +%% OTP-2924. Test that the socket process does not crash when +%% sys:get_status(Pid) is called. get_status(Config) when is_list(Config) -> {ok,{socket,Pid,_,_}} = gen_tcp:listen(5678,[]), {status,Pid,_,_} = sys:get_status(Pid). @@ -726,9 +688,11 @@ get_status(Config) when is_list(Config) -> -define(RECOVER_SLEEP, 60000). -define(RETRY_SLEEP, 15000). -iter_max_socks(doc) -> - ["Open as many sockets as possible. Do this several times and check ", - "that we get the same number of sockets every time."]; +iter_max_socks() -> + [{timetrap,{minutes,30}}]. + +%% Open as many sockets as possible. Do this several times and check +%% that we get the same number of sockets every time. iter_max_socks(Config) when is_list(Config) -> N = case os:type() of {win32,_} -> 10; _ -> 20 end, %% Run on a different node in order to limit the effect if this test fails. @@ -757,7 +721,7 @@ do_iter_max_socks(N, First) when is_integer(First) -> true -> io:format("Sleeping for ~p seconds...~n", [?RETRY_SLEEP/1000]), - ?t:sleep(?RETRY_SLEEP), + ct:sleep(?RETRY_SLEEP), io:format("Trying again...~n", []), RetryMS = max_socks(), if RetryMS == First -> @@ -775,10 +739,10 @@ all_equal([Rule | T]) -> all_equal(Rule, [Rule | T]) -> all_equal(Rule, T); all_equal(_, [_ | _]) -> - ?t:sleep(?RECOVER_SLEEP), % Wait a while and *hope* that we'll - % recover so other tests won't be - % affected. - ?t:fail(max_socket_mismatch); + ct:sleep(?RECOVER_SLEEP), % Wait a while and *hope* that we'll + %% recover so other tests won't be + %% affected. + ct:fail(max_socket_mismatch); all_equal(_Rule, []) -> ok. @@ -820,21 +784,20 @@ start_remote(Name) -> Pa = filename:dirname(code:which(?MODULE)), test_server:start_node(Name, slave, [{remote, true}, {args, "-pa " ++ Pa}]). -passive_sockets(doc) -> - ["Tests that when 'the other side' on a passive socket closes, the connecting", - "side still can read until the end of data."]; +%% Tests that when 'the other side' on a passive socket closes, the +%% connecting, side still can read until the end of data. passive_sockets(Config) when is_list(Config) -> spawn_link(?MODULE, passive_sockets_server, [[{active,false}],self()]), receive {socket,Port} -> ok end, - ?t:sleep(500), + ct:sleep(500), case gen_tcp:connect("localhost", Port, [{active, false}]) of {ok, Sock} -> passive_sockets_read(Sock); Error -> - ?t:fail({"Could not connect to server", Error}) + ct:fail({"Could not connect to server", Error}) end. %% @@ -850,7 +813,7 @@ passive_sockets_read(Sock) -> gen_tcp:close(Sock); Error -> gen_tcp:close(Sock), - ?t:fail({"Did not get {error, closed} before other error", Error}) + ct:fail({"Did not get {error, closed} before other error", Error}) end. passive_sockets_server(Opts, Parent) -> @@ -860,17 +823,17 @@ passive_sockets_server(Opts, Parent) -> Parent ! {socket,Port}, passive_sockets_server_accept(LSock); Error -> - ?t:fail({"Could not create listen socket", Error}) + ct:fail({"Could not create listen socket", Error}) end. passive_sockets_server_accept(Sock) -> case gen_tcp:accept(Sock) of {ok, Socket} -> - ?t:sleep(500), % Simulate latency + timer:sleep(500), % Simulate latency passive_sockets_server_send(Socket, 5), passive_sockets_server_accept(Sock); Error -> - ?t:fail({"Could not accept connection", Error}) + ct:fail({"Could not accept connection", Error}) end. passive_sockets_server_send(Socket, 0) -> @@ -880,16 +843,15 @@ passive_sockets_server_send(Socket, X) -> Data = lists:duplicate(1024*X, $a), case gen_tcp:send(Socket, Data) of ok -> - ?t:sleep(50), % Simulate some processing. + ct:sleep(50), % Simulate some processing. passive_sockets_server_send(Socket, X-1); {error, _Reason} -> - ?t:fail("Failed to send data") + ct:fail("Failed to send data") end. -accept_closed_by_other_process(doc) -> - ["Tests the return value from gen_tcp:accept when ", - "the socket is closed from another process. (OTP-3817)"]; +%% Tests the return value from gen_tcp:accept when +%% the socket is closed from another process. (OTP-3817) accept_closed_by_other_process(Config) when is_list(Config) -> Parent = self(), {ok, ListenSocket} = gen_tcp:listen(0, []), @@ -904,7 +866,7 @@ accept_closed_by_other_process(Config) when is_list(Config) -> {Child, {error, closed}} -> ok; {Child, Other} -> - ?t:fail({"Wrong result of gen_tcp:accept", Other}) + ct:fail({"Wrong result of gen_tcp:accept", Other}) end. repeat(N, Fun) -> @@ -917,10 +879,7 @@ repeat(_, _, _) -> ok. -closed_socket(suite) -> - []; -closed_socket(doc) -> - ["Tests the response when using a closed socket as argument"]; +%% Tests the response when using a closed socket as argument. closed_socket(Config) when is_list(Config) -> {ok, LS1} = gen_tcp:listen(0, []), erlang:yield(), @@ -932,7 +891,7 @@ closed_socket(Config) when is_list(Config) -> %% in inet_db processes the 'EXIT' message from the port, %% the socket is unregistered. %% - %% test_server:sleep(test_server:seconds(2)), + %% ct:sleep({seconds,2}) %% {error, R_send} = gen_tcp:send(LS1, "data"), {error, R_recv} = gen_tcp:recv(LS1, 17), @@ -974,7 +933,7 @@ shutdown_common(Active) -> do_sort(P, []), receive Any -> - ?t:fail({unexpected_message,Any}) + ct:fail({unexpected_message,Any}) after 0 -> ok end. @@ -1055,7 +1014,7 @@ shutdown_pending(Config) when is_list(Config) -> io:format("~p\n", [Msg]), N = list_to_integer(Msg) - 5; Other -> - ?t:fail({unexpected,Other}) + ct:fail({unexpected,Other}) end, ok. @@ -1107,9 +1066,9 @@ show_econnreset_active(Config) when is_list(Config) -> {tcp_closed, S} -> ok; Other -> - ?t:fail({unexpected1, Other}) + ct:fail({unexpected1, Other}) after 1000 -> - ?t:fail({timeout, {server, no_tcp_closed}}) + ct:fail({timeout, {server, no_tcp_closed}}) end, %% Now test with option switched on. @@ -1128,14 +1087,14 @@ show_econnreset_active(Config) when is_list(Config) -> {tcp_closed, S1} -> ok; Other1 -> - ?t:fail({unexpected2, Other1}) + ct:fail({unexpected2, Other1}) after 1 -> - ?t:fail({timeout, {server, no_tcp_closed}}) + ct:fail({timeout, {server, no_tcp_closed}}) end; Other2 -> - ?t:fail({unexpected3, Other2}) + ct:fail({unexpected3, Other2}) after 1000 -> - ?t:fail({timeout, {server, no_tcp_error}}) + ct:fail({timeout, {server, no_tcp_error}}) end. show_econnreset_active_once(Config) when is_list(Config) -> @@ -1149,7 +1108,7 @@ show_econnreset_active_once(Config) when is_list(Config) -> ok = gen_tcp:close(L), ok = inet:setopts(Client, [{linger, {true, 0}}]), ok = gen_tcp:close(Client), - ok = ?t:sleep(20), + ok = ct:sleep(20), ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end, ok = inet:setopts(S, [{active, once}]), receive @@ -1158,14 +1117,14 @@ show_econnreset_active_once(Config) when is_list(Config) -> {tcp_closed, S} -> ok; Other1 -> - ?t:fail({unexpected1, Other1}) + ct:fail({unexpected1, Other1}) after 1 -> - ?t:fail({timeout, {server, no_tcp_closed}}) + ct:fail({timeout, {server, no_tcp_closed}}) end; Other2 -> - ?t:fail({unexpected2, Other2}) + ct:fail({unexpected2, Other2}) after 1000 -> - ?t:fail({timeout, {server, no_tcp_error}}) + ct:fail({timeout, {server, no_tcp_error}}) end. show_econnreset_passive(Config) when is_list(Config) -> @@ -1177,7 +1136,7 @@ show_econnreset_passive(Config) when is_list(Config) -> ok = gen_tcp:close(L), ok = inet:setopts(S, [{linger, {true, 0}}]), ok = gen_tcp:close(S), - ok = ?t:sleep(1), + ok = ct:sleep(1), {error, closed} = gen_tcp:recv(Client, 0), %% Now test with option switched on. @@ -1190,7 +1149,7 @@ show_econnreset_passive(Config) when is_list(Config) -> ok = gen_tcp:close(L1), ok = inet:setopts(S1, [{linger, {true, 0}}]), ok = gen_tcp:close(S1), - ok = ?t:sleep(1), + ok = ct:sleep(1), {error, econnreset} = gen_tcp:recv(Client1, 0). econnreset_after_sync_send(Config) when is_list(Config) -> @@ -1202,7 +1161,7 @@ econnreset_after_sync_send(Config) when is_list(Config) -> ok = gen_tcp:close(L), ok = inet:setopts(S, [{linger, {true, 0}}]), ok = gen_tcp:close(S), - ok = ?t:sleep(20), + ok = ct:sleep(20), {error, closed} = gen_tcp:send(Client, "Whatever"), %% Now test with option switched on. @@ -1215,7 +1174,7 @@ econnreset_after_sync_send(Config) when is_list(Config) -> ok = gen_tcp:close(L1), ok = inet:setopts(S1, [{linger, {true, 0}}]), ok = gen_tcp:close(S1), - ok = ?t:sleep(20), + ok = ct:sleep(20), {error, econnreset} = gen_tcp:send(Client1, "Whatever"). econnreset_after_async_send_active(Config) when is_list(Config) -> @@ -1232,23 +1191,23 @@ econnreset_after_async_send_active(Config) when is_list(Config) -> case erlang:port_info(Client, queue_size) of {queue_size, N} when N > 0 -> ok; {queue_size, 0} when OS =:= win32 -> ok; - {queue_size, 0} = T -> ?t:fail(T) + {queue_size, 0} = T -> ct:fail(T) end, ok = gen_tcp:send(S, "Whatever"), - ok = ?t:sleep(20), + ok = ct:sleep(20), ok = inet:setopts(S, [{linger, {true, 0}}]), ok = gen_tcp:close(S), - ok = ?t:sleep(20), + ok = ct:sleep(20), receive {tcp, Client, "Whatever"} -> receive {tcp_closed, Client} -> ok; Other1 -> - ?t:fail({unexpected1, Other1}) + ct:fail({unexpected1, Other1}) end; Other2 -> - ?t:fail({unexpected2, Other2}) + ct:fail({unexpected2, Other2}) end, %% Now test with option switched on. @@ -1263,13 +1222,13 @@ econnreset_after_async_send_active(Config) when is_list(Config) -> case erlang:port_info(Client1, queue_size) of {queue_size, N1} when N1 > 0 -> ok; {queue_size, 0} when OS =:= win32 -> ok; - {queue_size, 0} = T1 -> ?t:fail(T1) + {queue_size, 0} = T1 -> ct:fail(T1) end, ok = gen_tcp:send(S1, "Whatever"), - ok = ?t:sleep(20), + ok = ct:sleep(20), ok = inet:setopts(S1, [{linger, {true, 0}}]), ok = gen_tcp:close(S1), - ok = ?t:sleep(20), + ok = ct:sleep(20), receive {tcp, Client1, "Whatever"} -> receive @@ -1278,13 +1237,13 @@ econnreset_after_async_send_active(Config) when is_list(Config) -> {tcp_closed, Client1} -> ok; Other3 -> - ?t:fail({unexpected3, Other3}) + ct:fail({unexpected3, Other3}) end; Other4 -> - ?t:fail({unexpected4, Other4}) + ct:fail({unexpected4, Other4}) end; Other5 -> - ?t:fail({unexpected5, Other5}) + ct:fail({unexpected5, Other5}) end. econnreset_after_async_send_active_once(Config) when is_list(Config) -> @@ -1302,13 +1261,13 @@ econnreset_after_async_send_active_once(Config) when is_list(Config) -> case erlang:port_info(Client, queue_size) of {queue_size, N} when N > 0 -> ok; {queue_size, 0} when OS =:= win32 -> ok; - {queue_size, 0} = T -> ?t:fail(T) + {queue_size, 0} = T -> ct:fail(T) end, ok = gen_tcp:send(S, "Whatever"), - ok = ?t:sleep(20), + ok = ct:sleep(20), ok = inet:setopts(S, [{linger, {true, 0}}]), ok = gen_tcp:close(S), - ok = ?t:sleep(20), + ok = ct:sleep(20), ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end, ok = inet:setopts(Client, [{active, once}]), receive @@ -1317,10 +1276,10 @@ econnreset_after_async_send_active_once(Config) when is_list(Config) -> {tcp_closed, Client} -> ok; Other -> - ?t:fail({unexpected1, Other}) + ct:fail({unexpected1, Other}) end; Other -> - ?t:fail({unexpected2, Other}) + ct:fail({unexpected2, Other}) end. econnreset_after_async_send_passive(Config) when is_list(Config) -> @@ -1341,10 +1300,10 @@ econnreset_after_async_send_passive(Config) when is_list(Config) -> case erlang:port_info(Client, queue_size) of {queue_size, N} when N > 0 -> ok; {queue_size, 0} when OS =:= win32 -> ok; - {queue_size, 0} = T -> ?t:fail(T) + {queue_size, 0} = T -> ct:fail(T) end, ok = gen_tcp:close(S), - ok = ?t:sleep(20), + ok = ct:sleep(20), {error, closed} = gen_tcp:recv(Client, 0), %% Now test with option switched on. @@ -1360,7 +1319,7 @@ econnreset_after_async_send_passive(Config) when is_list(Config) -> ok = gen_tcp:send(S1, "Whatever"), ok = gen_tcp:send(Client1, Payload), ok = gen_tcp:close(S1), - ok = ?t:sleep(20), + ok = ct:sleep(20), {error, econnreset} = gen_tcp:recv(Client1, 0). %% @@ -1387,11 +1346,11 @@ linger_zero(Config) when is_list(Config) -> case erlang:port_info(Client, queue_size) of {queue_size, N} when N > 0 -> ok; {queue_size, 0} when OS =:= win32 -> ok; - {queue_size, 0} = T -> ?t:fail(T) + {queue_size, 0} = T -> ct:fail(T) end, ok = inet:setopts(Client, [{linger, {true, 0}}]), ok = gen_tcp:close(Client), - ok = ?t:sleep(1), + ok = ct:sleep(1), undefined = erlang:port_info(Client, connected), {error, econnreset} = gen_tcp:recv(S, PayloadSize). @@ -1466,7 +1425,7 @@ busy_send_loop(Server, Client, N) -> busy_send_2(Server, Client, N+1) after 10000 -> %% If this happens, see busy_send_srv - ?t:fail({timeout,{server,not_send,flush([])}}) + ct:fail({timeout,{server,not_send,flush([])}}) end end. @@ -1477,7 +1436,7 @@ busy_send_2(Server, Client, _N) -> {Server,[closed]} -> receive {Client,[0,{error,closed}]} -> ok end after 10000 -> - ?t:fail({timeout,{server,not_closed,flush([])}}) + ct:fail({timeout,{server,not_closed,flush([])}}) end. busy_send_srv(L, Master, Msg) -> @@ -1567,7 +1526,7 @@ busy_disconnect_active_send(S, Data) -> {error,closed} -> receive {tcp_closed,S} -> ok; - _Other -> ?t:fail() + _Other -> ct:fail(failed) end end. @@ -1646,7 +1605,7 @@ fill_sendq_loop(Server, Client, Reader) -> ("Got reader closed.~n"), ok after 3000 -> - ?t:fail({timeout,{closed,reader}}) + ct:fail({timeout,{closed,reader}}) end; {Reader,[{error,closed}]} -> io:format("Got reader closed.~n"), @@ -1654,10 +1613,10 @@ fill_sendq_loop(Server, Client, Reader) -> io:format("Got server closed~n"), ok after 3000 -> - ?t:fail({timeout,{closed,server}}) + ct:fail({timeout,{closed,server}}) end after 3000 -> - ?t:fail({timeout,{closed,[server,reader]}}) + ct:fail({timeout,{closed,[server,reader]}}) end end. @@ -1865,7 +1824,7 @@ test_prio_accept_async() -> spawn(?MODULE,priority_server,[{self(),Ref}]), Port = receive {Ref,P} -> P - after 5000 -> ?t:fail({error,"helper process timeout"}) + after 5000 -> ct:fail({error,"helper process timeout"}) end, receive after 3000 -> ok @@ -1879,15 +1838,15 @@ test_prio_accept_async() -> {Ref,{ok,[{priority,4},{tos,Tos1}]}} -> ok; {Ref,Error} -> - ?t:fail({missmatch,Error}) - after 5000 -> ?t:fail({error,"helper process timeout"}) + ct:fail({missmatch,Error}) + after 5000 -> ct:fail({error,"helper process timeout"}) end, receive {Ref,{ok,[{priority,4},{tos,Tos1}]}} -> ok; {Ref,Error2} -> - ?t:fail({missmatch,Error2}) - after 5000 -> ?t:fail({error,"helper process timeout"}) + ct:fail({missmatch,Error2}) + after 5000 -> ct:fail({error,"helper process timeout"}) end, {ok,[{priority,4},{tos,Tos2}]} = inet:getopts(Sock2,[priority,tos]), @@ -1909,10 +1868,6 @@ priority_server({Parent,Ref}) -> test_prio_fail() -> {ok,L} = gen_tcp:listen(0, [{active,false}]), {error,_} = inet:setopts(L,[{priority,1000}]), -% This error could only happen in linux kernels earlier than 2.6.24.4 -% Privilege check is now disabled and IP_TOS can never fail (only silently -% be masked). -% {error,_} = inet:setopts(L,[{tos,6 bsl 5}]), gen_tcp:close(L), ok. @@ -1924,10 +1879,7 @@ test_prio_udp() -> gen_udp:close(S), ok. -so_priority(doc) -> - ["Tests the so_priority and ip_tos options on sockets when applicable."]; -so_priority(suite) -> - []; +%% Tests the so_priority and ip_tos options on sockets when applicable. so_priority(Config) when is_list(Config) -> {ok,L} = gen_tcp:listen(0, [{active,false}]), ok = inet:setopts(L,[{priority,1}]), @@ -1947,7 +1899,7 @@ so_priority(Config) when is_list(Config) -> {unix,linux} -> case os:version() of {X,Y,_} when (X > 2) or ((X =:= 2) and (Y >= 4)) -> - ?t:fail({error, + ct:fail({error, "so_priority should work on this " "OS, but does not"}); _ -> @@ -1961,7 +1913,7 @@ so_priority(Config) when is_list(Config) -> %% Accept test utilities (suites are below) millis() -> - erlang:monotonic_time(milli_seconds). + erlang:monotonic_time(millisecond). collect_accepts(0,_) -> []; collect_accepts(N,Tmo) -> @@ -2006,10 +1958,7 @@ mktmofun(Tmo,Parent,LS) -> fun() -> Parent ! {accepted,self(), catch gen_tcp:accept(LS,Tmo)} end. %% Accept tests -primitive_accept(suite) -> - []; -primitive_accept(doc) -> - ["Test singular accept"]; +%% Test singular accept. primitive_accept(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), {ok,PortNo}=inet:port(LS), @@ -2027,10 +1976,7 @@ primitive_accept(Config) when is_list(Config) -> end. -multi_accept_close_listen(suite) -> - []; -multi_accept_close_listen(doc) -> - ["Closing listen socket when multi-accepting"]; +%% Closing listen socket when multi-accepting. multi_accept_close_listen(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2043,10 +1989,7 @@ multi_accept_close_listen(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{_,{error,closed}},{_,{error,closed}}, {_,{error,closed}},{_,{error,closed}}],4,500). -accept_timeout(suite) -> - []; -accept_timeout(doc) -> - ["Single accept with timeout"]; +%% Single accept with timeout. accept_timeout(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2054,10 +1997,7 @@ accept_timeout(Config) when is_list(Config) -> P = spawn(F), ok = ?EXPECT_ACCEPTS([{P,{error,timeout}}],1,2000). -accept_timeouts_in_order(suite) -> - []; -accept_timeouts_in_order(doc) -> - ["Check that multi-accept timeouts happen in the correct order"]; +%% Check that multi-accept timeouts happen in the correct order. accept_timeouts_in_order(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2068,10 +2008,7 @@ accept_timeouts_in_order(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}},{P2,{error,timeout}}, {P3,{error,timeout}},{P4,{error,timeout}}],infinity,2000). -accept_timeouts_in_order2(suite) -> - []; -accept_timeouts_in_order2(doc) -> - ["Check that multi-accept timeouts happen in the correct order (more)"]; +%% Check that multi-accept timeouts happen in the correct order (more). accept_timeouts_in_order2(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2082,10 +2019,7 @@ accept_timeouts_in_order2(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P3,{error,timeout}}, {P2,{error,timeout}},{P1,{error,timeout}}],infinity,2000). -accept_timeouts_in_order3(suite) -> - []; -accept_timeouts_in_order3(doc) -> - ["Check that multi-accept timeouts happen in the correct order (even more)"]; +%% Check that multi-accept timeouts happen in the correct order (even more). accept_timeouts_in_order3(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2096,11 +2030,8 @@ accept_timeouts_in_order3(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P1,{error,timeout}}, {P3,{error,timeout}},{P2,{error,timeout}}],infinity,2000). -accept_timeouts_in_order4(suite) -> - []; -accept_timeouts_in_order4(doc) -> - ["Check that multi-accept timeouts happen in the correct order after " - "mixing millsec and sec timeouts"]; +%% Check that multi-accept timeouts happen in the correct order after +%% mixing millsec and sec timeouts. accept_timeouts_in_order4(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2111,11 +2042,8 @@ accept_timeouts_in_order4(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}},{P2,{error,timeout}}, {P4,{error,timeout}},{P3,{error,timeout}}],infinity,2000). -accept_timeouts_in_order5(suite) -> - []; -accept_timeouts_in_order5(doc) -> - ["Check that multi-accept timeouts happen in the correct order after " - "mixing millsec and sec timeouts (more)"]; +%% Check that multi-accept timeouts happen in the correct order after +%% mixing millsec and sec timeouts (more). accept_timeouts_in_order5(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2126,11 +2054,8 @@ accept_timeouts_in_order5(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P1,{error,timeout}}, {P3,{error,timeout}},{P2,{error,timeout}}],infinity,2000). -accept_timeouts_in_order6(suite) -> - []; -accept_timeouts_in_order6(doc) -> - ["Check that multi-accept timeouts happen in the correct order after " - "mixing millsec and sec timeouts (even more)"]; +%% Check that multi-accept timeouts happen in the correct order after +%% mixing millsec and sec timeouts (even more). accept_timeouts_in_order6(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2141,11 +2066,8 @@ accept_timeouts_in_order6(Config) when is_list(Config) -> ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P2,{error,timeout}}, {P3,{error,timeout}},{P1,{error,timeout}}],infinity,2000). -accept_timeouts_in_order7(suite) -> - []; -accept_timeouts_in_order7(doc) -> - ["Check that multi-accept timeouts happen in the correct order after " - "mixing millsec and sec timeouts (even more++)"]; +%% Check that multi-accept timeouts happen in the correct order after +%% mixing millsec and sec timeouts (even more++). accept_timeouts_in_order7(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2162,10 +2084,7 @@ accept_timeouts_in_order7(Config) when is_list(Config) -> {P1,{error,timeout}},{P3,{error,timeout}}, {P8,{error,timeout}},{P7,{error,timeout}}],infinity,2000). -accept_timeouts_mixed(suite) -> - []; -accept_timeouts_mixed(doc) -> - ["Check that multi-accept timeouts behave correctly when mixed with successful timeouts"]; +%% Check that multi-accept timeouts behave correctly when mixed with successful timeouts. accept_timeouts_mixed(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2185,10 +2104,7 @@ accept_timeouts_mixed(Config) when is_list(Config) -> gen_tcp:connect("localhost",PortNo,[]), ok = ?EXPECT_ACCEPTS([{P4,{ok,Port1}}] when is_port(Port1),infinity,100). -killing_acceptor(suite) -> - []; -killing_acceptor(doc) -> - ["Check that single acceptor behaves as expected when killed"]; +%% Check that single acceptor behaves as expected when killed. killing_acceptor(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Pid = spawn(fun() -> erlang:display({accepted,self(),gen_tcp:accept(LS)}) end), @@ -2203,10 +2119,7 @@ killing_acceptor(Config) when is_list(Config) -> false = lists:member(accepting, L2), ok. -killing_multi_acceptors(suite) -> - []; -killing_multi_acceptors(doc) -> - ["Check that multi acceptors behaves as expected when killed"]; +%% Check that multi acceptors behaves as expected when killed. killing_multi_acceptors(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2228,10 +2141,7 @@ killing_multi_acceptors(Config) when is_list(Config) -> false = lists:member(accepting, L3), ok. -killing_multi_acceptors2(suite) -> - []; -killing_multi_acceptors2(doc) -> - ["Check that multi acceptors behaves as expected when killed (more)"]; +%% Check that multi acceptors behaves as expected when killed (more). killing_multi_acceptors2(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2265,11 +2175,8 @@ killing_multi_acceptors2(Config) when is_list(Config) -> false = lists:member(accepting, L5), ok. -several_accepts_in_one_go(suite) -> - []; -several_accepts_in_one_go(doc) -> - ["checks that multi-accept works when more than one accept can be " - "done at once (wb test of inet_driver)"]; +%% Checks that multi-accept works when more than one accept can be +%% done at once (wb test of inet_driver). several_accepts_in_one_go(Config) when is_list(Config) -> {ok,LS}=gen_tcp:listen(0,[]), Parent = self(), @@ -2312,11 +2219,8 @@ wait_until_accepting(Proc,N) -> end. -accept_system_limit(suite) -> - []; -accept_system_limit(doc) -> - ["Check that accept returns {error, system_limit} " - "(and not {error, enfile}) when running out of ports"]; +%% Check that accept returns {error, system_limit} +%% (and not {error, enfile}) when running out of ports. accept_system_limit(Config) when is_list(Config) -> {ok, LS} = gen_tcp:listen(0, []), {ok, TcpPort} = inet:port(LS), @@ -2365,10 +2269,7 @@ open_ports(L) -> end. -active_once_closed(suite) -> - []; -active_once_closed(doc) -> - ["Check that active once and tcp_close messages behave as expected"]; +%% Check that active once and tcp_close messages behave as expected. active_once_closed(Config) when is_list(Config) -> (fun() -> {Loop,A} = setup_closed_ao(), @@ -2416,75 +2317,84 @@ active_once_closed(Config) when is_list(Config) -> ok = receive {tcp_closed, A} -> ok after 1000 -> error end end)(). -send_timeout(suite) -> - []; -send_timeout(doc) -> - ["Test the send_timeout socket option"]; +%% Test the send_timeout socket option. send_timeout(Config) when is_list(Config) -> + Dir = filename:dirname(code:which(?MODULE)), + {ok,RNode} = test_server:start_node(?UNIQ_NODE_NAME, slave, + [{args,"-pa " ++ Dir}]), + %% Basic - BasicFun = - fun(AutoClose) -> - {Loop,A,RNode} = setup_timeout_sink(1000, AutoClose), - {error,timeout} = - Loop(fun() -> - Res = gen_tcp:send(A,<<1:10000>>), - %%erlang:display(Res), - Res - end), - %% Check that the socket is not busy/closed... - Error = after_send_timeout(AutoClose), - {error,Error} = gen_tcp:send(A,<<"Hej">>), - test_server:stop_node(RNode) - end, - BasicFun(false), - BasicFun(true), - %% Check timeout length + send_timeout_basic(false, RNode), + send_timeout_basic(true, RNode), + + BinData = <<1:10000>>, + + %% Check timeout length. Self = self(), Pid = spawn(fun() -> - {Loop,A,RNode} = setup_timeout_sink(1000, true), - {error,timeout} = Loop(fun() -> - Res = gen_tcp:send(A,<<1:10000>>), - %%erlang:display(Res), - Self ! Res, - Res - end), - test_server:stop_node(RNode) + A = setup_timeout_sink(RNode, 1000, true), + Send = fun() -> + Res = gen_tcp:send(A, BinData), + Self ! Res, + Res + end, + {error,timeout} = timeout_sink_loop(Send) end), Diff = get_max_diff(), io:format("Max time for send: ~p~n",[Diff]), true = (Diff > 500) and (Diff < 1500), - %% Let test_server slave die... + + %% Wait for the process to die. Mon = erlang:monitor(process, Pid), receive {'DOWN',Mon,process,Pid,_} -> ok end, + %% Check that parallell writers do not hang forever - ParaFun = - fun(AutoClose) -> - {Loop,A,RNode} = setup_timeout_sink(1000, AutoClose), - SenderFun = fun() -> - {error,Error} = - Loop(fun() -> - gen_tcp:send(A, <<1:10000>>) - end), - Self ! {error,Error} - end, - spawn_link(SenderFun), - spawn_link(SenderFun), - receive - {error,timeout} -> ok - after 10000 -> - exit(timeout) - end, - NextErr = after_send_timeout(AutoClose), - receive - {error,NextErr} -> ok - after 10000 -> - exit(timeout) - end, - {error,NextErr} = gen_tcp:send(A,<<"Hej">>), - test_server:stop_node(RNode) - end, - ParaFun(false), - ParaFun(true), + send_timeout_para(false, RNode), + send_timeout_para(true, RNode), + + test_server:stop_node(RNode), + + ok. + +send_timeout_basic(AutoClose, RNode) -> + BinData = <<1:10000>>, + + A = setup_timeout_sink(RNode, 1000, AutoClose), + Send = fun() -> gen_tcp:send(A, BinData) end, + {error,timeout} = timeout_sink_loop(Send), + + %% Check that the socket is not busy/closed... + Error = after_send_timeout(AutoClose), + {error,Error} = gen_tcp:send(A, <<"Hej">>), + ok. + +send_timeout_para(AutoClose, RNode) -> + BinData = <<1:10000>>, + + A = setup_timeout_sink(RNode, 1000, AutoClose), + Self = self(), + SenderFun = fun() -> + Send = fun() -> gen_tcp:send(A, BinData) end, + {error,Error} = timeout_sink_loop(Send), + Self ! {error,Error} + end, + spawn_link(SenderFun), + spawn_link(SenderFun), + + receive + {error,timeout} -> ok + after 10000 -> + exit(timeout) + end, + + NextErr = after_send_timeout(AutoClose), + receive + {error,NextErr} -> ok + after 10000 -> + exit(timeout) + end, + + {error,NextErr} = gen_tcp:send(A, <<"Hej">>), ok. mad_sender(S) -> @@ -2500,46 +2410,41 @@ mad_sender(S) -> flush() -> receive _X -> - %erlang:display(_X), flush() after 0 -> ok end. -send_timeout_active(suite) -> - []; -send_timeout_active(doc) -> - ["Test the send_timeout socket option for active sockets"]; +%% Test the send_timeout socket option for active sockets. send_timeout_active(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:seconds(20)), - %% Basic - BasicFun = - fun(AutoClose) -> - {Loop,A,RNode,C} = setup_active_timeout_sink(1, AutoClose), - inet:setopts(A, [{active, once}]), - Mad = spawn_link(RNode,fun() -> mad_sender(C) end), - {error,timeout} = - Loop(fun() -> - receive - {tcp, _Sock, _Data} -> - inet:setopts(A, [{active, once}]), - Res = gen_tcp:send(A,lists:duplicate(1000, $a)), - %erlang:display(Res), - Res; - Err -> - io:format("sock closed: ~p~n", [Err]), - Err - end - end), - unlink(Mad), - exit(Mad,kill), - test_server:stop_node(RNode) + Dir = filename:dirname(code:which(?MODULE)), + {ok,RNode} = test_server:start_node(?UNIQ_NODE_NAME, slave, + [{args,"-pa " ++ Dir}]), + do_send_timeout_active(false, RNode), + do_send_timeout_active(true, RNode), + test_server:stop_node(RNode), + ok. + +do_send_timeout_active(AutoClose, RNode) -> + {A,C} = setup_active_timeout_sink(RNode, 1, AutoClose), + inet:setopts(A, [{active, once}]), + Mad = spawn_link(RNode, fun() -> mad_sender(C) end), + ListData = lists:duplicate(1000, $a), + F = fun() -> + receive + {tcp, _Sock, _Data} -> + inet:setopts(A, [{active, once}]), + Res = gen_tcp:send(A, ListData), + Res; + Err -> + io:format("sock closed: ~p~n", [Err]), + Err + end end, - BasicFun(false), - flush(), - BasicFun(true), + {error,timeout} = timeout_sink_loop(F), + unlink(Mad), + exit(Mad, kill), flush(), - test_server:timetrap_cancel(Dog), ok. after_send_timeout(AutoClose) -> @@ -2581,9 +2486,9 @@ get_max_diff(Max) -> setup_closed_ao() -> Dir = filename:dirname(code:which(?MODULE)), - {ok,R} = test_server:start_node(test_default_options_slave,slave, + {ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave, [{args,"-pa " ++ Dir}]), - Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))), + Host = get_hostname(node()), {ok, L} = gen_tcp:listen(0, [{active,false},{packet,2}]), Fun = fun(F) -> receive @@ -2622,11 +2527,8 @@ setup_closed_ao() -> test_server:stop_node(R), {Loop,A}. -setup_timeout_sink(Timeout, AutoClose) -> - Dir = filename:dirname(code:which(?MODULE)), - {ok,R} = test_server:start_node(test_default_options_slave,slave, - [{args,"-pa " ++ Dir}]), - Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))), +setup_timeout_sink(RNode, Timeout, AutoClose) -> + Host = get_hostname(node()), {ok, L} = gen_tcp:listen(0, [{active,false},{packet,2}, {send_timeout,Timeout}, {send_timeout_close,AutoClose}]), @@ -2637,7 +2539,7 @@ setup_timeout_sink(Timeout, AutoClose) -> die -> ok end end, - Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]), + Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]), {ok, Port} = inet:port(L), Remote = fun(Fu) -> Pid ! {self(), Fu}, @@ -2651,36 +2553,23 @@ setup_timeout_sink(Timeout, AutoClose) -> {ok,A} = gen_tcp:accept(L), gen_tcp:send(A,"Hello"), {ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end), - Loop2 = fun(_,_,0) -> - {failure, timeout}; - (L2,F2,N) -> - Ret = F2(), - io:format("~p~n",[Ret]), - case Ret of - ok -> receive after 1 -> ok end, - L2(L2,F2,N-1); - Other -> Other - end - end, - Loop = fun(F3) -> Loop2(Loop2,F3,1000) end, - {Loop,A,R}. - -setup_active_timeout_sink(Timeout, AutoClose) -> - Dir = filename:dirname(code:which(?MODULE)), - {ok,R} = test_server:start_node(test_default_options_slave,slave, - [{args,"-pa " ++ Dir}]), - Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))), - {ok, L} = gen_tcp:listen(0, [binary,{active,false},{packet,0},{nodelay, true},{keepalive, true}, - {send_timeout,Timeout}, - {send_timeout_close,AutoClose}]), + A. + +setup_active_timeout_sink(RNode, Timeout, AutoClose) -> + Host = get_hostname(node()), + ListenOpts = [binary,{active,false},{packet,0}, + {nodelay,true},{keepalive,true}, + {send_timeout,Timeout},{send_timeout_close,AutoClose}], + {ok, L} = gen_tcp:listen(0, ListenOpts), Fun = fun(F) -> receive {From,X} when is_function(X) -> - From ! {self(),X()}, F(F); + From ! {self(),X()}, + F(F); die -> ok end end, - Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]), + Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]), {ok, Port} = inet:port(L), Remote = fun(Fu) -> Pid ! {self(), Fu}, @@ -2688,26 +2577,22 @@ setup_active_timeout_sink(Timeout, AutoClose) -> end end, {ok, C} = Remote(fun() -> - gen_tcp:connect(Host,Port, - [{active,false}]) + gen_tcp:connect(Host, Port, [{active,false}]) end), {ok,A} = gen_tcp:accept(L), - gen_tcp:send(A,"Hello"), - {ok, "H"++_} = Remote(fun() -> gen_tcp:recv(C,0) end), - Loop2 = fun(_,_,0) -> - {failure, timeout}; - (L2,F2,N) -> - Ret = F2(), - io:format("~p~n",[Ret]), - case Ret of - ok -> receive after 1 -> ok end, - L2(L2,F2,N-1); - Other -> Other - end - end, - Loop = fun(F3) -> Loop2(Loop2,F3,1000) end, - {Loop,A,R,C}. + gen_tcp:send(A, "Hello"), + {ok, "H"++_} = Remote(fun() -> gen_tcp:recv(C, 0) end), + {A,C}. +timeout_sink_loop(Action) -> + Ret = Action(), + case Ret of + ok -> + receive after 1 -> ok end, + timeout_sink_loop(Action); + Other -> + Other + end. has_superfluous_schedulers() -> case {erlang:system_info(schedulers), @@ -2718,10 +2603,8 @@ has_superfluous_schedulers() -> end. -otp_7731(suite) -> []; -otp_7731(doc) -> - "Leaking message from inet_drv {inet_reply,P,ok} " - "when a socket sending resumes working after a send_timeout"; +%% Leaking message from inet_drv {inet_reply,P,ok} +%% when a socket sending resumes working after a send_timeout. otp_7731(Config) when is_list(Config) -> ServerPid = spawn_link(?MODULE, otp_7731_server, [self()]), receive {ServerPid, ready, PortNum} -> ok end, @@ -2738,7 +2621,7 @@ otp_7731(Config) when is_list(Config) -> %% Now make sure inet_drv does not leak any internal messages. receive Msg -> - test_server:fail({unexpected, Msg}) + ct:fail({unexpected, Msg}) after 1000 -> ok end, @@ -2791,8 +2674,7 @@ otp_7731_recv(Socket) -> %% OTP-7615: TCP-ports hanging in CLOSING state when sending large %% buffer followed by a recv() that returns error due to closed %% connection. -zombie_sockets(suite) -> []; -zombie_sockets(doc) -> ["OTP-7615 Leaking closed ports."]; +%% OTP-7615 Leaking closed ports. zombie_sockets(Config) when is_list(Config) -> register(zombie_collector,self()), Calls = 10, @@ -2872,9 +2754,7 @@ zombie_serve_client(Socket, Bin) -> gen_tcp:close(Socket), zombie_collector ! {closed, Socket}. -otp_7816(suite) -> []; -otp_7816(doc) -> - "Hanging send on windows when sending iolist with more than 16 binaries."; +%% Hanging send on windows when sending iolist with more than 16 binaries. otp_7816(Config) when is_list(Config) -> Client = self(), Server = spawn_link(fun()-> otp_7816_server(Client) end), @@ -2963,8 +2843,7 @@ otp_7816_recv(CSocket, BytesLeft) -> error end. -otp_8102(doc) -> ["Receive a packet with a faulty packet header"]; -otp_8102(suite) -> []; +%% Receive a packet with a faulty packet header. otp_8102(Config) when is_list(Config) -> {ok, LSocket} = gen_tcp:listen(0, []), {ok, {_, PortNum}} = inet:sockname(LSocket), @@ -3004,8 +2883,7 @@ otp_8102_do(LSocket, PortNum, {Bin,PType}) -> gen_tcp:close(SSocket), gen_tcp:close(RSocket). -otp_9389(doc) -> ["Verify packet_size handles long HTTP header lines"]; -otp_9389(suite) -> []; +%% Verify packet_size handles long HTTP header lines. otp_9389(Config) when is_list(Config) -> {ok, LS} = gen_tcp:listen(0, [{active,false}]), {ok, {_, PortNum}} = inet:sockname(LS), @@ -3064,10 +2942,10 @@ otp_9389_loop(S, OrigLinkHdr, State) -> error({timeout,header}) end. -wrapping_oct(doc) -> - "Check that 64bit octet counters work."; -wrapping_oct(suite) -> - []; +wrapping_oct() -> + [{timetrap,{minutes,10}}]. + +%% Check that 64bit octet counters work. wrapping_oct(Config) when is_list(Config) -> {ok,Sock} = gen_tcp:listen(0,[{active,false},{mode,binary}]), {ok,Port} = inet:port(Sock), @@ -3131,3 +3009,46 @@ oct_aloop(S,X,Times) -> end. ok({ok,V}) -> V. + +get_hostname(Name) -> + "@"++Host = lists:dropwhile(fun(C) -> C =/= $@ end, atom_to_list(Name)), + Host. + +otp_13939(doc) -> + ["Check that writing to a remotely closed socket doesn't block forever " + "when exit_on_close is false."]; +otp_13939(suite) -> + []; +otp_13939(Config) when is_list(Config) -> + {Pid, Ref} = spawn_opt( + fun() -> + {ok, Listener} = gen_tcp:listen(0, [{exit_on_close, false}]), + {ok, Port} = inet:port(Listener), + + spawn_link( + fun() -> + {ok, Client} = gen_tcp:connect("localhost", Port, + [{active, false}]), + ok = gen_tcp:close(Client) + end), + + {ok, Accepted} = gen_tcp:accept(Listener), + + ok = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>), + + %% The bug surfaces when there's a delay between the send + %% operations; inet:getstat is a red herring. + timer:sleep(100), + + {error, Code} = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>), + ct:pal("gen_tcp:send returned ~p~n", [Code]) + end, [link, monitor]), + + receive + {'DOWN', Ref, process, Pid, normal} -> + ok + after 1000 -> + demonitor(Ref, [flush]), + exit(Pid, normal), + ct:fail("Server process blocked on send.") + end. diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index 8d8c953303..aa616d43d6 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. 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. @@ -17,17 +17,16 @@ %% %% %CopyrightEnd% %% -% -% test the behavior of gen_udp. Testing udp is really a very unfunny task, -% because udp is not deterministic. -% --module(gen_udp_SUITE). --include_lib("test_server/include/test_server.hrl"). +%% +%% Test the behavior of gen_udp. Testing udp is really a very unfunny task, +%% because udp is not deterministic. +%% +-module(gen_udp_SUITE). +-include_lib("common_test/include/ct.hrl"). --define(default_timeout, ?t:minutes(1)). -% XXX - we should pick a port that we _know_ is closed. That's pretty hard. +%% XXX - we should pick a port that we _know_ is closed. That's pretty hard. -define(CLOSED_PORT, 6666). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -36,17 +35,24 @@ -export([send_to_closed/1, active_n/1, buffer_size/1, binary_passive_recv/1, bad_address/1, - read_packets/1, open_fd/1, connect/1, implicit_inet6/1]). + read_packets/1, open_fd/1, connect/1, implicit_inet6/1, + local_basic/1, local_unbound/1, + local_fdopen/1, local_fdopen_unbound/1, local_abstract/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [send_to_closed, buffer_size, binary_passive_recv, bad_address, read_packets, open_fd, connect, - implicit_inet6, active_n]. + implicit_inet6, active_n, + {group, local}]. groups() -> - []. + [{local, [], + [local_basic, local_unbound, + local_fdopen, local_fdopen_unbound, local_abstract]}]. init_per_suite(Config) -> Config. @@ -54,36 +60,40 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ok. +init_per_group(local, Config) -> + case gen_udp:open(0, [local]) of + {ok,S} -> + ok = gen_udp:close(S), + Config; + {error,eafnosupport} -> + {skip, "AF_LOCAL not supported"} + end; init_per_group(_GroupName, Config) -> Config. +end_per_group(local, _Config) -> + delete_local_filenames(); end_per_group(_GroupName, Config) -> Config. init_per_testcase(_Case, Config) -> - ?line Dog=test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. %%------------------------------------------------------------- %% Send two packets to a closed port (on some systems this causes the socket %% to be closed). -send_to_closed(doc) -> - ["Tests core functionality."]; -send_to_closed(suite) -> - []; +%% Tests core functionality. send_to_closed(Config) when is_list(Config) -> - ?line {ok, Sock} = gen_udp:open(0), - ?line ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"), + {ok, Sock} = gen_udp:open(0), + ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"), timer:sleep(2), - ?line ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"), - ?line ok = gen_udp:close(Sock), + ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"), + ok = gen_udp:close(Sock), ok. @@ -91,19 +101,16 @@ send_to_closed(Config) when is_list(Config) -> %%------------------------------------------------------------- %% Test that the UDP socket buffer sizes are settable -buffer_size(suite) -> - []; -buffer_size(doc) -> - ["Test UDP buffer size setting."]; +%% Test UDP buffer size setting. buffer_size(Config) when is_list(Config) -> - ?line Len = 256, - ?line Bin = list_to_binary(lists:seq(0, Len-1)), - ?line M = 8192 div Len, - ?line Spec0 = + Len = 256, + Bin = list_to_binary(lists:seq(0, Len-1)), + M = 8192 div Len, + Spec0 = [{opt,M},{safe,M-3},{long,M+1}, {opt,2*M},{safe,2*M-3},{long,2*M+1}, {opt,4*M},{safe,4*M-3},{long,4*M+1}], - ?line Spec = + Spec = [case Tag of opt -> [{recbuf,Val*Len},{sndbuf,(Val + 2)*Len}]; @@ -115,12 +122,12 @@ buffer_size(Config) when is_list(Config) -> [truncated,emsgsize,timeout]} end || {Tag,Val} <- Spec0], %% - ?line {ok, ClientSocket} = gen_udp:open(0, [binary]), - ?line {ok, ClientPort} = inet:port(ClientSocket), - ?line Client = self(), - ?line ClientIP = {127,0,0,1}, - ?line ServerIP = {127,0,0,1}, - ?line Server = + {ok, ClientSocket} = gen_udp:open(0, [binary]), + {ok, ClientPort} = inet:port(ClientSocket), + Client = self(), + ClientIP = {127,0,0,1}, + ServerIP = {127,0,0,1}, + Server = spawn_link( fun () -> {ok, ServerSocket} = gen_udp:open(0, [binary]), @@ -130,78 +137,77 @@ buffer_size(Config) when is_list(Config) -> ServerSocket, 1, Spec), ok = gen_udp:close(ServerSocket) end), - ?line Mref = erlang:monitor(process, Server), - ?line receive - {Server,port,ServerPort} -> - ?line buffer_size_client(Server, ServerIP, ServerPort, - ClientSocket, 1, Spec) - end, - ?line ok = gen_udp:close(ClientSocket), - ?line receive - {'DOWN',Mref,_,_,normal} -> - ?line ok - end. + Mref = erlang:monitor(process, Server), + receive + {Server,port,ServerPort} -> + buffer_size_client(Server, ServerIP, ServerPort, + ClientSocket, 1, Spec) + end, + ok = gen_udp:close(ClientSocket), + receive + {'DOWN',Mref,_,_,normal} -> + ok + end. buffer_size_client(_, _, _, _, _, []) -> - ?line ok; + ok; buffer_size_client(Server, IP, Port, Socket, Cnt, [Opts|T]) when is_list(Opts) -> - ?line io:format("buffer_size_client Cnt=~w setopts ~p.~n", [Cnt,Opts]), - ?line ok = inet:setopts(Socket, Opts), - ?line Server ! {self(),setopts,Cnt}, - ?line receive {Server,setopts,Cnt} -> ok end, - ?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T); + io:format("buffer_size_client Cnt=~w setopts ~p.~n", [Cnt,Opts]), + ok = inet:setopts(Socket, Opts), + Server ! {self(),setopts,Cnt}, + receive {Server,setopts,Cnt} -> ok end, + buffer_size_client(Server, IP, Port, Socket, Cnt+1, T); buffer_size_client(Server, IP, Port, Socket, Cnt, [{B,Replies}|T]=Opts) when is_binary(B) -> - ?line io:format( - "buffer_size_client Cnt=~w send size ~w expecting ~p.~n", - [Cnt,size(B),Replies]), - ?line ok = gen_udp:send(Socket, IP, Port, <<Cnt,B/binary>>), - ?line receive - {Server,Cnt,Reply} -> - ?line Tag = - if - is_tuple(Reply) -> - element(1, Reply); - is_atom(Reply) -> - Reply - end, - ?line case lists:member(Tag, Replies) of - true -> ok; - false -> - ?line - ?t:fail({reply_mismatch,Cnt,Reply,Replies, - byte_size(B), - inet:getopts(Socket, - [sndbuf,recbuf])}) - end, - ?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T) - after 1313 -> - ?line buffer_size_client(Server, IP, Port, Socket, Cnt, Opts) - end. + io:format( + "buffer_size_client Cnt=~w send size ~w expecting ~p.~n", + [Cnt,size(B),Replies]), + ok = gen_udp:send(Socket, IP, Port, <<Cnt,B/binary>>), + receive + {Server,Cnt,Reply} -> + Tag = + if + is_tuple(Reply) -> + element(1, Reply); + is_atom(Reply) -> + Reply + end, + case lists:member(Tag, Replies) of + true -> ok; + false -> + ct:fail({reply_mismatch,Cnt,Reply,Replies, + byte_size(B), + inet:getopts(Socket, + [sndbuf,recbuf])}) + end, + buffer_size_client(Server, IP, Port, Socket, Cnt+1, T) + after 1313 -> + buffer_size_client(Server, IP, Port, Socket, Cnt, Opts) + end. buffer_size_server(_, _, _, _, _, []) -> ok; buffer_size_server(Client, IP, Port, Socket, Cnt, [Opts|T]) when is_list(Opts) -> receive {Client,setopts,Cnt} -> ok end, - ?line io:format("buffer_size_server Cnt=~w setopts ~p.~n", [Cnt,Opts]), + io:format("buffer_size_server Cnt=~w setopts ~p.~n", [Cnt,Opts]), ok = inet:setopts(Socket, Opts), Client ! {self(),setopts,Cnt}, buffer_size_server(Client, IP, Port, Socket, Cnt+1, T); buffer_size_server(Client, IP, Port, Socket, Cnt, [{B,_}|T]) when is_binary(B) -> - ?line io:format( - "buffer_size_server Cnt=~w expecting size ~w.~n", - [Cnt,size(B)]), + io:format( + "buffer_size_server Cnt=~w expecting size ~w.~n", + [Cnt,size(B)]), Client ! {self(),Cnt, case buffer_size_server_recv(Socket, IP, Port, Cnt) of D when is_binary(D) -> SizeD = byte_size(D), - ?line io:format( - "buffer_size_server Cnt=~w received size ~w.~n", - [Cnt,SizeD]), + io:format( + "buffer_size_server Cnt=~w received size ~w.~n", + [Cnt,SizeD]), case B of D -> correct; @@ -211,9 +217,9 @@ buffer_size_server(Client, IP, Port, {unexpected,D} end; Error -> - ?line io:format( - "buffer_size_server Cnt=~w received error ~w.~n", - [Cnt,Error]), + io:format( + "buffer_size_server Cnt=~w received error ~w.~n", + [Cnt,Error]), Error end}, buffer_size_server(Client, IP, Port, Socket, Cnt+1, T). @@ -236,50 +242,44 @@ buffer_size_server_recv(Socket, IP, Port, Cnt) -> %% OTP-3823 gen_udp:recv does not return address in binary mode %% -binary_passive_recv(suite) -> - []; -binary_passive_recv(doc) -> - ["OTP-3823 gen_udp:recv does not return address in binary mode"]; +%% OTP-3823 gen_udp:recv does not return address in binary mode. binary_passive_recv(Config) when is_list(Config) -> - ?line D1 = "The quick brown fox jumps over a lazy dog", - ?line D2 = list_to_binary(D1), - ?line D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>, - <<>>, $a, [[], " lazy ", <<"dog">>]], - ?line D2 = iolist_to_binary(D3), - ?line B = D2, - ?line {ok, R} = gen_udp:open(0, [binary, {active, false}]), - ?line {ok, RP} = inet:port(R), - ?line {ok, S} = gen_udp:open(0), - ?line {ok, SP} = inet:port(S), - ?line ok = gen_udp:send(S, localhost, RP, D1), - ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), - ?line ok = gen_udp:send(S, localhost, RP, D2), - ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), - ?line ok = gen_udp:send(S, localhost, RP, D3), - ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), - ?line ok = gen_udp:close(S), - ?line ok = gen_udp:close(R), + D1 = "The quick brown fox jumps over a lazy dog", + D2 = list_to_binary(D1), + D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>, + <<>>, $a, [[], " lazy ", <<"dog">>]], + D2 = iolist_to_binary(D3), + B = D2, + {ok, R} = gen_udp:open(0, [binary, {active, false}]), + {ok, RP} = inet:port(R), + {ok, S} = gen_udp:open(0), + {ok, SP} = inet:port(S), + ok = gen_udp:send(S, localhost, RP, D1), + {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), + ok = gen_udp:send(S, localhost, RP, D2), + {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), + ok = gen_udp:send(S, localhost, RP, D3), + {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1), + ok = gen_udp:close(S), + ok = gen_udp:close(R), ok. %%------------------------------------------------------------- %% OTP-3836 inet_udp crashes when IP-address is larger than 255. -bad_address(suite) -> - []; -bad_address(doc) -> - ["OTP-3836 inet_udp crashes when IP-address is larger than 255."]; +%% OTP-3836 inet_udp crashes when IP-address is larger than 255. bad_address(Config) when is_list(Config) -> - ?line {ok, R} = gen_udp:open(0), - ?line {ok, RP} = inet:port(R), - ?line {ok, S} = gen_udp:open(0), - ?line {ok, _SP} = inet:port(S), - ?line {'EXIT', badarg} = + {ok, R} = gen_udp:open(0), + {ok, RP} = inet:port(R), + {ok, S} = gen_udp:open(0), + {ok, _SP} = inet:port(S), + {'EXIT', badarg} = (catch gen_udp:send(S, {127,0,0,1,0}, RP, "void")), - ?line {'EXIT', badarg} = + {'EXIT', badarg} = (catch gen_udp:send(S, {127,0,0,256}, RP, "void")), - ?line ok = gen_udp:close(S), - ?line ok = gen_udp:close(R), + ok = gen_udp:close(S), + ok = gen_udp:close(R), ok. @@ -298,8 +298,7 @@ bad_address(Config) when is_list(Config) -> %% What happens on the SMP emulator remains to be seen... %% -read_packets(doc) -> - ["OTP-6249 UDP option for number of packet reads."]; +%% OTP-6249 UDP option for number of packet reads. read_packets(Config) when is_list(Config) -> case erlang:system_info(smp_support) of false -> @@ -311,35 +310,35 @@ read_packets(Config) when is_list(Config) -> end. read_packets_1() -> - ?line N1 = 5, - ?line N2 = 7, - ?line {ok,R} = gen_udp:open(0, [{read_packets,N1}]), - ?line {ok,RP} = inet:port(R), - ?line {ok,Node} = start_node(gen_udp_SUITE_read_packets), - ?line Die = make_ref(), - ?line Loop = erlang:spawn_link(fun () -> infinite_loop(Die) end), + N1 = 5, + N2 = 7, + {ok,R} = gen_udp:open(0, [{read_packets,N1}]), + {ok,RP} = inet:port(R), + {ok,Node} = start_node(gen_udp_SUITE_read_packets), + Die = make_ref(), + Loop = erlang:spawn_link(fun () -> infinite_loop(Die) end), %% - ?line Msgs1 = [erlang:integer_to_list(M) || M <- lists:seq(1, N1*3)], - ?line [V1|_] = read_packets_test(R, RP, Msgs1, Node), - ?line {ok,[{read_packets,N1}]} = inet:getopts(R, [read_packets]), + Msgs1 = [erlang:integer_to_list(M) || M <- lists:seq(1, N1*3)], + [V1|_] = read_packets_test(R, RP, Msgs1, Node), + {ok,[{read_packets,N1}]} = inet:getopts(R, [read_packets]), %% - ?line ok = inet:setopts(R, [{read_packets,N2}]), - ?line Msgs2 = [erlang:integer_to_list(M) || M <- lists:seq(1, N2*3)], - ?line [V2|_] = read_packets_test(R, RP, Msgs2, Node), - ?line {ok,[{read_packets,N2}]} = inet:getopts(R, [read_packets]), + ok = inet:setopts(R, [{read_packets,N2}]), + Msgs2 = [erlang:integer_to_list(M) || M <- lists:seq(1, N2*3)], + [V2|_] = read_packets_test(R, RP, Msgs2, Node), + {ok,[{read_packets,N2}]} = inet:getopts(R, [read_packets]), %% - ?line stop_node(Node), - ?line Mref = erlang:monitor(process, Loop), - ?line Loop ! Die, - ?line receive - {'DOWN',Mref,_,_, normal} -> - case {V1,V2} of - {N1,N2} -> - ok; - _ when V1 =/= N1, V2 =/= N2 -> - ok - end - end. + stop_node(Node), + Mref = erlang:monitor(process, Loop), + Loop ! Die, + receive + {'DOWN',Mref,_,_, normal} -> + case {V1,V2} of + {N1,N2} -> + ok; + _ when V1 =/= N1, V2 =/= N2 -> + ok + end + end. infinite_loop(Die) -> receive @@ -407,21 +406,21 @@ read_packets_recv(N) -> read_packets_verify(R, SP, Msg, Trace) -> lists:reverse( - lists:sort(read_packets_verify(R, SP, Msg, Trace, 0))). - + lists:sort(read_packets_verify(R, SP, Msg, Trace, 0))). + read_packets_verify(R, SP, Msgs, [{trace,Self,OutIn,_}|Trace], M) when Self =:= self(), OutIn =:= out; Self =:= self(), OutIn =:= in -> push(M, read_packets_verify(R, SP, Msgs, Trace, 0)); read_packets_verify(R, SP, [Msg|Msgs], - [{trace,Self,'receive',{udp,R,{127,0,0,1},SP,Msg}} - |Trace], M) + [{trace,Self,'receive',{udp,R,{127,0,0,1},SP,Msg}} + |Trace], M) when Self =:= self() -> read_packets_verify(R, SP, Msgs, Trace, M+1); read_packets_verify(_R, _SP, [], [], M) -> push(M, []); read_packets_verify(_R, _SP, Msgs, Trace, M) -> - ?t:fail({read_packets_verify,mismatch,Msgs,Trace,M}). + ct:fail({read_packets_verify,mismatch,Msgs,Trace,M}). push(0, Vs) -> Vs; @@ -438,10 +437,7 @@ flush() -> -open_fd(suite) -> - []; -open_fd(doc) -> - ["Test that the 'fd' option works"]; +%% Test that the 'fd' option works. open_fd(Config) when is_list(Config) -> Msg = "Det gör ont när knoppar brista. Varför skulle annars våren tveka?", Addr = {127,0,0,1}, @@ -460,10 +456,10 @@ open_fd(Config) when is_list(Config) -> {udp,S3,Addr,P2,Msg} -> ok after 1000 -> - ?t:fail(io_lib:format("~w", [flush()])) + ct:fail(io_lib:format("~w", [flush()])) end after 1000 -> - ?t:fail(io_lib:format("~w", [flush()])) + ct:fail(io_lib:format("~w", [flush()])) end. active_n(Config) when is_list(Config) -> @@ -569,88 +565,228 @@ active_n(Config) when is_list(Config) -> ok = gen_udp:close(S1), ok. -% -% Utils -% + +local_basic(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + CFile = local_filename(client), + CAddr = {local,bin_filename(CFile)}, + _ = file:delete(SFile), + _ = file:delete(CFile), + %% + S = ok(gen_udp:open(0, [{ifaddr,{local,SFile}},{active,false}])), + C = ok(gen_udp:open(0, [{ifaddr,{local,CFile}},{active,false}])), + SAddr = ok(inet:sockname(S)), + CAddr = ok(inet:sockname(C)), + local_handshake(S, SAddr, C, CAddr), + ok = gen_udp:close(S), + ok = gen_udp:close(C), + %% + ok = file:delete(SFile), + ok = file:delete(CFile), + ok. + +local_unbound(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + %% + S = ok(gen_udp:open(0, [{ifaddr,SAddr},{active,false}])), + C = ok(gen_udp:open(0, [local,{active,false}])), + SAddr = ok(inet:sockname(S)), + local_handshake(S, SAddr, C, undefined), + ok = gen_udp:close(S), + ok = gen_udp:close(C), + %% + ok = file:delete(SFile), + ok. + +local_fdopen(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + CFile = local_filename(client), + CAddr = {local,bin_filename(CFile)}, + _ = file:delete(SFile), + _ = file:delete(CFile), + %% + S0 = ok(gen_udp:open(0, [{ifaddr,SAddr},{active,false}])), + C = ok(gen_udp:open(0, [{ifaddr,{local,CFile}},{active,false}])), + SAddr = ok(inet:sockname(S0)), + CAddr = ok(inet:sockname(C)), + Fd = ok(prim_inet:getfd(S0)), + S = ok(gen_udp:open(0, [{fd,Fd},local,{active,false}])), + SAddr = ok(inet:sockname(S)), + local_handshake(S, SAddr, C, CAddr), + ok = gen_udp:close(S), + ok = gen_udp:close(S0), + ok = gen_udp:close(C), + %% + ok = file:delete(SFile), + ok = file:delete(CFile), + ok. + +local_fdopen_unbound(_Config) -> + SFile = local_filename(server), + SAddr = {local,bin_filename(SFile)}, + _ = file:delete(SFile), + %% + S = ok(gen_udp:open(0, [{ifaddr,SAddr},{active,false}])), + C0 = ok(gen_udp:open(0, [local,{active,false}])), + SAddr = ok(inet:sockname(S)), + Fd = ok(prim_inet:getfd(C0)), + C = ok(gen_udp:open(0, [{fd,Fd},local,{active,false}])), + local_handshake(S, SAddr, C, undefined), + ok = gen_udp:close(S), + ok = gen_udp:close(C), + ok = gen_udp:close(C0), + %% + ok = file:delete(SFile), + ok. + +local_abstract(_Config) -> + case os:type() of + {unix,linux} -> + S = ok(gen_udp:open(0, [{ifaddr,{local,<<>>}},{active,false}])), + C = ok(gen_udp:open(0, [{ifaddr,{local,<<>>}},{active,false}])), + {local,_} = SAddr = ok(inet:sockname(S)), + {local,_} = CAddr = ok(inet:sockname(C)), + local_handshake(S, SAddr, C, CAddr), + ok = gen_udp:close(S), + ok = gen_udp:close(C), + ok; + _ -> + {skip,"AF_LOCAL Abstract Addresses only supported on Linux"} + end. + + +local_handshake(S, SAddr, C, CAddr) -> + SData = "9876543210", + CData = "0123456789", + ok = gen_udp:send(C, SAddr, 0, CData), + case ok(gen_tcp:recv(S, 112)) of + {{unspec,<<>>}, 0, CData} when CAddr =:= undefined -> + ok; + {{local,<<>>}, 0, CData} when CAddr =:= undefined -> + ok; + {CAddr, 0, CData} when CAddr =/= undefined -> + ok = gen_udp:send(S, CAddr, 0, SData), + {SAddr, 0, SData} = ok(gen_tcp:recv(C, 112)), + ok + + end. + +%% +%% Utils +%% + start_node(Name) -> Pa = filename:dirname(code:which(?MODULE)), - ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]). + test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). -connect(suite) -> - []; -connect(doc) -> - ["Test that connect/3 has effect"]; +%% Test that connect/3 has effect. connect(Config) when is_list(Config) -> - ?line Addr = {127,0,0,1}, - ?line {ok,S1} = gen_udp:open(0), - ?line {ok,P1} = inet:port(S1), - ?line {ok,S2} = gen_udp:open(0), - ?line ok = inet:setopts(S2, [{active,false}]), - ?line ok = gen_udp:close(S1), - ?line ok = gen_udp:connect(S2, Addr, P1), - ?line ok = gen_udp:send(S2, <<16#deadbeef:32>>), - ?line ok = case gen_udp:recv(S2, 0, 5) of - {error,econnrefused} -> ok; - {error,econnreset} -> ok; - Other -> Other - end, + Addr = {127,0,0,1}, + {ok,S1} = gen_udp:open(0), + {ok,P1} = inet:port(S1), + {ok,S2} = gen_udp:open(0), + ok = inet:setopts(S2, [{active,false}]), + ok = gen_udp:close(S1), + ok = gen_udp:connect(S2, Addr, P1), + ok = gen_udp:send(S2, <<16#deadbeef:32>>), + ok = case gen_udp:recv(S2, 0, 500) of + {error,econnrefused} -> ok; + {error,econnreset} -> ok; + Other -> Other + end, ok. implicit_inet6(Config) when is_list(Config) -> - ?line Host = ok(inet:gethostname()), - ?line - case inet:getaddr(Host, inet6) of - {ok,Addr} -> - ?line implicit_inet6(Host, Addr); - {error,Reason} -> - {skip, - "Can not look up IPv6 address: " - ++atom_to_list(Reason)} - end. + Host = ok(inet:gethostname()), + case inet:getaddr(Host, inet6) of + {ok,Addr} -> + implicit_inet6(Host, Addr); + {error,Reason} -> + {skip, + "Can not look up IPv6 address: " + ++atom_to_list(Reason)} + end. implicit_inet6(Host, Addr) -> - ?line Active = {active,false}, - ?line - case gen_udp:open(0, [inet6,Active]) of - {ok,S1} -> - ?line Loopback = {0,0,0,0,0,0,0,1}, - ?line io:format("~s ~p~n", ["::1",Loopback]), - ?line implicit_inet6(S1, Active, Loopback), - ?line ok = gen_udp:close(S1), - %% - ?line Localhost = "localhost", - ?line Localaddr = ok(inet:getaddr(Localhost, inet6)), - ?line io:format("~s ~p~n", [Localhost,Localaddr]), - ?line S2 = ok(gen_udp:open(0, [{ip,Localaddr},Active])), - ?line implicit_inet6(S2, Active, Localaddr), - ?line ok = gen_udp:close(S2), - %% - ?line io:format("~s ~p~n", [Host,Addr]), - ?line S3 = ok(gen_udp:open(0, [{ifaddr,Addr},Active])), - ?line implicit_inet6(S3, Active, Addr), - ?line ok = gen_udp:close(S3); - _ -> - {skip,"IPv6 not supported"} - end. + Active = {active,false}, + Loopback = {0,0,0,0,0,0,0,1}, + case gen_udp:open(0, [inet6,Active,{ip, Loopback}]) of + {ok,S1} -> + io:format("~s ~p~n", ["::1",Loopback]), + implicit_inet6(S1, Active, Loopback), + ok = gen_udp:close(S1), + %% + Localaddr = ok(get_localaddr()), + S2 = ok(gen_udp:open(0, [{ip,Localaddr},Active])), + implicit_inet6(S2, Active, Localaddr), + ok = gen_udp:close(S2), + %% + io:format("~s ~p~n", [Host,Addr]), + S3 = ok(gen_udp:open(0, [{ifaddr,Addr},Active])), + implicit_inet6(S3, Active, Addr), + ok = gen_udp:close(S3); + _ -> + {skip,"IPv6 not supported"} + end. implicit_inet6(S1, Active, Addr) -> - ?line P1 = ok(inet:port(S1)), - ?line S2 = ok(gen_udp:open(0, [inet6,Active])), - ?line P2 = ok(inet:port(S2)), - ?line ok = gen_udp:connect(S2, Addr, P1), - ?line ok = gen_udp:connect(S1, Addr, P2), - ?line {Addr,P2} = ok(inet:peername(S1)), - ?line {Addr,P1} = ok(inet:peername(S2)), - ?line {Addr,P1} = ok(inet:sockname(S1)), - ?line {Addr,P2} = ok(inet:sockname(S2)), - ?line ok = gen_udp:send(S1, Addr, P2, "ping"), - ?line {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)), - ?line ok = gen_udp:send(S2, Addr, P1, "pong"), - ?line {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)), - ?line ok = gen_udp:close(S2). - -ok({ok,V}) -> V. + P1 = ok(inet:port(S1)), + S2 = ok(gen_udp:open(0, [inet6,Active])), + P2 = ok(inet:port(S2)), + ok = gen_udp:connect(S2, Addr, P1), + ok = gen_udp:connect(S1, Addr, P2), + {Addr,P2} = ok(inet:peername(S1)), + {Addr,P1} = ok(inet:peername(S2)), + {Addr,P1} = ok(inet:sockname(S1)), + {Addr,P2} = ok(inet:sockname(S2)), + ok = gen_udp:send(S1, Addr, P2, "ping"), + {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)), + ok = gen_udp:send(S2, Addr, P1, "pong"), + {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)), + ok = gen_udp:close(S2). + +ok({ok,V}) -> V; +ok(NotOk) -> + try throw(not_ok) + catch + Thrown -> + erlang:raise( + error, {Thrown, NotOk}, tl(erlang:get_stacktrace())) + end. + + +local_filename(Tag) -> + "/tmp/" ?MODULE_STRING "_" ++ os:getpid() ++ "_" ++ atom_to_list(Tag). + +bin_filename(String) -> + unicode:characters_to_binary(String, file:native_name_encoding()). + +delete_local_filenames() -> + _ = + [file:delete(F) || + F <- + filelib:wildcard( + "/tmp/" ?MODULE_STRING "_" ++ os:getpid() ++ "_*")], + ok. + +get_localaddr() -> + get_localaddr(["localhost", "localhost6", "ip6-localhost"]). + +get_localaddr([]) -> + {error, localaddr_not_found}; +get_localaddr([Localhost|Ls]) -> + case inet:getaddr(Localhost, inet6) of + {ok, LocalAddr} -> + io:format("~s ~p~n", [Localhost, LocalAddr]), + {ok, LocalAddr}; + _ -> + get_localaddr(Ls) + end. diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl index 73ee86eba4..0e7b7adc47 100644 --- a/lib/kernel/test/global_SUITE.erl +++ b/lib/kernel/test/global_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-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. @@ -19,8 +19,6 @@ %% -module(global_SUITE). -%-define(line_trace, 1). - -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, init_per_suite/1, end_per_suite/1, names/1, names_hidden/1, locks/1, locks_hidden/1, @@ -51,7 +49,7 @@ -compile(export_all). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(NODES, [node()|nodes()]). @@ -61,7 +59,8 @@ -define(GLOBAL_LOCK, global). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}]. all() -> case init:get_argument(ring_line) of @@ -86,10 +85,10 @@ groups() -> ring]}]. init_per_group(_GroupName, Config) -> - Config. + Config. end_per_group(_GroupName, Config) -> - Config. + Config. init_per_suite(Config) -> Config. @@ -99,9 +98,9 @@ end_per_suite(_Config) -> -define(TESTCASE, testcase_name). --define(testcase, ?config(?TESTCASE, Config)). +-define(testcase, proplists:get_value(?TESTCASE, Config)). -define(nodes_tag, '$global_nodes'). --define(registered, ?config(registered, Config)). +-define(registered, proplists:get_value(registered, Config)). init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> ok = gen_server:call(global_name_server, high_level_trace_start,infinity), @@ -115,16 +114,16 @@ init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> end_per_testcase(_Case, Config) -> ct:log("Calling end_per_testcase!",[]), - ?line write_high_level_trace(Config), - ?line _ = + write_high_level_trace(Config), + _ = gen_server:call(global_name_server, high_level_trace_stop, infinity), [global:unregister_name(N) || N <- global:registered_names()], - ?line InitRegistered = ?registered, - ?line Registered = registered(), - ?line [io:format("~s local names: ~p~n", [What, N]) || - {What, N} <- [{"Added", Registered -- InitRegistered}, - {"Removed", InitRegistered -- Registered}], - N =/= []], + InitRegistered = ?registered, + Registered = registered(), + [io:format("~s local names: ~p~n", [What, N]) || + {What, N} <- [{"Added", Registered -- InitRegistered}, + {"Removed", InitRegistered -- Registered}], + N =/= []], ok. @@ -147,12 +146,11 @@ end_per_testcase(_Case, Config) -> %%% and releases the lock. Now the name should exist on both our own node %%% and on the slave node (we wait until that is true; it seems that we %%% can do rpc calls to another node before the connection is really up). -register_1(suite) -> []; register_1(Config) when is_list(Config) -> Timeout = 15, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), P = spawn_link(?MODULE, lock_global, [self(), Config]), receive {P, ok} -> @@ -161,7 +159,7 @@ register_1(Config) when is_list(Config) -> end, P ! step2, io:format("p1: sent step2~n"), - ?line yes = global:register_name(foo, self()), + yes = global:register_name(foo, self()), io:format("p1: registered~n"), P ! step3, receive @@ -172,11 +170,11 @@ register_1(Config) when is_list(Config) -> I =:= I2 -> ok; true -> - test_server:fail({notsync, I, I2}) + ct:fail({notsync, I, I2}) end, - ?line _ = global:unregister_name(foo), + _ = global:unregister_name(foo), write_high_level_trace(Config), - ?line init_condition(Config), + init_condition(Config), ok. lock_global(Parent, Config) -> @@ -203,7 +201,7 @@ lock_global(Parent, Config) -> io:format("p2: received step3~n"), I = global:whereis_name(foo), io:format("p2: name ~p~n", [I]), - ?line ?UNTIL(I =:= rpc:call(N1, global, whereis_name, [foo])), + ?UNTIL(I =:= rpc:call(N1, global, whereis_name, [foo])), I2 = I, slave:stop(N1), io:format("p2: name2 ~p~n", [I2]), @@ -216,75 +214,73 @@ lock_global(Parent, Config) -> %%% 'try_again_locker' would be called, and this time cause both 1 and 2 %%% to obtain a lock for 'global' on node 3, which would keep the %%% name registry from ever becoming consistent again. -both_known_1(suite) -> []; both_known_1(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), - ?line OrigNames = global:registered_names(), + OrigNames = global:registered_names(), - ?line [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], slave, Config), + [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], slave, Config), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - ?line rpc_disconnect_node(Cp1, Cp2, Config), + rpc_disconnect_node(Cp1, Cp2, Config), - ?line {_Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [p1]), - ?line {_Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [p2]), + {_Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [p1]), + {_Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [p2]), - ?line Names10 = rpc:call(Cp1, global, registered_names, []), - ?line Names20 = rpc:call(Cp2, global, registered_names, []), - ?line Names30 = rpc:call(Cp3, global, registered_names, []), + Names10 = rpc:call(Cp1, global, registered_names, []), + Names20 = rpc:call(Cp2, global, registered_names, []), + Names30 = rpc:call(Cp3, global, registered_names, []), Names1 = Names10 -- OrigNames, Names2 = Names20 -- OrigNames, Names3 = Names30 -- OrigNames, - ?line [p1] = lists:sort(Names1), - ?line [p2] = lists:sort(Names2), - ?line [p1, p2] = lists:sort(Names3), + [p1] = lists:sort(Names1), + [p2] = lists:sort(Names2), + [p1, p2] = lists:sort(Names3), - ?line Locker = spawn(Cp3, ?MODULE, lock_global2, [{global, l3}, - self()]), + Locker = spawn(Cp3, ?MODULE, lock_global2, [{global, l3}, + self()]), - ?line receive - {locked, S} -> - true = S - end, + receive + {locked, S} -> + true = S + end, - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2]), + pong = rpc:call(Cp1, net_adm, ping, [Cp2]), %% Bring cp1 and cp2 together, while someone has locked global. %% They will now loop in 'loop_locker'. - ?line Names10_2 = rpc:call(Cp1, global, registered_names, []), - ?line Names20_2 = rpc:call(Cp2, global, registered_names, []), - ?line Names30_2 = rpc:call(Cp3, global, registered_names, []), + Names10_2 = rpc:call(Cp1, global, registered_names, []), + Names20_2 = rpc:call(Cp2, global, registered_names, []), + Names30_2 = rpc:call(Cp3, global, registered_names, []), Names1_2 = Names10_2 -- OrigNames, Names2_2 = Names20_2 -- OrigNames, Names3_2 = Names30_2 -- OrigNames, - ?line [p1] = lists:sort(Names1_2), - ?line [p2] = lists:sort(Names2_2), - ?line [p1, p2] = lists:sort(Names3_2), + [p1] = lists:sort(Names1_2), + [p2] = lists:sort(Names2_2), + [p1, p2] = lists:sort(Names3_2), %% Let go of the lock, and expect the lockers to resolve the name %% registry. Locker ! {ok, self()}, - ?line ?UNTIL(begin - ?line Names10_3 = rpc:call(Cp1, global, registered_names, []), - ?line Names20_3 = rpc:call(Cp2, global, registered_names, []), - ?line Names30_3 = rpc:call(Cp3, global, registered_names, []), - + Names10_3 = rpc:call(Cp1, global, registered_names, []), + Names20_3 = rpc:call(Cp2, global, registered_names, []), + Names30_3 = rpc:call(Cp3, global, registered_names, []), + Names1_3 = Names10_3 -- OrigNames, Names2_3 = Names20_3 -- OrigNames, Names3_3 = Names30_3 -- OrigNames, - + N1 = lists:sort(Names1_3), N2 = lists:sort(Names2_3), N3 = lists:sort(Names3_3), @@ -296,51 +292,49 @@ both_known_1(Config) when is_list(Config) -> stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. -lost_unregister(suite) -> []; -lost_unregister(doc) -> - ["OTP-6428. An unregistered name reappears."]; +%% OTP-6428. An unregistered name reappears. lost_unregister(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), - ?line {ok, B} = start_node(b, Config), - ?line {ok, C} = start_node(c, Config), + {ok, B} = start_node(b, Config), + {ok, C} = start_node(c, Config), Nodes = [node(), B, C], - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % start a proc and register it - ?line {Pid, yes} = start_proc(test), + %% start a proc and register it + {Pid, yes} = start_proc(test), - ?line ?UNTIL(Pid =:= global:whereis_name(test)), - ?line check_everywhere(Nodes, test, Config), + ?UNTIL(Pid =:= global:whereis_name(test)), + check_everywhere(Nodes, test, Config), - ?line rpc_disconnect_node(B, C, Config), - ?line check_everywhere(Nodes, test, Config), - ?line _ = rpc:call(B, global, unregister_name, [test]), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line Pid = rpc:call(C, global, whereis_name, [test]), - ?line check_everywhere(Nodes--[C], test, Config), - ?line pong = rpc:call(B, net_adm, ping, [C]), + rpc_disconnect_node(B, C, Config), + check_everywhere(Nodes, test, Config), + _ = rpc:call(B, global, unregister_name, [test]), + ?UNTIL(undefined =:= global:whereis_name(test)), + Pid = rpc:call(C, global, whereis_name, [test]), + check_everywhere(Nodes--[C], test, Config), + pong = rpc:call(B, net_adm, ping, [C]), %% Now the name has reappeared on node B. - ?line ?UNTIL(Pid =:= global:whereis_name(test)), - ?line check_everywhere(Nodes, test, Config), + ?UNTIL(Pid =:= global:whereis_name(test)), + check_everywhere(Nodes, test, Config), exit_p(Pid), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line check_everywhere(Nodes, test, Config), + ?UNTIL(undefined =:= global:whereis_name(test)), + check_everywhere(Nodes, test, Config), write_high_level_trace(Config), stop_node(B), stop_node(C), - ?line init_condition(Config), + init_condition(Config), ok. -define(UNTIL_LOOP, 300). @@ -350,7 +344,7 @@ lost_unregister(Config) when is_list(Config) -> init_high_level_trace(Time) -> Mul = try test_server:timetrap_scale_factor() - catch _:_ -> 1 + catch _:_ -> 1 end, put(?end_tag, msec() + Time * Mul * 1000), %% Assures that started nodes start the high level trace automatically. @@ -395,7 +389,7 @@ write_high_level_trace(Nodes, Config) -> %% 'info' returns more than the trace, which is nice. Data = [{Node, {info, rpc:call(Node, global, info, [])}} || Node <- Nodes], - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), DataFile = filename:join([Dir, lists:concat(["global_", ?testcase])]), file:write_file(DataFile, term_to_binary({high_level_trace, When, Data})). @@ -413,37 +407,35 @@ lock_global2(Id, Parent) -> %% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3] %%----------------------------------------------------------------- -%cp1 - cp3 are started, and the name 'test' registered for a process on -%test_server. Then it is checked that the name is registered on all -%nodes, using whereis_name. Check that the same -%name can't be registered with another value. Exit the registered -%process and check that the name disappears. Register a new process -%(Pid2) under the name 'test'. Let another new process (Pid3) -%reregister itself under the same name. Test global:send/2. Test -%unregister. Kill Pid3. Start a process (Pid6) on cp3, -%register it as 'test', stop cp1 - cp3 and check that 'test' disappeared. -%Kill Pid2 and check that 'test' isn't registered. - -names(suite) -> []; +%% cp1 - cp3 are started, and the name 'test' registered for a process on +%% test_server. Then it is checked that the name is registered on all +%% nodes, using whereis_name. Check that the same +%% name can't be registered with another value. Exit the registered +%% process and check that the name disappears. Register a new process +%% (Pid2) under the name 'test'. Let another new process (Pid3) +%% reregister itself under the same name. Test global:send/2. Test +%% unregister. Kill Pid3. Start a process (Pid6) on cp3, +%% register it as 'test', stop cp1 - cp3 and check that 'test' disappeared. +%% Kill Pid2 and check that 'test' isn't registered. + names(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_node(cp3, Config), + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_node(cp3, Config), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % start a proc and register it - ?line {Pid, yes} = start_proc(test), + %% start a proc and register it + {Pid, yes} = start_proc(test), - % test that it is registered at all nodes - ?line - ?UNTIL(begin + %% test that it is registered at all nodes + ?UNTIL(begin (Pid =:= global:whereis_name(test)) and (Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and (Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and @@ -451,156 +443,148 @@ names(Config) when is_list(Config) -> ([test] =:= global:registered_names() -- OrigNames) end), - % try to register the same name - ?line no = global:register_name(test, self()), - ?line no = rpc:call(Cp1, global, register_name, [test, self()]), + %% try to register the same name + no = global:register_name(test, self()), + no = rpc:call(Cp1, global, register_name, [test, self()]), - % let process exit, check that it is unregistered automatically + %% let process exit, check that it is unregistered automatically exit_p(Pid), - ?line - ?UNTIL((undefined =:= global:whereis_name(test)) and + ?UNTIL((undefined =:= global:whereis_name(test)) and (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp3, global, whereis_name, [test]))), - % test re_register - ?line {Pid2, yes} = start_proc(test), - ?line ?UNTIL(Pid2 =:= rpc:call(Cp3, global, whereis_name, [test])), + %% test re_register + {Pid2, yes} = start_proc(test), + ?UNTIL(Pid2 =:= rpc:call(Cp3, global, whereis_name, [test])), Pid3 = rpc:call(Cp3, ?MODULE, start_proc2, [test]), - ?line ?UNTIL(Pid3 =:= rpc:call(Cp3, global, whereis_name, [test])), + ?UNTIL(Pid3 =:= rpc:call(Cp3, global, whereis_name, [test])), Pid3 = global:whereis_name(test), - % test sending + %% test sending global:send(test, {ping, self()}), receive {pong, Cp3} -> ok after - 2000 -> test_server:fail(timeout1) + 2000 -> ct:fail(timeout1) end, rpc:call(Cp1, global, send, [test, {ping, self()}]), receive {pong, Cp3} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line _ = global:unregister_name(test), - ?line - ?UNTIL((undefined =:= global:whereis_name(test)) and + _ = global:unregister_name(test), + ?UNTIL((undefined =:= global:whereis_name(test)) and (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp3, global, whereis_name, [test]))), exit_p(Pid3), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?UNTIL(undefined =:= global:whereis_name(test)), - % register a proc - ?line {_Pid6, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), + %% register a proc + {_Pid6, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), write_high_level_trace(Config), - % stop the nodes, and make sure names are released. + + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?UNTIL(undefined =:= global:whereis_name(test)), exit_p(Pid2), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line init_condition(Config), + ?UNTIL(undefined =:= global:whereis_name(test)), + init_condition(Config), ok. -names_hidden(suite) -> []; -names_hidden(doc) -> - ["Tests that names on a hidden node doesn't interfere with names on " - "visible nodes."]; +%% Tests that names on a hidden node doesn't interfere with names on +%% visible nodes. names_hidden(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), - ?line OrigNodes = nodes(), - - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_hidden_node(cp3, Config), - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp3]), - ?line pong = rpc:call(Cp3, net_adm, ping, [Cp2]), - ?line pong = rpc:call(Cp3, net_adm, ping, [node()]), - - ?line [] = [Cp1, Cp2 | OrigNodes] -- nodes(), - - % start a proc on hidden node and register it - ?line {HPid, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), - ?line Cp3 = node(HPid), - - % Check that it didn't get registered on visible nodes - ?line - ?UNTIL((undefined =:= global:whereis_name(test)) and + init_condition(Config), + OrigNames = global:registered_names(), + OrigNodes = nodes(), + + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_hidden_node(cp3, Config), + pong = rpc:call(Cp1, net_adm, ping, [Cp3]), + pong = rpc:call(Cp3, net_adm, ping, [Cp2]), + pong = rpc:call(Cp3, net_adm, ping, [node()]), + + [] = [Cp1, Cp2 | OrigNodes] -- nodes(), + + %% start a proc on hidden node and register it + {HPid, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), + Cp3 = node(HPid), + + %% Check that it didn't get registered on visible nodes + ?UNTIL((undefined =:= global:whereis_name(test)) and (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test]))), - % start a proc on visible node and register it - ?line {Pid, yes} = start_proc(test), - ?line true = (Pid =/= HPid), + %% start a proc on visible node and register it + {Pid, yes} = start_proc(test), + true = (Pid =/= HPid), - % test that it is registered at all nodes - ?line - ?UNTIL((Pid =:= global:whereis_name(test)) and + %% test that it is registered at all nodes + ?UNTIL((Pid =:= global:whereis_name(test)) and (Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and (Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and (HPid =:= rpc:call(Cp3, global, whereis_name, [test])) and ([test] =:= global:registered_names() -- OrigNames)), - % try to register the same name - ?line no = global:register_name(test, self()), - ?line no = rpc:call(Cp1, global, register_name, [test, self()]), + %% try to register the same name + no = global:register_name(test, self()), + no = rpc:call(Cp1, global, register_name, [test, self()]), - % let process exit, check that it is unregistered automatically + %% let process exit, check that it is unregistered automatically exit_p(Pid), - ?line - ?UNTIL((undefined =:= global:whereis_name(test)) and + ?UNTIL((undefined =:= global:whereis_name(test)) and (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and (HPid =:= rpc:call(Cp3, global, whereis_name, [test]))), - % test re_register - ?line {Pid2, yes} = start_proc(test), - ?line ?UNTIL(Pid2 =:= rpc:call(Cp2, global, whereis_name, [test])), + %% test re_register + {Pid2, yes} = start_proc(test), + ?UNTIL(Pid2 =:= rpc:call(Cp2, global, whereis_name, [test])), Pid3 = rpc:call(Cp2, ?MODULE, start_proc2, [test]), - ?line ?UNTIL(Pid3 =:= rpc:call(Cp2, global, whereis_name, [test])), - ?line Pid3 = global:whereis_name(test), + ?UNTIL(Pid3 =:= rpc:call(Cp2, global, whereis_name, [test])), + Pid3 = global:whereis_name(test), - % test sending - ?line Pid3 = global:send(test, {ping, self()}), + %% test sending + Pid3 = global:send(test, {ping, self()}), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout1) + 2000 -> ct:fail(timeout1) end, rpc:call(Cp1, global, send, [test, {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line _ = rpc:call(Cp3, global, unregister_name, [test]), - ?line - ?UNTIL((Pid3 =:= global:whereis_name(test)) and + _ = rpc:call(Cp3, global, unregister_name, [test]), + ?UNTIL((Pid3 =:= global:whereis_name(test)) and (Pid3 =:= rpc:call(Cp1, global, whereis_name, [test])) and (Pid3 =:= rpc:call(Cp2, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp3, global, whereis_name, [test]))), - ?line _ = global:unregister_name(test), - ?line - ?UNTIL((undefined =:= global:whereis_name(test)) and + _ = global:unregister_name(test), + ?UNTIL((undefined =:= global:whereis_name(test)) and (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp3, global, whereis_name, [test]))), @@ -608,277 +592,297 @@ names_hidden(Config) when is_list(Config) -> exit_p(Pid3), exit_p(HPid), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?UNTIL(undefined =:= global:whereis_name(test)), write_high_level_trace(Config), - % stop the nodes, and make sure names are released. + + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. -locks(suite) -> []; locks(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_node(cp3, Config), - - ?line wait_for_ready_net(Config), - - % start two procs - ?line Pid = start_proc(), - ?line Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []), - % set a lock, and make sure noone else can set the same lock - ?line true = global:set_lock({test_lock, self()}, ?NODES, 1), - ?line false = req(Pid, {set_lock, test_lock, self()}), - ?line false = req(Pid2, {set_lock, test_lock, self()}), - % delete, and let another proc set the lock + init_condition(Config), + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_node(cp3, Config), + + wait_for_ready_net(Config), + + %% start two procs + Pid = start_proc(), + Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []), + + %% set a lock, and make sure noone else can set the same lock + true = global:set_lock({test_lock, self()}, ?NODES, 1), + false = req(Pid, {set_lock, test_lock, self()}), + false = req(Pid2, {set_lock, test_lock, self()}), + + %% delete, and let another proc set the lock global:del_lock({test_lock, self()}), - ?line true = req(Pid, {set_lock, test_lock, self()}), - ?line false = req(Pid2, {set_lock, test_lock, self()}), - ?line false = global:set_lock({test_lock, self()}, ?NODES,1), - % kill lock-holding proc, make sure the lock is released + true = req(Pid, {set_lock, test_lock, self()}), + false = req(Pid2, {set_lock, test_lock, self()}), + false = global:set_lock({test_lock, self()}, ?NODES,1), + + %% kill lock-holding proc, make sure the lock is released exit_p(Pid), ?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES,1)), Pid2 ! {set_lock_loop, test_lock, self()}, - % make sure we don't have the msg + + %% make sure we don't have the msg receive - {got_lock, Pid2} -> test_server:fail(got_lock) + {got_lock, Pid2} -> ct:fail(got_lock) after 1000 -> ok end, global:del_lock({test_lock, self()}), - % make sure pid2 got the lock + + %% make sure pid2 got the lock receive {got_lock, Pid2} -> ok after - % 12000 >> 5000, which is the max time before a new retry for - % set_lock - 12000 -> test_server:fail(got_lock2) + %% 12000 >> 5000, which is the max time before a new retry for + %% set_lock + 12000 -> ct:fail(got_lock2) end, - % let proc set the same lock - ?line true = req(Pid2, {set_lock, test_lock, self()}), - % let proc set new lock - ?line true = req(Pid2, {set_lock, test_lock2, self()}), - ?line false = global:set_lock({test_lock, self()},?NODES,1), - ?line false = global:set_lock({test_lock2, self()}, ?NODES,1), + %% let proc set the same lock + true = req(Pid2, {set_lock, test_lock, self()}), + + %% let proc set new lock + true = req(Pid2, {set_lock, test_lock2, self()}), + false = global:set_lock({test_lock, self()},?NODES,1), + false = global:set_lock({test_lock2, self()}, ?NODES,1), exit_p(Pid2), -% erlang:display({locks1, ets:tab2list(global_locks)}), ?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)), ?UNTIL(true =:= global:set_lock({test_lock2, self()}, ?NODES, 1)), - ?line global:del_lock({test_lock, self()}), - ?line global:del_lock({test_lock2, self()}), - - % let proc set two locks - ?line Pid3 = rpc:call(Cp1, ?MODULE, start_proc, []), - ?line true = req(Pid3, {set_lock, test_lock, self()}), - ?line true = req(Pid3, {set_lock, test_lock2, self()}), - % del one lock - ?line Pid3 ! {del_lock, test_lock2}, - ?line test_server:sleep(100), - % check that one lock is still set, but not the other - ?line false = global:set_lock({test_lock, self()}, ?NODES, 1), - ?line true = global:set_lock({test_lock2, self()}, ?NODES, 1), - ?line global:del_lock({test_lock2, self()}), - % kill lock-holder + global:del_lock({test_lock, self()}), + global:del_lock({test_lock2, self()}), + + %% let proc set two locks + Pid3 = rpc:call(Cp1, ?MODULE, start_proc, []), + true = req(Pid3, {set_lock, test_lock, self()}), + true = req(Pid3, {set_lock, test_lock2, self()}), + + %% del one lock + Pid3 ! {del_lock, test_lock2}, + ct:sleep(100), + + %% check that one lock is still set, but not the other + false = global:set_lock({test_lock, self()}, ?NODES, 1), + true = global:set_lock({test_lock2, self()}, ?NODES, 1), + global:del_lock({test_lock2, self()}), + + %% kill lock-holder exit_p(Pid3), -% erlang:display({locks2, ets:tab2list(global_locks)}), + ?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)), - ?line global:del_lock({test_lock, self()}), + global:del_lock({test_lock, self()}), ?UNTIL(true =:= global:set_lock({test_lock2, self()}, ?NODES, 1)), - ?line global:del_lock({test_lock2, self()}), - - % start one proc on each node - ?line Pid4 = start_proc(), - ?line Pid5 = rpc:call(Cp1, ?MODULE, start_proc, []), - ?line Pid6 = rpc:call(Cp2, ?MODULE, start_proc, []), - ?line Pid7 = rpc:call(Cp3, ?MODULE, start_proc, []), - % set lock on two nodes - ?line true = req(Pid4, {set_lock, test_lock, self(), [node(), Cp1]}), - ?line false = req(Pid5, {set_lock, test_lock, self(), [node(), Cp1]}), - % set same lock on other two nodes - ?line true = req(Pid6, {set_lock, test_lock, self(), [Cp2, Cp3]}), - ?line false = req(Pid7, {set_lock, test_lock, self(), [Cp2, Cp3]}), - % release lock + global:del_lock({test_lock2, self()}), + + %% start one proc on each node + Pid4 = start_proc(), + Pid5 = rpc:call(Cp1, ?MODULE, start_proc, []), + Pid6 = rpc:call(Cp2, ?MODULE, start_proc, []), + Pid7 = rpc:call(Cp3, ?MODULE, start_proc, []), + + %% set lock on two nodes + true = req(Pid4, {set_lock, test_lock, self(), [node(), Cp1]}), + false = req(Pid5, {set_lock, test_lock, self(), [node(), Cp1]}), + + %% set same lock on other two nodes + true = req(Pid6, {set_lock, test_lock, self(), [Cp2, Cp3]}), + false = req(Pid7, {set_lock, test_lock, self(), [Cp2, Cp3]}), + + %% release lock Pid6 ! {del_lock, test_lock, [Cp2, Cp3]}, - % try to set lock on a node that already has the lock - ?line false = req(Pid6, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}), - % set lock on a node + %% try to set lock on a node that already has the lock + false = req(Pid6, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}), + + %% set lock on a node exit_p(Pid4), ?UNTIL(true =:= req(Pid5, {set_lock, test_lock, self(), [node(), Cp1]})), - ?line Pid8 = start_proc(), - ?line false = req(Pid8, {set_lock, test_lock, self()}), + Pid8 = start_proc(), + false = req(Pid8, {set_lock, test_lock, self()}), write_high_level_trace(Config), - % stop the nodes, and make sure locks are released. + + %% stop the nodes, and make sure locks are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line test_server:sleep(100), - ?line true = req(Pid8, {set_lock, test_lock, self()}), + ct:sleep(100), + true = req(Pid8, {set_lock, test_lock, self()}), exit_p(Pid8), - ?line test_server:sleep(10), + ct:sleep(10), - ?line init_condition(Config), + init_condition(Config), ok. - -locks_hidden(suite) -> []; -locks_hidden(doc) -> - ["Tests that locks on a hidden node doesn't interere with locks on " - "visible nodes."]; + +%% Tests that locks on a hidden node doesn't interere with locks on +%% visible nodes. locks_hidden(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNodes = nodes(), - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_hidden_node(cp3, Config), - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp3]), - ?line pong = rpc:call(Cp3, net_adm, ping, [Cp2]), - ?line pong = rpc:call(Cp3, net_adm, ping, [node()]), - - ?line [] = [Cp1, Cp2 | OrigNodes] -- nodes(), - - % start two procs - ?line Pid = start_proc(), - ?line Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []), - ?line HPid = rpc:call(Cp3, ?MODULE, start_proc, []), - % Make sure hidden node doesn't interfere with visible nodes lock - ?line true = req(HPid, {set_lock, test_lock, self()}), - ?line true = global:set_lock({test_lock, self()}, ?NODES, 1), - ?line false = req(Pid, {set_lock, test_lock, self()}), - ?line true = req(HPid, {del_lock_sync, test_lock, self()}), - ?line false = req(Pid2, {set_lock, test_lock, self()}), - % delete, and let another proc set the lock + init_condition(Config), + OrigNodes = nodes(), + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_hidden_node(cp3, Config), + pong = rpc:call(Cp1, net_adm, ping, [Cp3]), + pong = rpc:call(Cp3, net_adm, ping, [Cp2]), + pong = rpc:call(Cp3, net_adm, ping, [node()]), + + [] = [Cp1, Cp2 | OrigNodes] -- nodes(), + + %% start two procs + Pid = start_proc(), + Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []), + HPid = rpc:call(Cp3, ?MODULE, start_proc, []), + + %% Make sure hidden node doesn't interfere with visible nodes lock + true = req(HPid, {set_lock, test_lock, self()}), + true = global:set_lock({test_lock, self()}, ?NODES, 1), + false = req(Pid, {set_lock, test_lock, self()}), + true = req(HPid, {del_lock_sync, test_lock, self()}), + false = req(Pid2, {set_lock, test_lock, self()}), + + %% delete, and let another proc set the lock global:del_lock({test_lock, self()}), - ?line true = req(Pid, {set_lock, test_lock, self()}), - ?line false = req(Pid2, {set_lock, test_lock, self()}), - ?line false = global:set_lock({test_lock, self()}, ?NODES,1), - % kill lock-holding proc, make sure the lock is released + true = req(Pid, {set_lock, test_lock, self()}), + false = req(Pid2, {set_lock, test_lock, self()}), + false = global:set_lock({test_lock, self()}, ?NODES,1), + + %% kill lock-holding proc, make sure the lock is released exit_p(Pid), ?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)), ?UNTIL(true =:= req(HPid, {set_lock, test_lock, self()})), Pid2 ! {set_lock_loop, test_lock, self()}, - % make sure we don't have the msg + + %% make sure we don't have the msg receive - {got_lock, Pid2} -> test_server:fail(got_lock) + {got_lock, Pid2} -> ct:fail(got_lock) after 1000 -> ok end, global:del_lock({test_lock, self()}), - % make sure pid2 got the lock + + %% make sure pid2 got the lock receive {got_lock, Pid2} -> ok after - % 12000 >> 5000, which is the max time before a new retry for - % set_lock - 12000 -> test_server:fail(got_lock2) + %% 12000 >> 5000, which is the max time before a new retry for + %% set_lock + 12000 -> ct:fail(got_lock2) end, - ?line true = req(HPid, {del_lock_sync, test_lock, self()}), - - % let proc set the same lock - ?line true = req(Pid2, {set_lock, test_lock, self()}), - % let proc set new lock - ?line true = req(Pid2, {set_lock, test_lock2, self()}), - ?line true = req(HPid, {set_lock, test_lock, self()}), - ?line true = req(HPid, {set_lock, test_lock2, self()}), + true = req(HPid, {del_lock_sync, test_lock, self()}), + + %% let proc set the same lock + true = req(Pid2, {set_lock, test_lock, self()}), + + %% let proc set new lock + true = req(Pid2, {set_lock, test_lock2, self()}), + true = req(HPid, {set_lock, test_lock, self()}), + true = req(HPid, {set_lock, test_lock2, self()}), exit_p(HPid), - ?line false = global:set_lock({test_lock, self()},?NODES,1), - ?line false = global:set_lock({test_lock2, self()}, ?NODES,1), + false = global:set_lock({test_lock, self()},?NODES,1), + false = global:set_lock({test_lock2, self()}, ?NODES,1), + exit_p(Pid2), -% erlang:display({locks1, ets:tab2list(global_locks)}), ?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)), ?UNTIL(true =:= global:set_lock({test_lock2, self()}, ?NODES, 1)), - ?line global:del_lock({test_lock, self()}), - ?line global:del_lock({test_lock2, self()}), + global:del_lock({test_lock, self()}), + global:del_lock({test_lock2, self()}), write_high_level_trace(Config), - % stop the nodes, and make sure locks are released. + + %% stop the nodes, and make sure locks are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. - -bad_input(suite) -> []; + bad_input(Config) when is_list(Config) -> Timeout = 15, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), + Pid = whereis(global_name_server), + {'EXIT', _} = (catch global:set_lock(bad_id)), + {'EXIT', _} = (catch global:set_lock({id, self()}, bad_nodes)), + {'EXIT', _} = (catch global:del_lock(bad_id)), + {'EXIT', _} = (catch global:del_lock({id, self()}, bad_nodes)), + {'EXIT', _} = (catch global:register_name(name, bad_pid)), + {'EXIT', _} = (catch global:reregister_name(name, bad_pid)), + {'EXIT', _} = (catch global:trans(bad_id, {m,f})), + {'EXIT', _} = (catch global:trans({id, self()}, {m,f}, [node()], -1)), Pid = whereis(global_name_server), - ?line {'EXIT', _} = (catch global:set_lock(bad_id)), - ?line {'EXIT', _} = (catch global:set_lock({id, self()}, bad_nodes)), - ?line {'EXIT', _} = (catch global:del_lock(bad_id)), - ?line {'EXIT', _} = (catch global:del_lock({id, self()}, bad_nodes)), - ?line {'EXIT', _} = (catch global:register_name(name, bad_pid)), - ?line {'EXIT', _} = (catch global:reregister_name(name, bad_pid)), - ?line {'EXIT', _} = (catch global:trans(bad_id, {m,f})), - ?line {'EXIT', _} = (catch global:trans({id, self()}, {m,f}, [node()], -1)), - ?line Pid = whereis(global_name_server), - ?line init_condition(Config), + init_condition(Config), ok. -names_and_locks(suite) -> []; names_and_locks(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), - - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_node(cp3, Config), - - % start one proc on each node - ?line PidTS = start_proc(), - ?line Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []), - ?line Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []), - ?line Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []), - % register some of them - ?line yes = global:register_name(test1, Pid1), - ?line yes = global:register_name(test2, Pid2), - ?line yes = global:register_name(test3, Pid3), - ?line no = global:register_name(test3, PidTS), - ?line yes = global:register_name(test4, PidTS), - - % set lock on two nodes - ?line true = req(PidTS, {set_lock, test_lock, self(), [node(), Cp1]}), - ?line false = req(Pid1, {set_lock, test_lock, self(), [node(), Cp1]}), - % set same lock on other two nodes - ?line true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}), - ?line false = req(Pid3, {set_lock, test_lock, self(), [Cp2, Cp3]}), - % release lock + init_condition(Config), + OrigNames = global:registered_names(), + + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_node(cp3, Config), + + %% start one proc on each node + PidTS = start_proc(), + Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []), + Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []), + Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []), + + %% register some of them + yes = global:register_name(test1, Pid1), + yes = global:register_name(test2, Pid2), + yes = global:register_name(test3, Pid3), + no = global:register_name(test3, PidTS), + yes = global:register_name(test4, PidTS), + + %% set lock on two nodes + true = req(PidTS, {set_lock, test_lock, self(), [node(), Cp1]}), + false = req(Pid1, {set_lock, test_lock, self(), [node(), Cp1]}), + + %% set same lock on other two nodes + true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}), + false = req(Pid3, {set_lock, test_lock, self(), [Cp2, Cp3]}), + + %% release lock Pid2 ! {del_lock, test_lock, [Cp2, Cp3]}, - ?line test_server:sleep(100), - % try to set lock on a node that already has the lock - ?line false = req(Pid2, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}), - % set two locks - ?line true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}), - ?line true = req(Pid2, {set_lock, test_lock2, self(), [Cp2, Cp3]}), - - % kill some processes, make sure all locks/names are released + ct:sleep(100), + + %% try to set lock on a node that already has the lock + false = req(Pid2, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}), + + %% set two locks + true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}), + true = req(Pid2, {set_lock, test_lock2, self(), [Cp2, Cp3]}), + + %% kill some processes, make sure all locks/names are released exit_p(PidTS), - ?line ?UNTIL(undefined =:= global:whereis_name(test4)), - ?line true = global:set_lock({test_lock, self()}, [node(), Cp1], 1), + ?UNTIL(undefined =:= global:whereis_name(test4)), + true = global:set_lock({test_lock, self()}, [node(), Cp1], 1), global:del_lock({test_lock, self()}, [node(), Cp1]), exit_p(Pid2), - ?line - ?UNTIL((undefined =:= global:whereis_name(test2)) and + ?UNTIL((undefined =:= global:whereis_name(test2)) and (true =:= global:set_lock({test_lock, self()}, [Cp2, Cp3], 1)) and (true =:= global:set_lock({test_lock2, self()}, [Cp2, Cp3], 1))), @@ -888,117 +892,113 @@ names_and_locks(Config) when is_list(Config) -> exit_p(Pid1), exit_p(Pid3), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. - -lock_die(suite) -> []; -lock_die(doc) -> - ["OTP-6341. Remove locks using monitors."]; + +%% OTP-6341. Remove locks using monitors. lock_die(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), %% First test. LockId = {id, self()}, - ?line Pid2 = start_proc(), - ?line true = req(Pid2, {set_lock2, LockId, self()}), + Pid2 = start_proc(), + true = req(Pid2, {set_lock2, LockId, self()}), - ?line true = global:set_lock(LockId, [Cp1]), + true = global:set_lock(LockId, [Cp1]), %% Id is locked on Cp1 and Cp2 (by Pid2) but not by self(): %% (there is no mon. ref) - ?line _ = global:del_lock(LockId, [node(), Cp1, Cp2]), + _ = global:del_lock(LockId, [node(), Cp1, Cp2]), + + exit_p(Pid2), - ?line exit_p(Pid2), - %% Second test. - ?line Pid3 = start_proc(), - ?line true = req(Pid3, {set_lock, id, self(), [Cp1]}), + Pid3 = start_proc(), + true = req(Pid3, {set_lock, id, self(), [Cp1]}), %% The lock is removed from Cp1 thanks to monitors. - ?line exit_p(Pid3), - - ?line true = global:set_lock(LockId, [node(), Cp1]), - ?line _ = global:del_lock(LockId, [node(), Cp1]), + exit_p(Pid3), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + true = global:set_lock(LockId, [node(), Cp1]), + _ = global:del_lock(LockId, [node(), Cp1]), + + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp1), stop_node(Cp2), - ?line init_condition(Config), + init_condition(Config), ok. -name_die(suite) -> []; -name_die(doc) -> - ["OTP-6341. Remove names using monitors."]; +%% OTP-6341. Remove names using monitors. name_die(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), - ?line [Cp1] = Cps = start_nodes([z], peer, Config), % z > test_server + init_condition(Config), + OrigNames = global:registered_names(), + [Cp1] = Cps = start_nodes([z], peer, Config), % z > test_server Nodes = lists:sort([node() | Cps]), - ?line wait_for_ready_net(Config), - + wait_for_ready_net(Config), + Name = name_die, - ?line Pid = rpc:call(Cp1, ?MODULE, start_proc, []), + Pid = rpc:call(Cp1, ?MODULE, start_proc, []), %% Test 1. No resolver is called if the same pid is registered on %% both partitions. T1 = node(), Part1 = [T1], Part2 = [Cp1], - ?line rpc_cast(Cp1, - ?MODULE, part_2_2, [Config, - Part1, - Part2, - []]), - ?line ?UNTIL(is_ready_partition(Config)), - ?line ?UNTIL(undefined =:= global:whereis_name(Name)), - ?line yes = global:register_name(Name, Pid), - - ?line pong = net_adm:ping(Cp1), - ?line wait_for_ready_net(Nodes, Config), - ?line assert_pid(global:whereis_name(Name)), + rpc_cast(Cp1, + ?MODULE, part_2_2, [Config, + Part1, + Part2, + []]), + ?UNTIL(is_ready_partition(Config)), + ?UNTIL(undefined =:= global:whereis_name(Name)), + yes = global:register_name(Name, Pid), + + pong = net_adm:ping(Cp1), + wait_for_ready_net(Nodes, Config), + assert_pid(global:whereis_name(Name)), exit_p(Pid), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), %% Test 2. Register a name running outside the current partition. %% Killing the pid will not remove the name from the current %% partition, unless monitors are used. - ?line Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []), - Dir = ?config(priv_dir, Config), + Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []), + Dir = proplists:get_value(priv_dir, Config), KillFile = filename:join([Dir, "kill.txt"]), file:delete(KillFile), - ?line erlang:spawn(Cp1, fun() -> kill_pid(Pid2, KillFile, Config) end), - ?line rpc_cast(Cp1, - ?MODULE, part_2_2, [Config, - Part1, - Part2, - []]), - ?line ?UNTIL(is_ready_partition(Config)), - ?line ?UNTIL(undefined =:= global:whereis_name(Name)), - ?line yes = global:register_name(Name, Pid2), - ?line touch(KillFile, "kill"), - ?line file_contents(KillFile, "done", Config), + erlang:spawn(Cp1, fun() -> kill_pid(Pid2, KillFile, Config) end), + rpc_cast(Cp1, + ?MODULE, part_2_2, [Config, + Part1, + Part2, + []]), + ?UNTIL(is_ready_partition(Config)), + ?UNTIL(undefined =:= global:whereis_name(Name)), + yes = global:register_name(Name, Pid2), + touch(KillFile, "kill"), + file_contents(KillFile, "done", Config), file:delete(KillFile), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_nodes(Cps), - ?line init_condition(Config), + init_condition(Config), ok. kill_pid(Pid, File, Config) -> @@ -1006,186 +1006,178 @@ kill_pid(Pid, File, Config) -> exit_p(Pid), touch(File, "done"). -basic_partition(suite) -> []; -basic_partition(doc) -> - ["Tests that two partitioned networks exchange correct info."]; +%% Tests that two partitioned networks exchange correct info. basic_partition(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), - - ?line [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config), - ?line [Cp1, Cp2, Cp3] = lists:sort(nodes()), - - ?line wait_for_ready_net(Config), - - % make cp2 and cp3 connected, partitioned from us and cp1 - ?line rpc_cast(Cp2, ?MODULE, part1, [Config, node(), Cp1, Cp3]), - ?line ?UNTIL(is_ready_partition(Config)), - - % start different processes in both partitions - ?line {Pid, yes} = start_proc(test), - - % connect to other partition - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line [Cp1, Cp2, Cp3] = lists:sort(nodes()), - - % check names - ?line ?UNTIL(Pid =:= rpc:call(Cp2, global, whereis_name, [test])), - ?line ?UNTIL(undefined =/= global:whereis_name(test2)), - ?line Pid2 = global:whereis_name(test2), - ?line Pid2 = rpc:call(Cp2, global, whereis_name, [test2]), - ?line assert_pid(Pid2), - ?line Pid3 = global:whereis_name(test4), - ?line ?UNTIL(Pid3 =:= rpc:call(Cp1, global, whereis_name, [test4])), - ?line assert_pid(Pid3), - - % kill all procs - ?line Pid3 = global:send(test4, die), - % sleep to let the proc die + init_condition(Config), + OrigNames = global:registered_names(), + + [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config), + [Cp1, Cp2, Cp3] = lists:sort(nodes()), + + wait_for_ready_net(Config), + + %% make cp2 and cp3 connected, partitioned from us and cp1 + rpc_cast(Cp2, ?MODULE, part1, [Config, node(), Cp1, Cp3]), + ?UNTIL(is_ready_partition(Config)), + + %% start different processes in both partitions + {Pid, yes} = start_proc(test), + + %% connect to other partition + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + [Cp1, Cp2, Cp3] = lists:sort(nodes()), + + %% check names + ?UNTIL(Pid =:= rpc:call(Cp2, global, whereis_name, [test])), + ?UNTIL(undefined =/= global:whereis_name(test2)), + Pid2 = global:whereis_name(test2), + Pid2 = rpc:call(Cp2, global, whereis_name, [test2]), + assert_pid(Pid2), + Pid3 = global:whereis_name(test4), + ?UNTIL(Pid3 =:= rpc:call(Cp1, global, whereis_name, [test4])), + assert_pid(Pid3), + + %% kill all procs + Pid3 = global:send(test4, die), + %% sleep to let the proc die wait_for_exit(Pid3), - ?line ?UNTIL(undefined =:= global:whereis_name(test4)), - + ?UNTIL(undefined =:= global:whereis_name(test4)), + exit_p(Pid), exit_p(Pid2), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. -basic_name_partition(suite) -> - []; -basic_name_partition(doc) -> - ["Creates two partitions with two nodes in each partition.", - "Tests that names are exchanged correctly, and that EXITs", - "during connect phase are handled correctly."]; +%% Creates two partitions with two nodes in each partition. +%% Tests that names are exchanged correctly, and that EXITs +%% during connect phase are handled correctly. basic_name_partition(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config), - ?line [Cp1, Cp2, Cp3] = lists:sort(nodes()), + [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config), + [Cp1, Cp2, Cp3] = lists:sort(nodes()), Nodes = ?NODES, - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % There used to be more than one name registered for some - % processes. That was a mistake; there is no support for more than - % one name per process, and the manual is quite clear about that - % ("equivalent to the register/2 and whereis/1 BIFs"). The - % resolver procedure did not take care of such "duplicated" names, - % which caused this testcase to fail every now and then. + %% There used to be more than one name registered for some + %% processes. That was a mistake; there is no support for more than + %% one name per process, and the manual is quite clear about that + %% ("equivalent to the register/2 and whereis/1 BIFs"). The + %% resolver procedure did not take care of such "duplicated" names, + %% which caused this testcase to fail every now and then. - % make cp2 and cp3 connected, partitioned from us and cp1 - % us: register name03 - % cp1: register name12 - % cp2: register name12 - % cp3: register name03 - - ?line rpc_cast(Cp2, ?MODULE, part1_5, [Config, node(), Cp1, Cp3]), - ?line ?UNTIL(is_ready_partition(Config)), - - % start different processes in both partitions - ?line {_, yes} = start_proc_basic(name03), - ?line {_, yes} = rpc:call(Cp1, ?MODULE, start_proc_basic, [name12]), - test_server:sleep(1000), + %% make cp2 and cp3 connected, partitioned from us and cp1 + %% us: register name03 + %% cp1: register name12 + %% cp2: register name12 + %% cp3: register name03 - % connect to other partition - ?line pong = net_adm:ping(Cp3), - - ?line ?UNTIL([Cp1, Cp2, Cp3] =:= lists:sort(nodes())), - ?line wait_for_ready_net(Config), - % check names - ?line Pid03 = global:whereis_name(name03), - ?line assert_pid(Pid03), - ?line true = lists:member(node(Pid03), [node(), Cp3]), - ?line check_everywhere(Nodes, name03, Config), - - ?line Pid12 = global:whereis_name(name12), - ?line assert_pid(Pid12), - ?line true = lists:member(node(Pid12), [Cp1, Cp2]), - ?line check_everywhere(Nodes, name12, Config), - - % kill all procs - ?line Pid12 = global:send(name12, die), - ?line Pid03 = global:send(name03, die), - % sleep to let the procs die + rpc_cast(Cp2, ?MODULE, part1_5, [Config, node(), Cp1, Cp3]), + ?UNTIL(is_ready_partition(Config)), + + %% start different processes in both partitions + {_, yes} = start_proc_basic(name03), + {_, yes} = rpc:call(Cp1, ?MODULE, start_proc_basic, [name12]), + ct:sleep(1000), + + %% connect to other partition + pong = net_adm:ping(Cp3), + + ?UNTIL([Cp1, Cp2, Cp3] =:= lists:sort(nodes())), + wait_for_ready_net(Config), + + %% check names + Pid03 = global:whereis_name(name03), + assert_pid(Pid03), + true = lists:member(node(Pid03), [node(), Cp3]), + check_everywhere(Nodes, name03, Config), + + Pid12 = global:whereis_name(name12), + assert_pid(Pid12), + true = lists:member(node(Pid12), [Cp1, Cp2]), + check_everywhere(Nodes, name12, Config), + + %% kill all procs + Pid12 = global:send(name12, die), + Pid03 = global:send(name03, die), + + %% sleep to let the procs die wait_for_exit(Pid12), wait_for_exit(Pid03), - ?line ?UNTIL(begin Names = [name03, name12], lists:duplicate(length(Names), undefined) =:= [global:whereis_name(Name) || Name <- Names] end), - - ?line ?UNTIL(OrigNames =:= global:registered_names()), + + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. -%Peer nodes cp0 - cp6 are started. Break apart the connections from -%cp3-cp6 to cp0-cp2 and test_server so we get two partitions. -%In the cp3-cp6 partition, start one process on each node and register -%using both erlang:register, and global:register (test1 on cp3, test2 on -%cp4, test3 on cp5, test4 on cp6), using different resolution functions: -%default for test1, notify_all_name for test2, random_notify_name for test3 -%and one for test4 that sends a message to test_server and keeps the -%process which is greater in the standard ordering. In the other partition, -%do the same (test1 on test_server, test2 on cp0, test3 on cp1, test4 on cp2). -%Sleep a little, then from test_server, connect to cp3-cp6 in order. -%Check that the values for the registered names are the expected ones, and -%that the messages from test4 arrive. - -advanced_partition(suite) -> - []; -advanced_partition(doc) -> - ["Test that names are resolved correctly when two", - "partitioned networks connect."]; +%% Peer nodes cp0 - cp6 are started. Break apart the connections from +%% cp3-cp6 to cp0-cp2 and test_server so we get two partitions. +%% In the cp3-cp6 partition, start one process on each node and register +%% using both erlang:register, and global:register (test1 on cp3, test2 on +%% cp4, test3 on cp5, test4 on cp6), using different resolution functions: +%% default for test1, notify_all_name for test2, random_notify_name for test3 +%% and one for test4 that sends a message to test_server and keeps the +%% process which is greater in the standard ordering. In the other partition, +%% do the same (test1 on test_server, test2 on cp0, test3 on cp1, test4 on cp2). +%% Sleep a little, then from test_server, connect to cp3-cp6 in order. +%% Check that the values for the registered names are the expected ones, and +%% that the messages from test4 arrive. + +%% Test that names are resolved correctly when two +%% partitioned networks connect. advanced_partition(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6] + [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6] = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6], peer, Config), Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % make cp3-cp6 connected, partitioned from us and cp0-cp2 - ?line rpc_cast(Cp3, ?MODULE, part2, - [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]), - ?line ?UNTIL(is_ready_partition(Config)), - - % start different processes in this partition - ?line start_procs(self(), Cp0, Cp1, Cp2, Config), - - % connect to other partition - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - ?line pong = net_adm:ping(Cp6), - - ?line wait_for_ready_net(Config), + %% make cp3-cp6 connected, partitioned from us and cp0-cp2 + rpc_cast(Cp3, ?MODULE, part2, + [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]), + ?UNTIL(is_ready_partition(Config)), + + %% start different processes in this partition + start_procs(self(), Cp0, Cp1, Cp2, Config), + + %% connect to other partition + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + pong = net_adm:ping(Cp6), + + wait_for_ready_net(Config), - ?line ?UNTIL(lists:member(undefined, [rpc:call(Cp3, erlang, whereis, [test1]), rpc:call(node(), erlang, whereis, [test1])])), @@ -1200,43 +1192,42 @@ advanced_partition(Config) when is_list(Config) -> Mt3 = rpc:call(Cp1, erlang, whereis, [test3]), _Mt4 = rpc:call(Cp2, erlang, whereis, [test4]), - % check names - ?line Pid1 = global:whereis_name(test1), - ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test1]), - ?line assert_pid(Pid1), - ?line true = lists:member(Pid1, [Nt1, Mt1]), - ?line true = lists:member(undefined, [Nt1, Mt1]), - ?line check_everywhere(Nodes, test1, Config), - - ?line undefined = global:whereis_name(test2), - ?line undefined = rpc:call(Cp3, global, whereis_name, [test2]), - ?line yes = sreq(Nt2, {got_notify, self()}), - ?line yes = sreq(Mt2, {got_notify, self()}), - ?line check_everywhere(Nodes, test2, Config), - - ?line Pid3 = global:whereis_name(test3), - ?line Pid3 = rpc:call(Cp3, global, whereis_name, [test3]), - ?line assert_pid(Pid3), - ?line true = lists:member(Pid3, [Nt3, Mt3]), - ?line no = sreq(Pid3, {got_notify, self()}), - ?line yes = sreq(other(Pid3, [Nt2, Nt3]), {got_notify, self()}), - ?line check_everywhere(Nodes, test3, Config), - - ?line Pid4 = global:whereis_name(test4), - ?line Pid4 = rpc:call(Cp3, global, whereis_name, [test4]), - ?line assert_pid(Pid4), -% ?line true = lists:member(Pid4, [Nt4, Mt4]), - ?line Pid4 = Nt4, - ?line check_everywhere(Nodes, test4, Config), - - ?line 1 = collect_resolves(), - - ?line Pid1 = global:send(test1, die), + %% check names + Pid1 = global:whereis_name(test1), + Pid1 = rpc:call(Cp3, global, whereis_name, [test1]), + assert_pid(Pid1), + true = lists:member(Pid1, [Nt1, Mt1]), + true = lists:member(undefined, [Nt1, Mt1]), + check_everywhere(Nodes, test1, Config), + + undefined = global:whereis_name(test2), + undefined = rpc:call(Cp3, global, whereis_name, [test2]), + yes = sreq(Nt2, {got_notify, self()}), + yes = sreq(Mt2, {got_notify, self()}), + check_everywhere(Nodes, test2, Config), + + Pid3 = global:whereis_name(test3), + Pid3 = rpc:call(Cp3, global, whereis_name, [test3]), + assert_pid(Pid3), + true = lists:member(Pid3, [Nt3, Mt3]), + no = sreq(Pid3, {got_notify, self()}), + yes = sreq(other(Pid3, [Nt2, Nt3]), {got_notify, self()}), + check_everywhere(Nodes, test3, Config), + + Pid4 = global:whereis_name(test4), + Pid4 = rpc:call(Cp3, global, whereis_name, [test4]), + assert_pid(Pid4), + Pid4 = Nt4, + check_everywhere(Nodes, test4, Config), + + 1 = collect_resolves(), + + Pid1 = global:send(test1, die), exit_p(Pid3), exit_p(Pid4), wait_for_exit(Pid1), wait_for_exit(Pid3), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp0), @@ -1246,93 +1237,90 @@ advanced_partition(Config) when is_list(Config) -> stop_node(Cp4), stop_node(Cp5), stop_node(Cp6), - ?line init_condition(Config), + init_condition(Config), ok. - -%Peer nodes cp0 - cp6 are started, and partitioned just like in -%advanced_partition. Start cp8, only connected to test_server. Let cp6 -%break apart from the rest, and 12 s later, ping cp0 and cp3, and -%register the name test5. After the same 12 s, let cp5 halt. -%Wait for the death of cp5. Ping cp3 (at the same time as cp6 does). -%Take down cp2. Start cp7, restart cp2. Ping cp4, cp6 and cp8. -%Now, expect all nodes to be connected and have the same picture of all -%registered names. - -stress_partition(suite) -> - []; -stress_partition(doc) -> - ["Stress global, make a partitioned net, make some nodes", - "go up/down a bit."]; + +%% Peer nodes cp0 - cp6 are started, and partitioned just like in +%% advanced_partition. Start cp8, only connected to test_server. Let cp6 +%% break apart from the rest, and 12 s later, ping cp0 and cp3, and +%% register the name test5. After the same 12 s, let cp5 halt. +%% Wait for the death of cp5. Ping cp3 (at the same time as cp6 does). +%% Take down cp2. Start cp7, restart cp2. Ping cp4, cp6 and cp8. +%% Now, expect all nodes to be connected and have the same picture of all +%% registered names. + +%% Stress global, make a partitioned net, make some nodes +%% go up/down a bit. stress_partition(Config) when is_list(Config) -> Timeout = 90, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6] + [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6] = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6], peer, Config), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % make cp3-cp5 connected, partitioned from us and cp0-cp2 - % cp6 is alone (single node). cp6 pings cp0 and cp3 in 12 secs... - ?line rpc_cast(Cp3, ?MODULE, part3, - [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]), - ?line ?UNTIL(is_ready_partition(Config)), - - % start different processes in this partition - ?line start_procs(self(), Cp0, Cp1, Cp2, Config), + %% make cp3-cp5 connected, partitioned from us and cp0-cp2 + %% cp6 is alone (single node). cp6 pings cp0 and cp3 in 12 secs... + rpc_cast(Cp3, ?MODULE, part3, + [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]), + ?UNTIL(is_ready_partition(Config)), + + %% start different processes in this partition + start_procs(self(), Cp0, Cp1, Cp2, Config), + + {ok, Cp8} = start_peer_node(cp8, Config), - ?line {ok, Cp8} = start_peer_node(cp8, Config), - monitor_node(Cp5, true), receive {nodedown, Cp5} -> ok after - 20000 -> test_server:fail({no_nodedown, Cp5}) + 20000 -> ct:fail({no_nodedown, Cp5}) end, monitor_node(Cp5, false), - % Ok, now cp6 pings us, and cp5 will go down. - - % connect to other partition - ?line pong = net_adm:ping(Cp3), - ?line rpc_cast(Cp2, ?MODULE, crash, [0]), - - % Start new nodes - ?line {ok, Cp7} = start_peer_node(cp7, Config), - ?line {ok, Cp2_2} = start_peer_node(cp2, Config), + %% Ok, now cp6 pings us, and cp5 will go down. + + %% connect to other partition + pong = net_adm:ping(Cp3), + rpc_cast(Cp2, ?MODULE, crash, [0]), + + %% Start new nodes + {ok, Cp7} = start_peer_node(cp7, Config), + {ok, Cp2_2} = start_peer_node(cp2, Config), Nodes = lists:sort([node(), Cp0, Cp1, Cp2_2, Cp3, Cp4, Cp6, Cp7, Cp8]), put(?nodes_tag, Nodes), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp6), - ?line pong = net_adm:ping(Cp8), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp6), + pong = net_adm:ping(Cp8), - ?line wait_for_ready_net(Nodes, Config), + wait_for_ready_net(Nodes, Config), - % Make sure that all nodes have the same picture of all names - ?line check_everywhere(Nodes, test1, Config), - ?line assert_pid(global:whereis_name(test1)), - - ?line check_everywhere(Nodes, test2, Config), - ?line undefined = global:whereis_name(test2), + %% Make sure that all nodes have the same picture of all names + check_everywhere(Nodes, test1, Config), + assert_pid(global:whereis_name(test1)), - ?line check_everywhere(Nodes, test3, Config), - ?line assert_pid(global:whereis_name(test3)), + check_everywhere(Nodes, test2, Config), + undefined = global:whereis_name(test2), - ?line check_everywhere(Nodes, test4, Config), - ?line assert_pid(global:whereis_name(test4)), + check_everywhere(Nodes, test3, Config), + assert_pid(global:whereis_name(test3)), - ?line check_everywhere(Nodes, test5, Config), - ?line ?UNTIL(undefined =:= global:whereis_name(test5)), - - ?line assert_pid(global:send(test1, die)), - ?line assert_pid(global:send(test3, die)), - ?line assert_pid(global:send(test4, die)), + check_everywhere(Nodes, test4, Config), + assert_pid(global:whereis_name(test4)), + + check_everywhere(Nodes, test5, Config), + ?UNTIL(undefined =:= global:whereis_name(test5)), + + assert_pid(global:send(test1, die)), + assert_pid(global:send(test3, die)), + assert_pid(global:send(test4, die)), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp0), @@ -1344,15 +1332,13 @@ stress_partition(Config) when is_list(Config) -> stop_node(Cp6), stop_node(Cp7), stop_node(Cp8), - ?line init_condition(Config), + init_condition(Config), ok. %% Use this one to test alot of connection tests -%% erl -sname ts -rsh ctrsh -pa /clearcase/otp/internal_tools/test_server/ebin/ -ring_line 10000 -s test_server run_test global_SUITE +%% erl -sname ts -ring_line 10000 -s test_server run_test global_SUITE -ring_line(suite) -> []; -ring_line(doc) -> [""]; ring_line(Config) when is_list(Config) -> {ok, [[N]]} = init:get_argument(ring_line), loop_it(list_to_integer(N), Config). @@ -1361,74 +1347,70 @@ loop_it(N, Config) -> loop_it(N,N, Config). loop_it(0,_, _Config) -> ok; loop_it(N,M, Config) -> - test_server:format(1, "Round: ~w", [M-N]), + ct:pal(?HI_VERBOSITY, "Round: ~w", [M-N]), ring(Config), line(Config), loop_it(N-1,M, Config). -ring(suite) -> - []; -ring(doc) -> - ["Make 10 single nodes, all having the same name.", - "Make all ping its predecessor, pinging in a ring.", - "Make sure that there's just one winner."]; +%% Make 10 single nodes, all having the same name. +%% Make all ping its predecessor, pinging in a ring. +%% Make sure that there's just one winner. ring(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8] + [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8] = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8], peer, Config), Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), Time = msec() + 7000, - ?line rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp8, Config]), - ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), - ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), - ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), - ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), - ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), - ?line rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]), - ?line rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]), - ?line rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]), - - % sleep to make the partitioned net ready - test_server:sleep(Time - msec()), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - ?line pong = net_adm:ping(Cp6), - ?line pong = net_adm:ping(Cp7), - ?line pong = net_adm:ping(Cp8), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - ?line pong = net_adm:ping(Cp6), - ?line pong = net_adm:ping(Cp7), - ?line pong = net_adm:ping(Cp8), - - ?line wait_for_ready_net(Nodes, Config), - - % Just make sure that all nodes have the same picture of all names - ?line check_everywhere(Nodes, single_name, Config), - ?line assert_pid(global:whereis_name(single_name)), - - ?line + rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp8, Config]), + rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), + rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), + rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), + rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), + rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), + rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]), + rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]), + rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]), + + %% sleep to make the partitioned net ready + ct:sleep(Time - msec()), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + pong = net_adm:ping(Cp6), + pong = net_adm:ping(Cp7), + pong = net_adm:ping(Cp8), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + pong = net_adm:ping(Cp6), + pong = net_adm:ping(Cp7), + pong = net_adm:ping(Cp8), + + wait_for_ready_net(Nodes, Config), + + %% Just make sure that all nodes have the same picture of all names + check_everywhere(Nodes, single_name, Config), + assert_pid(global:whereis_name(single_name)), + ?UNTIL(begin {Ns2, []} = rpc:multicall(Nodes, erlang, whereis, [single_name]), @@ -1437,10 +1419,10 @@ ring(Config) when is_list(Config) -> end, 0, Ns2) end), - - ?line assert_pid(global:send(single_name, die)), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + assert_pid(global:send(single_name, die)), + + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp0), @@ -1452,64 +1434,60 @@ ring(Config) when is_list(Config) -> stop_node(Cp6), stop_node(Cp7), stop_node(Cp8), - ?line init_condition(Config), + init_condition(Config), ok. -simple_ring(suite) -> - []; -simple_ring(doc) -> - ["Simpler version of the ring case. Used because there are some", - "distribution problems with many nodes.", - "Make 6 single nodes, all having the same name.", - "Make all ping its predecessor, pinging in a ring.", - "Make sure that there's just one winner."]; +%% Simpler version of the ring case. Used because there are some +%% distribution problems with many nodes. +%% Make 6 single nodes, all having the same name. +%% Make all ping its predecessor, pinging in a ring. +%% Make sure that there's just one winner. simple_ring(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), Names = [cp0, cp1, cp2, cp3, cp4, cp5], - ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5] + [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5] = start_nodes(Names, peer, Config), Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), Time = msec() + 5000, - ?line rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp5, Config]), - ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), - ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), - ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), - ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), - ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), - - % sleep to make the partitioned net ready - test_server:sleep(Time - msec()), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - - ?line wait_for_ready_net(Nodes, Config), - - % Just make sure that all nodes have the same picture of all names - ?line check_everywhere(Nodes, single_name, Config), - ?line assert_pid(global:whereis_name(single_name)), - - ?line + rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp5, Config]), + rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), + rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), + rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), + rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), + rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), + + %% sleep to make the partitioned net ready + ct:sleep(Time - msec()), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + + wait_for_ready_net(Nodes, Config), + + %% Just make sure that all nodes have the same picture of all names + check_everywhere(Nodes, single_name, Config), + assert_pid(global:whereis_name(single_name)), + ?UNTIL(begin {Ns2, []} = rpc:multicall(Nodes, erlang, whereis, [single_name]), @@ -1518,10 +1496,10 @@ simple_ring(Config) when is_list(Config) -> end, 0, Ns2) end), - - ?line assert_pid(global:send(single_name, die)), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + assert_pid(global:send(single_name, die)), + + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp0), @@ -1530,72 +1508,68 @@ simple_ring(Config) when is_list(Config) -> stop_node(Cp3), stop_node(Cp4), stop_node(Cp5), - ?line init_condition(Config), + init_condition(Config), ok. -line(suite) -> - []; -line(doc) -> - ["Make 6 single nodes, all having the same name.", - "Make all ping its predecessor, pinging in a line.", - "Make sure that there's just one winner."]; +%% Make 6 single nodes, all having the same name. +%% Make all ping its predecessor, pinging in a line. +%% Make sure that there's just one winner. line(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8] + [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8] = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8], peer, Config), Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), Time = msec() + 7000, - ?line rpc_cast(Cp0, ?MODULE, single_node, - [Time, Cp0, Config]), % ping ourself! - ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), - ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), - ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), - ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), - ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), - ?line rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]), - ?line rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]), - ?line rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]), - - % sleep to make the partitioned net ready - test_server:sleep(Time - msec()), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - ?line pong = net_adm:ping(Cp6), - ?line pong = net_adm:ping(Cp7), - ?line pong = net_adm:ping(Cp8), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - ?line pong = net_adm:ping(Cp6), - ?line pong = net_adm:ping(Cp7), - ?line pong = net_adm:ping(Cp8), - - ?line wait_for_ready_net(Nodes, Config), - - % Just make sure that all nodes have the same picture of all names - ?line check_everywhere(Nodes, single_name, Config), - ?line assert_pid(global:whereis_name(single_name)), - - ?line + rpc_cast(Cp0, ?MODULE, single_node, + [Time, Cp0, Config]), % ping ourself! + rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), + rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), + rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), + rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), + rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), + rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]), + rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]), + rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]), + + %% Sleep to make the partitioned net ready + ct:sleep(Time - msec()), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + pong = net_adm:ping(Cp6), + pong = net_adm:ping(Cp7), + pong = net_adm:ping(Cp8), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + pong = net_adm:ping(Cp6), + pong = net_adm:ping(Cp7), + pong = net_adm:ping(Cp8), + + wait_for_ready_net(Nodes, Config), + + %% Just make sure that all nodes have the same picture of all names + check_everywhere(Nodes, single_name, Config), + assert_pid(global:whereis_name(single_name)), + ?UNTIL(begin {Ns2, []} = rpc:multicall(Nodes, erlang, whereis, [single_name]), @@ -1604,10 +1578,10 @@ line(Config) when is_list(Config) -> end, 0, Ns2) end), - - ?line assert_pid(global:send(single_name, die)), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + assert_pid(global:send(single_name, die)), + + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp0), @@ -1619,65 +1593,61 @@ line(Config) when is_list(Config) -> stop_node(Cp6), stop_node(Cp7), stop_node(Cp8), - ?line init_condition(Config), + init_condition(Config), ok. -simple_line(suite) -> - []; -simple_line(doc) -> - ["Simpler version of the line case. Used because there are some", - "distribution problems with many nodes.", - "Make 6 single nodes, all having the same name.", - "Make all ping its predecessor, pinging in a line.", - "Make sure that there's just one winner."]; +%% Simpler version of the line case. Used because there are some +%% distribution problems with many nodes. +%% Make 6 single nodes, all having the same name. +%% Make all ping its predecessor, pinging in a line. +%% Make sure that there's just one winner. simple_line(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5] + [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5] = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5], peer, Config), Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), Time = msec() + 5000, - ?line rpc_cast(Cp0, ?MODULE, single_node, - [Time, Cp0, Config]), % ping ourself! - ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), - ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), - ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), - ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), - ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), - - % sleep to make the partitioned net ready - test_server:sleep(Time - msec()), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - - ?line pong = net_adm:ping(Cp0), - ?line pong = net_adm:ping(Cp1), - ?line pong = net_adm:ping(Cp2), - ?line pong = net_adm:ping(Cp3), - ?line pong = net_adm:ping(Cp4), - ?line pong = net_adm:ping(Cp5), - - ?line wait_for_ready_net(Nodes, Config), - - % Just make sure that all nodes have the same picture of all names - ?line check_everywhere(Nodes, single_name, Config), - ?line assert_pid(global:whereis_name(single_name)), - - ?line + rpc_cast(Cp0, ?MODULE, single_node, + [Time, Cp0, Config]), % ping ourself! + rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]), + rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]), + rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]), + rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]), + rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]), + + %% sleep to make the partitioned net ready + ct:sleep(Time - msec()), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + + pong = net_adm:ping(Cp0), + pong = net_adm:ping(Cp1), + pong = net_adm:ping(Cp2), + pong = net_adm:ping(Cp3), + pong = net_adm:ping(Cp4), + pong = net_adm:ping(Cp5), + + wait_for_ready_net(Nodes, Config), + + %% Just make sure that all nodes have the same picture of all names + check_everywhere(Nodes, single_name, Config), + assert_pid(global:whereis_name(single_name)), + ?UNTIL(begin {Ns2, []} = rpc:multicall(Nodes, erlang, whereis, [single_name]), @@ -1686,10 +1656,10 @@ simple_line(Config) when is_list(Config) -> end, 0, Ns2) end), - - ?line assert_pid(global:send(single_name, die)), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + assert_pid(global:send(single_name, die)), + + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_node(Cp0), @@ -1698,82 +1668,74 @@ simple_line(Config) when is_list(Config) -> stop_node(Cp3), stop_node(Cp4), stop_node(Cp5), - ?line init_condition(Config), + init_condition(Config), ok. - -otp_1849(suite) -> []; -otp_1849(doc) -> - ["Test ticket: Global should keep track of all pids that set the same lock."]; + +%% Test ticket: Global should keep track of all pids that set the same lock. otp_1849(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_node(cp3, Config), - - ?line wait_for_ready_net(Config), - - % start procs on each node - ?line Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []), - ?line assert_pid(Pid1), - ?line Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []), - ?line assert_pid(Pid2), - ?line Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []), - ?line assert_pid(Pid3), - - % set a lock on every node - ?line true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}), - ?line true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}), - ?line true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}), - - ?line - ?UNTIL(begin + init_condition(Config), + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_node(cp3, Config), + + wait_for_ready_net(Config), + + %% start procs on each node + Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []), + assert_pid(Pid1), + Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []), + assert_pid(Pid2), + Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []), + assert_pid(Pid3), + + %% set a lock on every node + true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}), + true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}), + true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}), + + ?UNTIL(begin [{test_lock, ?MODULE, Lock1}] = rpc:call(Cp1, ets, tab2list, [global_locks]), 3 =:= length(Lock1) end), - ?line true = req(Pid3, {del_lock2, {test_lock, ?MODULE}, self()}), - ?line + true = req(Pid3, {del_lock2, {test_lock, ?MODULE}, self()}), ?UNTIL(begin [{test_lock, ?MODULE, Lock2}] = rpc:call(Cp1, ets, tab2list, [global_locks]), 2 =:= length(Lock2) end), - ?line true = req(Pid2, {del_lock2, {test_lock, ?MODULE}, self()}), - ?line + true = req(Pid2, {del_lock2, {test_lock, ?MODULE}, self()}), ?UNTIL(begin [{test_lock, ?MODULE, Lock3}] = rpc:call(Cp1, ets, tab2list, [global_locks]), 1 =:= length(Lock3) end), - ?line true = req(Pid1, {del_lock2, {test_lock, ?MODULE}, self()}), - ?line ?UNTIL([] =:= rpc:call(Cp1, ets, tab2list, [global_locks])), + true = req(Pid1, {del_lock2, {test_lock, ?MODULE}, self()}), + ?UNTIL([] =:= rpc:call(Cp1, ets, tab2list, [global_locks])), - ?line true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}), - ?line true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}), - ?line true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}), - ?line false = req(Pid2, {set_lock2, {test_lock, not_valid}, self()}), + true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}), + true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}), + true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}), + false = req(Pid2, {set_lock2, {test_lock, not_valid}, self()}), exit_p(Pid1), - ?line ?UNTIL(begin [{test_lock, ?MODULE, Lock10}] = rpc:call(Cp1, ets, tab2list, [global_locks]), 2 =:= length(Lock10) end), - ?line ?UNTIL(begin [{test_lock, ?MODULE, Lock11}] = rpc:call(Cp2, ets, tab2list, [global_locks]), 2 =:= length(Lock11) end), - ?line ?UNTIL(begin [{test_lock, ?MODULE, Lock12}] = rpc:call(Cp3, ets, tab2list, [global_locks]), @@ -1784,13 +1746,11 @@ otp_1849(Config) when is_list(Config) -> stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. - -otp_3162(suite) -> []; -otp_3162(doc) -> - ["Test ticket: Deadlock in global"]; + +%% Test ticket: Deadlock in global. otp_3162(Config) when is_list(Config) -> StartFun = fun() -> {ok, Cp1} = start_node(cp1, Config), @@ -1804,77 +1764,74 @@ do_otp_3162(StartFun, Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line [Cp1, Cp2, Cp3] = StartFun(), + init_condition(Config), + [Cp1, Cp2, Cp3] = StartFun(), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % start procs on each node - ?line Pid1 = rpc:call(Cp1, ?MODULE, start_proc4, [kalle]), - ?line assert_pid(Pid1), - ?line Pid2 = rpc:call(Cp2, ?MODULE, start_proc4, [stina]), - ?line assert_pid(Pid2), - ?line Pid3 = rpc:call(Cp3, ?MODULE, start_proc4, [vera]), - ?line assert_pid(Pid3), + %% start procs on each node + Pid1 = rpc:call(Cp1, ?MODULE, start_proc4, [kalle]), + assert_pid(Pid1), + Pid2 = rpc:call(Cp2, ?MODULE, start_proc4, [stina]), + assert_pid(Pid2), + Pid3 = rpc:call(Cp3, ?MODULE, start_proc4, [vera]), + assert_pid(Pid3), - ?line rpc_disconnect_node(Cp1, Cp2, Config), + rpc_disconnect_node(Cp1, Cp2, Config), - ?line ?UNTIL + ?UNTIL ([Cp3] =:= lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]), ?UNTIL([kalle, vera] =:= - lists:sort(rpc:call(Cp1, global, registered_names, []))), - ?line ?UNTIL + lists:sort(rpc:call(Cp1, global, registered_names, []))), + ?UNTIL ([Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]), ?UNTIL([stina, vera] =:= - lists:sort(rpc:call(Cp2, global, registered_names, []))), - ?line ?UNTIL + lists:sort(rpc:call(Cp2, global, registered_names, []))), + ?UNTIL ([Cp1, Cp2] =:= - lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]), + lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]), ?UNTIL([kalle, stina, vera] =:= - lists:sort(rpc:call(Cp3, global, registered_names, []))), + lists:sort(rpc:call(Cp3, global, registered_names, []))), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1]), + pong = rpc:call(Cp2, net_adm, ping, [Cp1]), - ?line ?UNTIL + ?UNTIL ([Cp2, Cp3] =:= - lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]), - ?line + lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]), ?UNTIL(begin NN = lists:sort(rpc:call(Cp1, global, registered_names, [])), [kalle, stina, vera] =:= NN end), - ?line ?UNTIL + ?UNTIL ([Cp1, Cp3] =:= - lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]), + lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]), ?UNTIL([kalle, stina, vera] =:= - lists:sort(rpc:call(Cp2, global, registered_names, []))), - ?line ?UNTIL + lists:sort(rpc:call(Cp2, global, registered_names, []))), + ?UNTIL ([Cp1, Cp2] =:= - lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]), + lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]), ?UNTIL([kalle, stina, vera] =:= - lists:sort(rpc:call(Cp3, global, registered_names, []))), + lists:sort(rpc:call(Cp3, global, registered_names, []))), write_high_level_trace(Config), stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line init_condition(Config), + init_condition(Config), ok. - -otp_5640(suite) -> []; -otp_5640(doc) -> - ["OTP-5640. 'allow' multiple names for registered processes."]; + +%% OTP-5640. 'allow' multiple names for registered processes. otp_5640(Config) when is_list(Config) -> Timeout = 25, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), init_condition(Config), - ?line {ok, B} = start_node(b, Config), + {ok, B} = start_node(b, Config), - ?line Nodes = lists:sort([node(), B]), - ?line wait_for_ready_net(Nodes, Config), + Nodes = lists:sort([node(), B]), + wait_for_ready_net(Nodes, Config), Server = whereis(global_name_server), ServerB = rpc:call(B, erlang, whereis, [global_name_server]), @@ -1882,50 +1839,50 @@ otp_5640(Config) when is_list(Config) -> Me = self(), Proc = spawn(fun() -> otp_5640_proc(Me) end), - ?line yes = global:register_name(name1, Proc), - ?line no = global:register_name(name2, Proc), + yes = global:register_name(name1, Proc), + no = global:register_name(name2, Proc), - ?line ok = application:set_env(kernel, global_multi_name_action, allow), - ?line yes = global:register_name(name2, Proc), + ok = application:set_env(kernel, global_multi_name_action, allow), + yes = global:register_name(name2, Proc), - test_server:sleep(100), - ?line Proc = global:whereis_name(name1), - ?line Proc = global:whereis_name(name2), - ?line check_everywhere(Nodes, name1, Config), - ?line check_everywhere(Nodes, name2, Config), + ct:sleep(100), + Proc = global:whereis_name(name1), + Proc = global:whereis_name(name2), + check_everywhere(Nodes, name1, Config), + check_everywhere(Nodes, name2, Config), - ?line {monitors_2levels, MonBy1} = mon_by_servers(Proc), - ?line [] = ([Server,Server,ServerB,ServerB] -- MonBy1), - ?line {links,[]} = process_info(Proc, links), - ?line _ = global:unregister_name(name1), + {monitors_2levels, MonBy1} = mon_by_servers(Proc), + [] = ([Server,Server,ServerB,ServerB] -- MonBy1), + {links,[]} = process_info(Proc, links), + _ = global:unregister_name(name1), - test_server:sleep(100), - ?line undefined = global:whereis_name(name1), - ?line Proc = global:whereis_name(name2), - ?line check_everywhere(Nodes, name1, Config), - ?line check_everywhere(Nodes, name2, Config), + ct:sleep(100), + undefined = global:whereis_name(name1), + Proc = global:whereis_name(name2), + check_everywhere(Nodes, name1, Config), + check_everywhere(Nodes, name2, Config), - ?line {monitors_2levels, MonBy2} = mon_by_servers(Proc), - ?line [] = ([Server,ServerB] -- MonBy2), + {monitors_2levels, MonBy2} = mon_by_servers(Proc), + [] = ([Server,ServerB] -- MonBy2), TmpMonBy2 = MonBy2 -- [Server,ServerB], - ?line TmpMonBy2 = TmpMonBy2 -- [Server,ServerB], - ?line {links,[]} = process_info(Proc, links), + TmpMonBy2 = TmpMonBy2 -- [Server,ServerB], + {links,[]} = process_info(Proc, links), - ?line yes = global:register_name(name1, Proc), + yes = global:register_name(name1, Proc), Proc ! die, - test_server:sleep(100), - ?line undefined = global:whereis_name(name1), - ?line undefined = global:whereis_name(name2), - ?line check_everywhere(Nodes, name1, Config), - ?line check_everywhere(Nodes, name2, Config), - ?line {monitors, GMonitors} = process_info(Server, monitors), - ?line false = lists:member({process, Proc}, GMonitors), + ct:sleep(100), + undefined = global:whereis_name(name1), + undefined = global:whereis_name(name2), + check_everywhere(Nodes, name1, Config), + check_everywhere(Nodes, name2, Config), + {monitors, GMonitors} = process_info(Server, monitors), + false = lists:member({process, Proc}, GMonitors), write_high_level_trace(Config), stop_node(B), - ?line init_condition(Config), + init_condition(Config), ok. otp_5640_proc(_Parent) -> @@ -1934,45 +1891,42 @@ otp_5640_proc(_Parent) -> exit(normal) end. -otp_5737(suite) -> []; -otp_5737(doc) -> - ["OTP-5737. set_lock/3 and trans/4 accept Retries = 0."]; +%% OTP-5737. set_lock/3 and trans/4 accept Retries = 0. otp_5737(Config) when is_list(Config) -> Timeout = 25, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), LockId = {?MODULE,self()}, Nodes = [node()], - ?line {'EXIT', _} = (catch global:set_lock(LockId, Nodes, -1)), - ?line {'EXIT', _} = (catch global:set_lock(LockId, Nodes, a)), - ?line true = global:set_lock(LockId, Nodes, 0), + {'EXIT', _} = (catch global:set_lock(LockId, Nodes, -1)), + {'EXIT', _} = (catch global:set_lock(LockId, Nodes, a)), + true = global:set_lock(LockId, Nodes, 0), Time1 = now(), - ?line false = global:set_lock({?MODULE,not_me}, Nodes, 0), - ?line true = timer:now_diff(now(), Time1) < 5000, - ?line _ = global:del_lock(LockId, Nodes), + false = global:set_lock({?MODULE,not_me}, Nodes, 0), + true = timer:now_diff(now(), Time1) < 5000, + _ = global:del_lock(LockId, Nodes), Fun = fun() -> ok end, - ?line {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, -1)), - ?line {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, a)), - ?line ok = global:trans(LockId, Fun, Nodes, 0), + {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, -1)), + {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, a)), + ok = global:trans(LockId, Fun, Nodes, 0), write_high_level_trace(Config), - ?line init_condition(Config), + init_condition(Config), ok. -otp_6931(suite) -> []; -otp_6931(doc) -> ["OTP-6931. Ignore nodeup when connect_all=false."]; +%% OTP-6931. Ignore nodeup when connect_all=false. otp_6931(Config) when is_list(Config) -> Me = self(), - ?line {ok, CAf} = start_non_connecting_node(ca_false, Config), - ?line ok = rpc:call(CAf, error_logger, add_report_handler, [?MODULE, Me]), - ?line info = rpc:call(CAf, error_logger, warning_map, []), - ?line {global_name_server,CAf} ! {nodeup, fake_node}, + {ok, CAf} = start_non_connecting_node(ca_false, Config), + ok = rpc:call(CAf, error_logger, add_report_handler, [?MODULE, Me]), + info = rpc:call(CAf, error_logger, warning_map, []), + {global_name_server,CAf} ! {nodeup, fake_node}, timer:sleep(100), stop_node(CAf), - receive {nodeup,fake_node} -> test_server:fail({info_report, was, sent}) + receive {nodeup,fake_node} -> ct:fail({info_report, was, sent}) after 1000 -> ok end, ok. @@ -1980,18 +1934,17 @@ otp_6931(Config) when is_list(Config) -> %%%----------------------------------------------------------------- %%% Testing a disconnected node. Not two partitions. %%%----------------------------------------------------------------- -simple_disconnect(suite) -> []; -simple_disconnect(doc) -> ["OTP-5563. Disconnected nodes (not partitions)"]; +%% OTP-5563. Disconnected nodes (not partitions). simple_disconnect(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), %% Three nodes (test_server, n_1, n_2). - ?line [Cp1, Cp2] = Cps = start_nodes([n_1, n_2], peer, Config), - ?line wait_for_ready_net(Config), + [Cp1, Cp2] = Cps = start_nodes([n_1, n_2], peer, Config), + wait_for_ready_net(Config), Nodes = lists:sort([node() | Cps]), @@ -2001,39 +1954,39 @@ simple_disconnect(Config) when is_list(Config) -> Resolver = {no_module, resolve_none}, % will never be called PingNode = Cp2, - ?line {_Pid1, yes} = + {_Pid1, yes} = rpc:call(Cp1, ?MODULE, start_resolver, [Name, Resolver]), - test_server:sleep(100), + ct:sleep(100), %% Disconnect test_server and Cp2. - ?line true = erlang:disconnect_node(Cp2), - test_server:sleep(500), + true = erlang:disconnect_node(Cp2), + ct:sleep(500), %% _Pid is registered on Cp1. The exchange of names between Cp2 and %% test_server sees two identical pids. - ?line pong = net_adm:ping(PingNode), - ?line ?UNTIL(Cps =:= lists:sort(nodes())), + pong = net_adm:ping(PingNode), + ?UNTIL(Cps =:= lists:sort(nodes())), - ?line {_, Trace0} = collect_tracers(Nodes), - ?line Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0], - ?line lists:foreach(fun(P) -> P ! die end, Resolvers), - ?line lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers), - ?line check_everywhere(Nodes, Name, Config), - ?line undefined = global:whereis_name(Name), + {_, Trace0} = collect_tracers(Nodes), + Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0], + lists:foreach(fun(P) -> P ! die end, Resolvers), + lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers), + check_everywhere(Nodes, Name, Config), + undefined = global:whereis_name(Name), - ?line {_, Trace1} = collect_tracers(Nodes), + {_, Trace1} = collect_tracers(Nodes), Trace = Trace0 ++ Trace1, - ?line [] = [foo || {_, resolve_none, _, _} <- Trace], + [] = [foo || {_, resolve_none, _, _} <- Trace], - ?line Gs = name_servers(Nodes), - ?line [_, _, _] = monitored_by_node(Trace, Gs), + Gs = name_servers(Nodes), + [_, _, _] = monitored_by_node(Trace, Gs), lists:foreach(fun(N) -> rpc:call(N, ?MODULE, stop_tracer, []) end, Nodes), - ?line OrigNames = global:registered_names(), + OrigNames = global:registered_names(), write_high_level_trace(Config), stop_nodes(Cps), - ?line init_condition(Config), + init_condition(Config), ok. %% Not used right now. @@ -2052,7 +2005,7 @@ simple_dis(Nodes0, Name, Resolver, Config) -> simple_dis_node(_Node, DisNodes, _Name, _Resolver, Config) -> lists:foreach( fun(OtherNode) -> _ = erlang:disconnect_node(OtherNode) end, DisNodes), - ?line ?UNTIL(DisNodes -- nodes() =:= DisNodes), + ?UNTIL(DisNodes -- nodes() =:= DisNodes), ok. @@ -2072,19 +2025,18 @@ simple_dis_node(_Node, DisNodes, _Name, _Resolver, Config) -> -define(RES(F), {F, fun ?MODULE:F/3}). -simple_resolve(suite) -> []; -simple_resolve(doc) -> ["OTP-5563. Partitions and names."]; +%% OTP-5563. Partitions and names. simple_resolve(Config) when is_list(Config) -> Timeout = 360, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), + [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), Nodes = lists:sort([node() | Cps]), - ?line wait_for_ready_net(Config), - + wait_for_ready_net(Config), + lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end, Nodes), @@ -2193,20 +2145,19 @@ simple_resolve(Config) when is_list(Config) -> %% then a new attempt (nodeup etc.) is made. This time the %% resolver does not disconnect any node. res(?RES(disconnect_first), Cps, Cf#cf{link = Z2, n2 = Z2, - nodes = [node(), N1, A2, Z2]}), + nodes = [node(), N1, A2, Z2]}), - ?line lists:foreach(fun(N) -> - rpc:call(N, ?MODULE, stop_tracer, []) - end, Nodes), + lists:foreach(fun(N) -> + rpc:call(N, ?MODULE, stop_tracer, []) + end, Nodes), - ?line OrigNames = global:registered_names(), + OrigNames = global:registered_names(), write_high_level_trace(Config), stop_nodes(Cps), - ?line init_condition(Config), + init_condition(Config), ok. -simple_resolve2(suite) -> []; -simple_resolve2(doc) -> ["OTP-5563. Partitions and names."]; +%% OTP-5563. Partitions and names. simple_resolve2(Config) when is_list(Config) -> %% Continuation of simple_resolve. Of some reason it did not %% always work to re-start z_2. "Cannot be a global bug." @@ -2214,13 +2165,13 @@ simple_resolve2(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), - ?line wait_for_ready_net(Config), + [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), + wait_for_ready_net(Config), Nodes = lists:sort([node() | Cps]), - + lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end, Nodes), @@ -2230,33 +2181,32 @@ simple_resolve2(Config) when is_list(Config) -> %% Halt z_2. res(?RES(halt_second), Cps, Cf#cf{link = N1, n1 = N1, n2 = Z2, ping = A2, - nodes = [node(), N1, A2], n_res = 1}), + nodes = [node(), N1, A2], n_res = 1}), - ?line lists:foreach(fun(N) -> - rpc:call(N, ?MODULE, stop_tracer, []) - end, Nodes), + lists:foreach(fun(N) -> + rpc:call(N, ?MODULE, stop_tracer, []) + end, Nodes), - ?line OrigNames = global:registered_names(), + OrigNames = global:registered_names(), write_high_level_trace(Config), stop_nodes(Cps), % Not all nodes may be present, but it works anyway. - ?line init_condition(Config), + init_condition(Config), ok. -simple_resolve3(suite) -> []; -simple_resolve3(doc) -> ["OTP-5563. Partitions and names."]; +%% OTP-5563. Partitions and names. simple_resolve3(Config) when is_list(Config) -> %% Continuation of simple_resolve. Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), - ?line wait_for_ready_net(Config), + [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), + wait_for_ready_net(Config), Nodes = lists:sort([node() | Cps]), - + lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end, Nodes), @@ -2267,27 +2217,27 @@ simple_resolve3(Config) when is_list(Config) -> %% Halt a_2. res(?RES(halt_second), Cps, Cf#cf{link = node(), n2 = A2, nodes = [node(), N1], n_res = 1}), - - ?line lists:foreach(fun(N) -> - rpc:call(N, ?MODULE, stop_tracer, []) - end, Nodes), - ?line OrigNames = global:registered_names(), + lists:foreach(fun(N) -> + rpc:call(N, ?MODULE, stop_tracer, []) + end, Nodes), + + OrigNames = global:registered_names(), write_high_level_trace(Config), stop_nodes(Cps), % Not all nodes may be present, but it works anyway. - ?line init_condition(Config), + init_condition(Config), ok. res({Res,Resolver}, [N1, A2, Z2], Cf) -> %% Note: there are no links anymore, but monitors. #cf{link = LinkedNode, ping = PingNode, n1 = Res1, n2 = OtherNode, nodes = Nodes0, n_res = NRes, config = Config} = Cf, - ?t:format("~n~nResolver: ~p", [Res]), - ?t:format(" Registered on partition 1: ~p", [Res1]), - ?t:format(" Registered on partition 2: ~p", [OtherNode]), - ?t:format(" Pinged node: ~p", [PingNode]), - ?t:format(" Linked node: ~p", [LinkedNode]), - ?t:format(" Expected # resolvers: ~p", [NRes]), + io:format("~n~nResolver: ~p", [Res]), + io:format(" Registered on partition 1: ~p", [Res1]), + io:format(" Registered on partition 2: ~p", [OtherNode]), + io:format(" Pinged node: ~p", [PingNode]), + io:format(" Linked node: ~p", [LinkedNode]), + io:format(" Expected # resolvers: ~p", [NRes]), Nodes = lists:sort(Nodes0), T1 = node(), Part1 = [T1, N1], @@ -2299,67 +2249,67 @@ res({Res,Resolver}, [N1, A2, Z2], Cf) -> %% expected monitors remain between registered processes and the %% global_name_server. - ?line rpc_cast(OtherNode, - ?MODULE, - part_2_2, - [Config, Part1, Part2, [{Name, Resolver}]]), - ?line ?UNTIL(is_ready_partition(Config)), - ?line {_Pid1, yes} = + rpc_cast(OtherNode, + ?MODULE, + part_2_2, + [Config, Part1, Part2, [{Name, Resolver}]]), + ?UNTIL(is_ready_partition(Config)), + {_Pid1, yes} = rpc:call(Res1, ?MODULE, start_resolver, [Name, Resolver]), - ?line pong = net_adm:ping(PingNode), - ?line wait_for_ready_net(Nodes, Config), + pong = net_adm:ping(PingNode), + wait_for_ready_net(Nodes, Config), - ?line check_everywhere(Nodes, Name, Config), - ?line case global:whereis_name(Name) of - undefined when LinkedNode =:= none -> ok; - Pid -> assert_pid(Pid) - end, + check_everywhere(Nodes, Name, Config), + case global:whereis_name(Name) of + undefined when LinkedNode =:= none -> ok; + Pid -> assert_pid(Pid) + end, - ?line {_, Trace0} = collect_tracers(Nodes), - ?line Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0], + {_, Trace0} = collect_tracers(Nodes), + Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0], - ?line NRes = length(Resolvers), + NRes = length(Resolvers), %% Wait for extra monitor processes to be created. %% This applies as long as global:do_monitor/1 spawns processes. %% (Some day monitor() will be truly synchronous.) - test_server:sleep(100), + ct:sleep(100), - ?line lists:foreach(fun(P) -> P ! die end, Resolvers), - ?line lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers), + lists:foreach(fun(P) -> P ! die end, Resolvers), + lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers), - ?line check_everywhere(Nodes, Name, Config), - ?line undefined = global:whereis_name(Name), + check_everywhere(Nodes, Name, Config), + undefined = global:whereis_name(Name), %% Wait for monitors to remove names. - test_server:sleep(100), + ct:sleep(100), - ?line {_, Trace1} = collect_tracers(Nodes), + {_, Trace1} = collect_tracers(Nodes), Trace = Trace0 ++ Trace1, - ?line Gs = name_servers([T1, N1, A2, Z2]), - ?line MonitoredByNode = monitored_by_node(Trace, Gs), - ?line MonitoredBy = [M || {_N,M} <- MonitoredByNode], - + Gs = name_servers([T1, N1, A2, Z2]), + MonitoredByNode = monitored_by_node(Trace, Gs), + MonitoredBy = [M || {_N,M} <- MonitoredByNode], + X = MonitoredBy -- Gs, LengthGs = length(Gs), - ?line case MonitoredBy of - [] when LinkedNode =:= none -> ok; - Gs -> ok; - _ when LengthGs < 4, X =:= [] -> ok; - _ -> ?t:format("ERROR:~nMonitoredBy ~p~n" - "global_name_servers ~p~n", - [MonitoredByNode, Gs]), - ?t:fail(monitor_mismatch) - end, + case MonitoredBy of + [] when LinkedNode =:= none -> ok; + Gs -> ok; + _ when LengthGs < 4, X =:= [] -> ok; + _ -> io:format("ERROR:~nMonitoredBy ~p~n" + "global_name_servers ~p~n", + [MonitoredByNode, Gs]), + ct:fail(monitor_mismatch) + end, ok. name_servers(Nodes) -> lists:sort([rpc:call(N, erlang, whereis, [global_name_server]) || N <- Nodes, pong =:= net_adm:ping(N)]). - + monitored_by_node(Trace, Servers) -> lists:sort([{node(M),M} || {_Node,_P,died,{monitors_2levels,ML}} <- Trace, @@ -2371,7 +2321,7 @@ part_2_2(Config, Part1, Part2, NameResolvers) -> make_partition(Config, Part1, Part2), lists:foreach (fun({Name, Resolver}) -> - ?line {Pid2, yes} = start_resolver(Name, Resolver), + {Pid2, yes} = start_resolver(Name, Resolver), trace_message({node(), part_2_2, nodes(), {pid2,Pid2}}) end, NameResolvers). @@ -2396,7 +2346,7 @@ exit_resolver(name, _Pid1, _Pid2) -> lock_resolver(name, Pid1, _Pid2) -> Id = {?MODULE, self()}, Nodes = [node()], - ?line true = global:set_lock(Id, Nodes), + true = global:set_lock(Id, Nodes), _ = global:del_lock(Id, Nodes), Pid1. @@ -2426,7 +2376,7 @@ start_resolver(Name, Resolver) -> receive {Pid, Res} -> {Pid, Res} end. - + init_resolver(Parent, Name, Resolver) -> X = global:register_name(Name, self(), Resolver), Parent ! {self(), X}, @@ -2455,18 +2405,17 @@ mon_by_servers(Proc) -> -define(REGNAME, contact_a_2). -leftover_name(suite) -> []; -leftover_name(doc) -> ["OTP-5563. Bug: nodedown while synching."]; +%% OTP-5563. Bug: nodedown while synching. leftover_name(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), - ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), + init_condition(Config), + OrigNames = global:registered_names(), + [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config), Nodes = lists:sort([node() | Cps]), - ?line wait_for_ready_net(Config), - + wait_for_ready_net(Config), + lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end, Nodes), @@ -2474,20 +2423,20 @@ leftover_name(Config) when is_list(Config) -> Name = name, % registered on a_2 ResName = resolved_name, % registered on n_1 and a_2 %% - ?line _Pid = ping_a_2_fun(?REGNAME, N1, A2), + _Pid = ping_a_2_fun(?REGNAME, N1, A2), T1 = node(), Part1 = [T1, N1], Part2 = [A2, Z2], NoResolver = {no_module, resolve_none}, Resolver = fun contact_a_2/3, - ?line rpc_cast(A2, - ?MODULE, part_2_2, [Config, - Part1, - Part2, - [{Name, NoResolver}, - {ResName, Resolver}]]), - ?line ?UNTIL(is_ready_partition(Config)), + rpc_cast(A2, + ?MODULE, part_2_2, [Config, + Part1, + Part2, + [{Name, NoResolver}, + {ResName, Resolver}]]), + ?UNTIL(is_ready_partition(Config)), %% resolved_name is resolved to run on a_2, an insert operation is %% sent to n_1. The resolver function halts a_2, but the nodedown @@ -2496,36 +2445,36 @@ leftover_name(Config) when is_list(Config) -> %% delayed). Unless "artificial" nodedown messages are sent the %% name would linger on indefinitely. [There is no test case for %% the situation that no nodedown message at all is sent.] - ?line {_Pid1, yes} = + {_Pid1, yes} = rpc:call(N1, ?MODULE, start_resolver, [ResName, fun contact_a_2/3]), - test_server:sleep(1000), + ct:sleep(1000), - ?line trace_message({node(), pinging, z_2}), - ?line pong = net_adm:ping(Z2), - ?line ?UNTIL((Nodes -- [A2]) =:= lists:sort(?NODES)), - ?t:sleep(1000), + trace_message({node(), pinging, z_2}), + pong = net_adm:ping(Z2), + ?UNTIL((Nodes -- [A2]) =:= lists:sort(?NODES)), + ct:sleep(1000), - ?line {_,Trace0} = collect_tracers(Nodes), + {_,Trace0} = collect_tracers(Nodes), - ?line Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0], - ?line lists:foreach(fun(P) -> P ! die end, Resolvers), - ?line lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers), + Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0], + lists:foreach(fun(P) -> P ! die end, Resolvers), + lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers), - ?line lists:foreach(fun(N) -> - rpc:call(N, ?MODULE, stop_tracer, []) - end, Nodes), + lists:foreach(fun(N) -> + rpc:call(N, ?MODULE, stop_tracer, []) + end, Nodes), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), stop_nodes(Cps), - ?line init_condition(Config), + init_condition(Config), ok. %% Runs on n_1 contact_a_2(resolved_name, Pid1, Pid2) -> trace_message({node(), ?REGNAME, {pid1,Pid1}, {pid2,Pid2}, - {node1,node(Pid1)}, {node2,node(Pid2)}}), + {node1,node(Pid1)}, {node2,node(Pid2)}}), ?REGNAME ! doit, Pid2. @@ -2543,15 +2492,14 @@ ping_a_2(RegName, N1, A2) -> {nodedown, A2} -> ok end end. - + halt_node(Node) -> rpc:call(Node, erlang, halt, []). %%%----------------------------------------------------------------- %%% Testing re-registration of a name. %%%----------------------------------------------------------------- -re_register_name(suite) -> []; -re_register_name(doc) -> ["OTP-5563. Name is re-registered."]; +%% OTP-5563. Name is re-registered. re_register_name(Config) when is_list(Config) -> %% When re-registering a name the link to the old pid used to %% linger on. Don't think is was a serious bug though--some memory @@ -2560,18 +2508,18 @@ re_register_name(Config) when is_list(Config) -> Timeout = 15, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), Me = self(), Pid1 = spawn(fun() -> proc(Me) end), - ?line yes = global:register_name(name, Pid1), + yes = global:register_name(name, Pid1), Pid2 = spawn(fun() -> proc(Me) end), - ?line _ = global:re_register_name(name, Pid2), + _ = global:re_register_name(name, Pid2), Pid2 ! die, Pid1 ! die, receive {Pid1, MonitoredBy1} -> [] = MonitoredBy1 end, receive {Pid2, MonitoredBy2} -> [_] = MonitoredBy2 end, - ?line _ = global:unregister_name(name), - ?line init_condition(Config), + _ = global:unregister_name(name), + init_condition(Config), ok. proc(Parent) -> @@ -2583,15 +2531,14 @@ proc(Parent) -> %%%----------------------------------------------------------------- %%% %%%----------------------------------------------------------------- -name_exit(suite) -> []; -name_exit(doc) -> ["OTP-5563. Registered process dies."]; +%% OTP-5563. Registered process dies. name_exit(Config) when is_list(Config) -> StartFun = fun() -> {ok, N1} = start_node_rel(n_1, this, Config), {ok, N2} = start_node_rel(n_2, this, Config), [N1, N2] end, - ?t:format("Test of current release~n"), + io:format("Test of current release~n"), do_name_exit(StartFun, current, Config). do_name_exit(StartFun, Version, Config) -> @@ -2607,17 +2554,17 @@ do_name_exit(StartFun, Version, Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), %% Three nodes (test_server, n_1, n_2). - ?line Cps = StartFun(), + Cps = StartFun(), Nodes = lists:sort([node() | Cps]), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end,Nodes), Name = name, - ?line {Pid, yes} = start_proc(Name), + {Pid, yes} = start_proc(Name), Me = self(), LL = spawn(fun() -> long_lock(Me) end), @@ -2628,23 +2575,23 @@ do_name_exit(StartFun, Version, Config) -> Pid ! die, wait_for_exit_fast(Pid), - ?t:sleep(100), + ct:sleep(100), %% Name has been removed from node()'s table, but nowhere else %% since there is a lock on 'global'. {R1,[]} = rpc:multicall(Nodes, global, whereis_name, [Name]), - ?line case Version of - old -> [_,_] = lists:usort(R1); - current -> [undefined, undefined, undefined] = R1 - end, - ?t:sleep(3000), - ?line check_everywhere(Nodes, Name, Config), + case Version of + old -> [_,_] = lists:usort(R1); + current -> [undefined, undefined, undefined] = R1 + end, + ct:sleep(3000), + check_everywhere(Nodes, Name, Config), lists:foreach(fun(N) -> rpc:call(N, ?MODULE, stop_tracer, []) end, Nodes), - ?line OrigNames = global:registered_names(), + OrigNames = global:registered_names(), exit(LL, kill), write_high_level_trace(Config), stop_nodes(Cps), - ?line init_condition(Config), + init_condition(Config), ok. long_lock(Parent) -> @@ -2657,17 +2604,16 @@ long_lock(Parent) -> %%%----------------------------------------------------------------- %%% Testing the support for external nodes (cnodes) %%%----------------------------------------------------------------- -external_nodes(suite) -> []; -external_nodes(doc) -> ["OTP-5563. External nodes (cnodes)."]; +%% OTP-5563. External nodes (cnodes). external_nodes(Config) when is_list(Config) -> Timeout = 30, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), - ?line [NodeB, NodeC] = start_nodes([b, c], peer, Config), - ?line wait_for_ready_net(Config), + [NodeB, NodeC] = start_nodes([b, c], peer, Config), + wait_for_ready_net(Config), %% Nodes = ?NODES, %% lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end, @@ -2676,75 +2622,75 @@ external_nodes(Config) when is_list(Config) -> %% Two partitions: [test_server] and [b, c]. %% c registers an external name on b - ?line rpc_cast(NodeB, ?MODULE, part_ext, - [Config, node(), NodeC, Name]), - ?line ?UNTIL(is_ready_partition(Config)), + rpc_cast(NodeB, ?MODULE, part_ext, + [Config, node(), NodeC, Name]), + ?UNTIL(is_ready_partition(Config)), - ?line pong = net_adm:ping(NodeB), - ?line ?UNTIL([NodeB, NodeC] =:= lists:sort(nodes())), - ?line wait_for_ready_net(Config), + pong = net_adm:ping(NodeB), + ?UNTIL([NodeB, NodeC] =:= lists:sort(nodes())), + wait_for_ready_net(Config), - ?line Cpid = rpc:call(NodeC, erlang, whereis, [Name]), + Cpid = rpc:call(NodeC, erlang, whereis, [Name]), ExternalName = [{name,Cpid,NodeB}], - ?line ExternalName = get_ext_names(), - ?line ExternalName = rpc:call(NodeB, gen_server, call, - [global_name_server, get_names_ext]), - ?line ExternalName = rpc:call(NodeC, gen_server, call, - [global_name_server, get_names_ext]), - - ?line [_] = cnode_links(Cpid), - ?line [_,_,_] = cnode_monitored_by(Cpid), - ?line no = global:register_name(Name, self()), - ?line yes = global:re_register_name(Name, self()), - ?line ?UNTIL([] =:= cnode_monitored_by(Cpid)), - ?line ?UNTIL([] =:= cnode_links(Cpid)), - ?line [] = gen_server:call(global_name_server, get_names_ext, infinity), - - ?line Cpid ! {register, self(), Name}, - ?line receive {Cpid, Reply1} -> no = Reply1 end, - ?line _ = global:unregister_name(Name), - test_server:sleep(1000), - ?line Cpid ! {register, self(), Name}, - ?line ?UNTIL(length(get_ext_names()) =:= 1), - ?line receive {Cpid, Reply2} -> yes = Reply2 end, - - ?line Cpid ! {unregister, self(), Name}, - ?line ?UNTIL(length(get_ext_names()) =:= 0), - ?line receive {Cpid, Reply3} -> ok = Reply3 end, + ExternalName = get_ext_names(), + ExternalName = rpc:call(NodeB, gen_server, call, + [global_name_server, get_names_ext]), + ExternalName = rpc:call(NodeC, gen_server, call, + [global_name_server, get_names_ext]), + + [_] = cnode_links(Cpid), + [_,_,_] = cnode_monitored_by(Cpid), + no = global:register_name(Name, self()), + yes = global:re_register_name(Name, self()), + ?UNTIL([] =:= cnode_monitored_by(Cpid)), + ?UNTIL([] =:= cnode_links(Cpid)), + [] = gen_server:call(global_name_server, get_names_ext, infinity), + + Cpid ! {register, self(), Name}, + receive {Cpid, Reply1} -> no = Reply1 end, + _ = global:unregister_name(Name), + ct:sleep(1000), + Cpid ! {register, self(), Name}, + ?UNTIL(length(get_ext_names()) =:= 1), + receive {Cpid, Reply2} -> yes = Reply2 end, + + Cpid ! {unregister, self(), Name}, + ?UNTIL(length(get_ext_names()) =:= 0), + receive {Cpid, Reply3} -> ok = Reply3 end, Cpid ! die, - ?line ?UNTIL(OrigNames =:= global:registered_names()), - ?line [] = get_ext_names(), - ?line [] = rpc:call(NodeB, gen_server, call, - [global_name_server, get_names_ext]), - ?line [] = rpc:call(NodeC, gen_server, call, - [global_name_server, get_names_ext]), + ?UNTIL(OrigNames =:= global:registered_names()), + [] = get_ext_names(), + [] = rpc:call(NodeB, gen_server, call, + [global_name_server, get_names_ext]), + [] = rpc:call(NodeC, gen_server, call, + [global_name_server, get_names_ext]), - ?line Cpid2 = erlang:spawn(NodeC, fun() -> cnode_proc(NodeB) end), - ?line Cpid2 ! {register, self(), Name}, - ?line receive {Cpid2, Reply4} -> yes = Reply4 end, + Cpid2 = erlang:spawn(NodeC, fun() -> cnode_proc(NodeB) end), + Cpid2 ! {register, self(), Name}, + receive {Cpid2, Reply4} -> yes = Reply4 end, %% It could be a bug that Cpid2 is linked to 'global_name_server' %% at node 'b'. The effect: Cpid2 dies when node 'b' crashes. stop_node(NodeB), - ?line ?UNTIL(OrigNames =:= global:registered_names()), - ?line [] = get_ext_names(), - ?line [] = rpc:call(NodeC, gen_server, call, - [global_name_server, get_names_ext]), + ?UNTIL(OrigNames =:= global:registered_names()), + [] = get_ext_names(), + [] = rpc:call(NodeC, gen_server, call, + [global_name_server, get_names_ext]), - %% ?line {_, Trace} = collect_tracers(Nodes), + %% {_, Trace} = collect_tracers(Nodes), %% lists:foreach(fun(M) -> erlang:display(M) end, Trace), ThisNode = node(), - ?line Cpid3 = erlang:spawn(NodeC, fun() -> cnode_proc(ThisNode) end), - ?line Cpid3 ! {register, self(), Name}, - ?line receive {Cpid3, Reply5} -> yes = Reply5 end, + Cpid3 = erlang:spawn(NodeC, fun() -> cnode_proc(ThisNode) end), + Cpid3 ! {register, self(), Name}, + receive {Cpid3, Reply5} -> yes = Reply5 end, - ?line ?UNTIL(length(get_ext_names()) =:= 1), + ?UNTIL(length(get_ext_names()) =:= 1), stop_node(NodeC), - ?line ?UNTIL(length(get_ext_names()) =:= 0), + ?UNTIL(length(get_ext_names()) =:= 0), - ?line init_condition(Config), + init_condition(Config), ok. get_ext_names() -> @@ -2791,19 +2737,16 @@ cnode_proc(E) -> cnode_proc(E). -many_nodes(suite) -> - []; -many_nodes(doc) -> - ["OTP-5770. Start many nodes. Make them connect at the same time."]; +%% OTP-5770. Start many nodes. Make them connect at the same time. many_nodes(Config) when is_list(Config) -> Timeout = 240, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), {Rels, N_cps} = - case ?t:os_type() of + case test_server:os_type() of {unix, Osname} when Osname =:= linux; Osname =:= openbsd; Osname =:= darwin -> @@ -2814,12 +2757,12 @@ many_nodes(Config) when is_list(Config) -> _ -> {node_rel(1, 32, this), 32} end, - ?line Cps = [begin {ok, Cp} = start_node_rel(Name, Rel, Config), Cp end || - {Name,Rel} <- Rels], + Cps = [begin {ok, Cp} = start_node_rel(Name, Rel, Config), Cp end || + {Name,Rel} <- Rels], Nodes = lists:sort(?NODES), - ?line wait_for_ready_net(Nodes, Config), + wait_for_ready_net(Nodes, Config), - ?line Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), GoFile = filename:join([Dir, "go.txt"]), file:delete(GoFile), @@ -2830,34 +2773,34 @@ many_nodes(Config) when is_list(Config) -> file:delete(File), rpc_cast(N, ?MODULE, isolated_node, [File, GoFile, Cps, Config]) end, - ?line lists:foreach(IsoFun, CpsFiles), - - ?line all_nodes_files(CpsFiles, "isolated", Config), - ?line Time = msec(), - ?line sync_until(), + lists:foreach(IsoFun, CpsFiles), + + all_nodes_files(CpsFiles, "isolated", Config), + Time = msec(), + sync_until(), erlang:display(ready_to_go), - ?line touch(GoFile, "go"), - ?line all_nodes_files(CpsFiles, "done", Config), - ?line Time2 = msec(), + touch(GoFile, "go"), + all_nodes_files(CpsFiles, "done", Config), + Time2 = msec(), - ?line lists:foreach(fun(N) -> pong = net_adm:ping(N) end, Cps), + lists:foreach(fun(N) -> pong = net_adm:ping(N) end, Cps), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), write_high_level_trace(Config), % The test succeeded, but was it slow? - ?line lists:foreach(fun({_N, File}) -> file:delete(File) end, CpsFiles), - ?line file:delete(GoFile), + lists:foreach(fun({_N, File}) -> file:delete(File) end, CpsFiles), + file:delete(GoFile), - ?line ?UNTIL(OrigNames =:= global:registered_names()), + ?UNTIL(OrigNames =:= global:registered_names()), write_high_level_trace(Config), - ?line stop_nodes(Cps), - ?line init_condition(Config), + stop_nodes(Cps), + init_condition(Config), Diff = Time2 - Time, Return = lists:flatten(io_lib:format("~w nodes took ~w ms", [N_cps, Diff])), erlang:display({{nodes,N_cps},{time,Diff}}), - ?t:format("~s~n", [Return]), + io:format("~s~n", [Return]), {comment, Return}. node_rel(From, To, Rel) -> @@ -2883,7 +2826,7 @@ isolated_node(File, GoFile, Nodes, Config) -> touch(File, "got_go"), lists:foreach(fun(N) -> _ = net_adm:ping(N) end, shuffle(Nodes)), touch(File, "pinged"), - ?line ?UNTIL((Ns -- get_known(node())) =:= []), + ?UNTIL((Ns -- get_known(node())) =:= []), touch(File, "done"). touch(File, List) -> @@ -2931,19 +2874,17 @@ sync_until(LogFile) -> timer:sleep(Time). shuffle(L) -> - [E || {_, E} <- lists:keysort(1, [{random:uniform(), E} || E <- L])]. + [E || {_, E} <- lists:keysort(1, [{rand:uniform(), E} || E <- L])]. -sync_0(suite) -> []; -sync_0(doc) -> - ["OTP-5770. sync/0."]; +%% OTP-5770. sync/0. sync_0(Config) when is_list(Config) -> Timeout = 180, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), + init_condition(Config), N_cps = - case ?t:os_type() of + case test_server:os_type() of {unix, Osname} when Osname =:= linux; Osname =:= openbsd; Osname =:= darwin -> @@ -2958,82 +2899,80 @@ sync_0(Config) when is_list(Config) -> Names = [lists:concat([cp,N]) || N <- lists:seq(1, N_cps)], Cps = start_and_sync(Names), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), write_high_level_trace(Config), stop_nodes(Cps), - ?line init_condition(Config), + init_condition(Config), ok. start_and_sync([]) -> []; start_and_sync([Name | Names]) -> - ?line {ok, N} = start_node(Name, slave, []), - ?line {Time, _Void} = rpc:call(N, timer, tc, [global, sync, []]), - ?t:format("~p: ~p~n", [Name, Time]), + {ok, N} = start_node(Name, slave, []), + {Time, _Void} = rpc:call(N, timer, tc, [global, sync, []]), + io:format("~p: ~p~n", [Name, Time]), [N | start_and_sync(Names)]. %%%----------------------------------------------------------------- %%% Testing of change of global_groups parameter. %%%----------------------------------------------------------------- -global_groups_change(suite) -> []; -global_groups_change(doc) -> ["Test change of global_groups parameter."]; +%% Test change of global_groups parameter. global_groups_change(Config) -> Timeout = 90, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line M = from($@, atom_to_list(node())), - - % Create the .app files and the boot script - ?line {KernelVer, StdlibVer} = create_script_dc("dc"), - ?line case is_real_system(KernelVer, StdlibVer) of - true -> - Options = []; - false -> - Options = [local] - end, + init_condition(Config), + M = from($@, atom_to_list(node())), + + %% Create the .app files and the boot script + {KernelVer, StdlibVer} = create_script_dc("dc"), + case is_real_system(KernelVer, StdlibVer) of + true -> + Options = []; + false -> + Options = [local] + end, + + ok = systools:make_script("dc", Options), - ?line ok = systools:make_script("dc", Options), - [Ncp1,Ncp2,Ncp3,Ncp4,Ncp5,NcpA,NcpB,NcpC,NcpD,NcpE] = node_names([cp1,cp2,cp3,cp4,cp5,cpA,cpB,cpC,cpD,cpE], Config), - % Write config files - ?line Dir = ?config(priv_dir,Config), - ?line {ok, Fd_dc} = file:open(filename:join(Dir, "sys.config"), [write]), - ?line config_dc1(Fd_dc, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE), - ?line file:close(Fd_dc), - ?line Config1 = filename:join(Dir, "sys"), - - % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_boot(Ncp1, Config1, dc), - ?line {ok, Cp2} = start_node_boot(Ncp2, Config1, dc), - ?line {ok, Cp3} = start_node_boot(Ncp3, Config1, dc), - ?line {ok, CpA} = start_node_boot(NcpA, Config1, dc), - ?line {ok, CpB} = start_node_boot(NcpB, Config1, dc), - ?line {ok, CpC} = start_node_boot(NcpC, Config1, dc), - ?line {ok, CpD} = start_node_boot(NcpD, Config1, dc), - ?line {ok, CpE} = start_node_boot(NcpE, Config1, dc), - - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2]), - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp3]), - ?line pang = rpc:call(Cp1, net_adm, ping, - [list_to_atom(lists:concat(["cp5@", M]))]), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3]), - ?line pang = rpc:call(Cp2, net_adm, ping, - [list_to_atom(lists:concat(["cp5@", M]))]), - - ?line {TestGG4, yes} = rpc:call(CpB, ?MODULE, start_proc, [test]), - ?line {TestGG5, yes} = rpc:call(CpE, ?MODULE, start_proc, [test]), - - - ?line pong = rpc:call(CpA, net_adm, ping, [CpC]), - ?line pong = rpc:call(CpC, net_adm, ping, [CpB]), - ?line pong = rpc:call(CpD, net_adm, ping, [CpC]), - ?line pong = rpc:call(CpE, net_adm, ping, [CpD]), - - ?line + %% Write config files + Dir = proplists:get_value(priv_dir,Config), + {ok, Fd_dc} = file:open(filename:join(Dir, "sys.config"), [write]), + config_dc1(Fd_dc, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE), + file:close(Fd_dc), + Config1 = filename:join(Dir, "sys"), + + %% Test [cp1, cp2, cp3] + {ok, Cp1} = start_node_boot(Ncp1, Config1, dc), + {ok, Cp2} = start_node_boot(Ncp2, Config1, dc), + {ok, Cp3} = start_node_boot(Ncp3, Config1, dc), + {ok, CpA} = start_node_boot(NcpA, Config1, dc), + {ok, CpB} = start_node_boot(NcpB, Config1, dc), + {ok, CpC} = start_node_boot(NcpC, Config1, dc), + {ok, CpD} = start_node_boot(NcpD, Config1, dc), + {ok, CpE} = start_node_boot(NcpE, Config1, dc), + + pong = rpc:call(Cp1, net_adm, ping, [Cp2]), + pong = rpc:call(Cp1, net_adm, ping, [Cp3]), + pang = rpc:call(Cp1, net_adm, ping, + [list_to_atom(lists:concat(["cp5@", M]))]), + pong = rpc:call(Cp2, net_adm, ping, [Cp3]), + pang = rpc:call(Cp2, net_adm, ping, + [list_to_atom(lists:concat(["cp5@", M]))]), + + {TestGG4, yes} = rpc:call(CpB, ?MODULE, start_proc, [test]), + {TestGG5, yes} = rpc:call(CpE, ?MODULE, start_proc, [test]), + + + pong = rpc:call(CpA, net_adm, ping, [CpC]), + pong = rpc:call(CpC, net_adm, ping, [CpB]), + pong = rpc:call(CpD, net_adm, ping, [CpC]), + pong = rpc:call(CpE, net_adm, ping, [CpD]), + ?UNTIL(begin TestGG4_1 = rpc:call(CpA, global, whereis_name, [test]), TestGG4_2 = rpc:call(CpB, global, whereis_name, [test]), @@ -3050,88 +2989,87 @@ global_groups_change(Config) -> (TestGG5_2 =:= TestGG5) end), - ?line ?t:format( "#### nodes() ~p~n",[nodes()]), + io:format( "#### nodes() ~p~n",[nodes()]), - ?line XDcWa1 = rpc:call(Cp1, global_group, info, []), - ?line XDcWa2 = rpc:call(Cp2, global_group, info, []), - ?line XDcWa3 = rpc:call(Cp3, global_group, info, []), - ?line ?t:format( "#### XDcWa1 ~p~n",[XDcWa1]), - ?line ?t:format( "#### XDcWa2 ~p~n",[XDcWa2]), - ?line ?t:format( "#### XDcWa3 ~p~n",[XDcWa3]), + XDcWa1 = rpc:call(Cp1, global_group, info, []), + XDcWa2 = rpc:call(Cp2, global_group, info, []), + XDcWa3 = rpc:call(Cp3, global_group, info, []), + io:format( "#### XDcWa1 ~p~n",[XDcWa1]), + io:format( "#### XDcWa2 ~p~n",[XDcWa2]), + io:format( "#### XDcWa3 ~p~n",[XDcWa3]), + + stop_node(CpC), - ?line stop_node(CpC), - %% Read the current configuration parameters, and change them - ?line OldEnv = + OldEnv = rpc:call(Cp1, application_controller, prep_config_change, []), - ?line {value, {kernel, OldKernel}} = lists:keysearch(kernel, 1, OldEnv), + {value, {kernel, OldKernel}} = lists:keysearch(kernel, 1, OldEnv), - ?line GG1 = + GG1 = lists:sort([mk_node(Ncp1, M), mk_node(Ncp2, M), mk_node(Ncp5, M)]), - ?line GG2 = lists:sort([mk_node(Ncp3, M)]), - ?line GG3 = lists:sort([mk_node(Ncp4, M)]), - ?line GG4 = lists:sort([mk_node(NcpA, M), mk_node(NcpB, M)]), - ?line GG5 = + GG2 = lists:sort([mk_node(Ncp3, M)]), + GG3 = lists:sort([mk_node(Ncp4, M)]), + GG4 = lists:sort([mk_node(NcpA, M), mk_node(NcpB, M)]), + GG5 = lists:sort([mk_node(NcpC, M), mk_node(NcpD, M), mk_node(NcpE, M)]), - ?line NewNG = {global_groups,[{gg1, normal, GG1}, - {gg2, normal, GG2}, - {gg3, normal, GG3}, - {gg4, normal, GG4}, - {gg5, hidden, GG5}]}, - - ?line NewKernel = + NewNG = {global_groups,[{gg1, normal, GG1}, + {gg2, normal, GG2}, + {gg3, normal, GG3}, + {gg4, normal, GG4}, + {gg5, hidden, GG5}]}, + + NewKernel = [{kernel, lists:keyreplace(global_groups, 1, OldKernel, NewNG)}], - ?line ok = rpc:call(Cp1, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - ?line ok = rpc:call(Cp2, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - ?line ok = rpc:call(Cp3, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - ?line ok = rpc:call(CpA, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - ?line ok = rpc:call(CpB, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - ?line ok = rpc:call(CpD, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - ?line ok = rpc:call(CpE, application_controller, test_change_apps, - [[kernel], [NewKernel]]), - - ?line ?t:format("#### ~p~n",[multicall]), - ?line ?t:format( "#### ~p~n",[multicall]), + ok = rpc:call(Cp1, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + ok = rpc:call(Cp2, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + ok = rpc:call(Cp3, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + ok = rpc:call(CpA, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + ok = rpc:call(CpB, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + ok = rpc:call(CpD, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + ok = rpc:call(CpE, application_controller, test_change_apps, + [[kernel], [NewKernel]]), + + io:format("#### ~p~n",[multicall]), + io:format( "#### ~p~n",[multicall]), %% no idea to check the result from the rpc because the other %% nodes will disconnect test server, and thus the result will %% always be {badrpc, nodedown} - ?line rpc:multicall([Cp1, Cp2, Cp3, CpA, CpB, CpD, CpE], - application_controller, config_change, [OldEnv]), + rpc:multicall([Cp1, Cp2, Cp3, CpA, CpB, CpD, CpE], + application_controller, config_change, [OldEnv]), - ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]), - ?line config_dc2(Fd_dc2, NewNG, Ncp1, Ncp2, Ncp3), - ?line file:close(Fd_dc2), - ?line Config2 = filename:join(Dir, "sys2"), - ?line {ok, CpC} = start_node_boot(NcpC, Config2, dc), + {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]), + config_dc2(Fd_dc2, NewNG, Ncp1, Ncp2, Ncp3), + file:close(Fd_dc2), + Config2 = filename:join(Dir, "sys2"), + {ok, CpC} = start_node_boot(NcpC, Config2, dc), - ?line sync_and_wait(CpA), - ?line sync_and_wait(CpD), - - ?line pong = rpc:call(CpA, net_adm, ping, [CpC]), - ?line pong = rpc:call(CpC, net_adm, ping, [CpB]), - ?line pong = rpc:call(CpD, net_adm, ping, [CpC]), - ?line pong = rpc:call(CpE, net_adm, ping, [CpD]), - - ?line GG5 = + sync_and_wait(CpA), + sync_and_wait(CpD), + + pong = rpc:call(CpA, net_adm, ping, [CpC]), + pong = rpc:call(CpC, net_adm, ping, [CpB]), + pong = rpc:call(CpD, net_adm, ping, [CpC]), + pong = rpc:call(CpE, net_adm, ping, [CpD]), + + GG5 = lists:sort([mk_node(NcpC, M)|rpc:call(CpC, erlang, nodes, [])]), - ?line GG5 = + GG5 = lists:sort([mk_node(NcpD, M)|rpc:call(CpD, erlang, nodes, [])]), - ?line GG5 = + GG5 = lists:sort([mk_node(NcpE, M)|rpc:call(CpE, erlang, nodes, [])]), - ?line false = + false = lists:member(mk_node(NcpC, M), rpc:call(CpA, erlang, nodes, [])), - ?line false = + false = lists:member(mk_node(NcpC, M), rpc:call(CpB, erlang, nodes, [])), - ?line ?UNTIL(begin TestGG4a = rpc:call(CpA, global, whereis_name, [test]), TestGG4b = rpc:call(CpB, global, whereis_name, [test]), @@ -3148,171 +3086,171 @@ global_groups_change(Config) -> (TestGG5 =:= TestGG5e) end), - ?line Info1 = rpc:call(Cp1, global_group, info, []), - ?line Info2 = rpc:call(Cp2, global_group, info, []), - ?line Info3 = rpc:call(Cp3, global_group, info, []), - ?line InfoA = rpc:call(CpA, global_group, info, []), - ?line InfoB = rpc:call(CpB, global_group, info, []), - ?line InfoC = rpc:call(CpC, global_group, info, []), - ?line InfoD = rpc:call(CpD, global_group, info, []), - ?line InfoE = rpc:call(CpE, global_group, info, []), - ?line ?t:format( "#### Info1 ~p~n",[Info1]), - ?line ?t:format( "#### Info2 ~p~n",[Info2]), - ?line ?t:format( "#### Info3 ~p~n",[Info3]), - ?line ?t:format( "#### InfoA ~p~n",[InfoA]), - ?line ?t:format( "#### InfoB ~p~n",[InfoB]), - ?line ?t:format( "#### InfoC ~p~n",[InfoC]), - ?line ?t:format( "#### InfoD ~p~n",[InfoD]), - ?line ?t:format( "#### InfoE ~p~n",[InfoE]), - - ?line {global_groups, GGNodes} = NewNG, - - ?line Info1ok = [{state, synced}, - {own_group_name, gg1}, - {own_group_nodes, GG1}, - {synced_nodes, [mk_node(Ncp2, M)]}, - {sync_error, []}, - {no_contact, [mk_node(Ncp5, M)]}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg1, 1, GGNodes))}, - {monitoring, []}], - - - ?line Info2ok = [{state, synced}, - {own_group_name, gg1}, - {own_group_nodes, GG1}, - {synced_nodes, [mk_node(Ncp1, M)]}, - {sync_error, []}, - {no_contact, [mk_node(Ncp5, M)]}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg1, 1, GGNodes))}, - {monitoring, []}], - - ?line Info3ok = [{state, synced}, - {own_group_name, gg2}, - {own_group_nodes, GG2}, - {synced_nodes, []}, - {sync_error, []}, - {no_contact, []}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg2, 1, GGNodes))}, - {monitoring, []}], - - ?line InfoAok = [{state, synced}, - {own_group_name, gg4}, - {own_group_nodes, GG4}, - {synced_nodes, lists:delete(mk_node(NcpA, M), GG4)}, - {sync_error, []}, - {no_contact, []}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg4, 1, GGNodes))}, - {monitoring, []}], - - ?line InfoBok = [{state, synced}, - {own_group_name, gg4}, - {own_group_nodes, GG4}, - {synced_nodes, lists:delete(mk_node(NcpB, M), GG4)}, - {sync_error, []}, - {no_contact, []}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg4, 1, GGNodes))}, - {monitoring, []}], - - ?line InfoCok = [{state, synced}, - {own_group_name, gg5}, - {own_group_nodes, GG5}, - {synced_nodes, lists:delete(mk_node(NcpC, M), GG5)}, - {sync_error, []}, - {no_contact, []}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg5, 1, GGNodes))}, - {monitoring, []}], - - ?line InfoDok = [{state, synced}, - {own_group_name, gg5}, - {own_group_nodes, GG5}, - {synced_nodes, lists:delete(mk_node(NcpD, M), GG5)}, - {sync_error, []}, - {no_contact, []}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg5, 1, GGNodes))}, - {monitoring, []}], - - ?line InfoEok = [{state, synced}, - {own_group_name, gg5}, - {own_group_nodes, GG5}, - {synced_nodes, lists:delete(mk_node(NcpE, M), GG5)}, - {sync_error, []}, - {no_contact, []}, - {other_groups, remove_gg_pub_type(lists:keydelete - (gg5, 1, GGNodes))}, - {monitoring, []}], - - - ?line case Info1 of - Info1ok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", Cp1}, {Info1, Info1ok}}) - end, + Info1 = rpc:call(Cp1, global_group, info, []), + Info2 = rpc:call(Cp2, global_group, info, []), + Info3 = rpc:call(Cp3, global_group, info, []), + InfoA = rpc:call(CpA, global_group, info, []), + InfoB = rpc:call(CpB, global_group, info, []), + InfoC = rpc:call(CpC, global_group, info, []), + InfoD = rpc:call(CpD, global_group, info, []), + InfoE = rpc:call(CpE, global_group, info, []), + io:format( "#### Info1 ~p~n",[Info1]), + io:format( "#### Info2 ~p~n",[Info2]), + io:format( "#### Info3 ~p~n",[Info3]), + io:format( "#### InfoA ~p~n",[InfoA]), + io:format( "#### InfoB ~p~n",[InfoB]), + io:format( "#### InfoC ~p~n",[InfoC]), + io:format( "#### InfoD ~p~n",[InfoD]), + io:format( "#### InfoE ~p~n",[InfoE]), + + {global_groups, GGNodes} = NewNG, + + Info1ok = [{state, synced}, + {own_group_name, gg1}, + {own_group_nodes, GG1}, + {synced_nodes, [mk_node(Ncp2, M)]}, + {sync_error, []}, + {no_contact, [mk_node(Ncp5, M)]}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg1, 1, GGNodes))}, + {monitoring, []}], + + + Info2ok = [{state, synced}, + {own_group_name, gg1}, + {own_group_nodes, GG1}, + {synced_nodes, [mk_node(Ncp1, M)]}, + {sync_error, []}, + {no_contact, [mk_node(Ncp5, M)]}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg1, 1, GGNodes))}, + {monitoring, []}], + + Info3ok = [{state, synced}, + {own_group_name, gg2}, + {own_group_nodes, GG2}, + {synced_nodes, []}, + {sync_error, []}, + {no_contact, []}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg2, 1, GGNodes))}, + {monitoring, []}], + + InfoAok = [{state, synced}, + {own_group_name, gg4}, + {own_group_nodes, GG4}, + {synced_nodes, lists:delete(mk_node(NcpA, M), GG4)}, + {sync_error, []}, + {no_contact, []}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg4, 1, GGNodes))}, + {monitoring, []}], + + InfoBok = [{state, synced}, + {own_group_name, gg4}, + {own_group_nodes, GG4}, + {synced_nodes, lists:delete(mk_node(NcpB, M), GG4)}, + {sync_error, []}, + {no_contact, []}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg4, 1, GGNodes))}, + {monitoring, []}], + + InfoCok = [{state, synced}, + {own_group_name, gg5}, + {own_group_nodes, GG5}, + {synced_nodes, lists:delete(mk_node(NcpC, M), GG5)}, + {sync_error, []}, + {no_contact, []}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg5, 1, GGNodes))}, + {monitoring, []}], + + InfoDok = [{state, synced}, + {own_group_name, gg5}, + {own_group_nodes, GG5}, + {synced_nodes, lists:delete(mk_node(NcpD, M), GG5)}, + {sync_error, []}, + {no_contact, []}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg5, 1, GGNodes))}, + {monitoring, []}], + + InfoEok = [{state, synced}, + {own_group_name, gg5}, + {own_group_nodes, GG5}, + {synced_nodes, lists:delete(mk_node(NcpE, M), GG5)}, + {sync_error, []}, + {no_contact, []}, + {other_groups, remove_gg_pub_type(lists:keydelete + (gg5, 1, GGNodes))}, + {monitoring, []}], + + + case Info1 of + Info1ok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", Cp1}, {Info1, Info1ok}}) + end, - ?line case Info2 of - Info2ok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", Cp2}, {Info2, Info2ok}}) - end, + case Info2 of + Info2ok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", Cp2}, {Info2, Info2ok}}) + end, - ?line case Info3 of - Info3ok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", Cp3}, {Info3, Info3ok}}) - end, + case Info3 of + Info3ok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", Cp3}, {Info3, Info3ok}}) + end, - ?line case InfoA of - InfoAok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", CpA}, {InfoA, InfoAok}}) - end, + case InfoA of + InfoAok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", CpA}, {InfoA, InfoAok}}) + end, - ?line case InfoB of - InfoBok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", CpB}, {InfoB, InfoBok}}) - end, + case InfoB of + InfoBok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", CpB}, {InfoB, InfoBok}}) + end, - ?line case InfoC of - InfoCok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", CpC}, {InfoC, InfoCok}}) - end, + case InfoC of + InfoCok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", CpC}, {InfoC, InfoCok}}) + end, - ?line case InfoD of - InfoDok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", CpD}, {InfoD, InfoDok}}) - end, + case InfoD of + InfoDok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", CpD}, {InfoD, InfoDok}}) + end, - ?line case InfoE of - InfoEok -> - ok; - _ -> - test_server:fail({{"could not change the global groups" - " in node", CpE}, {InfoE, InfoEok}}) - end, + case InfoE of + InfoEok -> + ok; + _ -> + ct:fail({{"could not change the global groups" + " in node", CpE}, {InfoE, InfoEok}}) + end, write_high_level_trace(Config), % no good since CpC was restarted stop_node(Cp1), @@ -3324,7 +3262,7 @@ global_groups_change(Config) -> stop_node(CpD), stop_node(CpE), - ?line init_condition(Config), + init_condition(Config), ok. sync_and_wait(Node) -> @@ -3354,43 +3292,43 @@ sync_and_wait(Node) -> is_real_system(KernelVsn, StdlibVsn) -> LibDir = code:lib_dir(), filelib:is_dir(filename:join(LibDir, "kernel-" ++ KernelVsn)) - andalso - filelib:is_dir(filename:join(LibDir, "stdlib-" ++ StdlibVsn)). + andalso + filelib:is_dir(filename:join(LibDir, "stdlib-" ++ StdlibVsn)). create_script_dc(ScriptName) -> - ?line Name = filename:join(".", ScriptName), - ?line Apps = application_controller:which_applications(), - ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), - ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), - ?line {ok,Fd} = file:open(Name ++ ".rel", [write]), - ?line {_, Version} = init:script_id(), - ?line io:format(Fd, - "{release, {\"Test release 3\", \"~s\"}, \n" - " {erts, \"4.4\"}, \n" - " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n", - [Version, KernelVer, StdlibVer]), - ?line file:close(Fd), + Name = filename:join(".", ScriptName), + Apps = application_controller:which_applications(), + {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), + {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), + {ok,Fd} = file:open(Name ++ ".rel", [write]), + {_, Version} = init:script_id(), + io:format(Fd, + "{release, {\"Test release 3\", \"~s\"}, \n" + " {erts, \"4.4\"}, \n" + " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n", + [Version, KernelVer, StdlibVer]), + file:close(Fd), {KernelVer, StdlibVer}. %% Not used? config_dc(Fd, Ncp1, Ncp2, Ncp3) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000}," - "{global_groups, [{gg1, ['~s@~s', '~s@~s']}," - " {gg2, ['~s@~s']}]}" - " ]}].~n", + "{sync_nodes_timeout, 1000}," + "{global_groups, [{gg1, ['~s@~s', '~s@~s']}," + " {gg2, ['~s@~s']}]}" + " ]}].~n", [Ncp1, M, Ncp2, M, Ncp3, M, Ncp1, M, Ncp2, M, Ncp3, M]). config_dc1(Fd, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s','~s@~s','~s@~s','~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000}," - "{global_groups, [{gg1, ['~s@~s', '~s@~s']}," - " {gg2, ['~s@~s']}," - " {gg4, normal, ['~s@~s','~s@~s','~s@~s']}," - " {gg5, hidden, ['~s@~s','~s@~s']}]}]}].~n", + "{sync_nodes_timeout, 1000}," + "{global_groups, [{gg1, ['~s@~s', '~s@~s']}," + " {gg2, ['~s@~s']}," + " {gg4, normal, ['~s@~s','~s@~s','~s@~s']}," + " {gg5, hidden, ['~s@~s','~s@~s']}]}]}].~n", [Ncp1, M, Ncp2, M, Ncp3, M, NcpA, M, NcpB, M, NcpC, M, NcpD, M, NcpE, M, Ncp1, M, Ncp2, M, @@ -3401,8 +3339,8 @@ config_dc1(Fd, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE) -> config_dc2(Fd, NewGG, Ncp1, Ncp2, Ncp3) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000}," - "~p]}].~n", + "{sync_nodes_timeout, 1000}," + "~p]}].~n", [Ncp1, M, Ncp2, M, Ncp3, M, NewGG]). @@ -3414,33 +3352,33 @@ from(_H, []) -> []. other(A, [A, _B]) -> A; other(_, [_A, B]) -> B. - + %% this one runs at cp2 part1(Config, Main, Cp1, Cp3) -> case catch begin make_partition(Config, [Main, Cp1], [node(), Cp3]), - ?line {_Pid, yes} = start_proc(test2), - ?line {_Pid2, yes} = start_proc(test4) + {_Pid, yes} = start_proc(test2), + {_Pid2, yes} = start_proc(test4) end of {_, yes} -> ok; % w("ok", []); {'EXIT', _R} -> ok - % w("global_SUITE line:~w: ~p", [?LINE, _R]) + %% w("global_SUITE line:~w: ~p", [?LINE, _R]) end. %% Runs at Cp2 part1_5(Config, Main, Cp1, Cp3) -> case catch begin make_partition(Config, [Main, Cp1], [node(), Cp3]), - ?line {_Pid1, yes} = start_proc_basic(name12), - ?line {_Pid2, yes} = + {_Pid1, yes} = start_proc_basic(name12), + {_Pid2, yes} = rpc:call(Cp3, ?MODULE, start_proc_basic, [name03]) end of {_, yes} -> ok; % w("ok", []); {'EXIT', _R} -> ok - % w("global_SUITE line:~w: ~p", [?LINE, _R]) + %% w("global_SUITE line:~w: ~p", [?LINE, _R]) end. w(X,Y) -> @@ -3451,7 +3389,7 @@ w(X,Y) -> %% this one runs on one node in Part2 %% The partition is ready when is_ready_partition(Config) returns (true). make_partition(Config, Part1, Part2) -> - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), Ns = [begin Name = lists:concat([atom_to_list(N),"_",msec(),".part"]), File = filename:join([Dir, Name]), @@ -3503,7 +3441,7 @@ is_ready_partition(Config) -> true. make_partition_file(Config) -> - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), filename:join([Dir, atom_to_list(make_partition_done)]). %% this one runs at cp3 @@ -3514,37 +3452,36 @@ part2(Config, Parent, Main, Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6) -> part3(Config, Parent, Main, Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6) -> make_partition(Config, [Main, Cp0, Cp1, Cp2], [Cp3, Cp4, Cp5, Cp6]), start_procs(Parent, Cp4, Cp5, Cp6, Config), - % Make Cp6 alone - ?line rpc_cast(Cp5, ?MODULE, crash, [12000]), - ?line rpc_cast(Cp6, ?MODULE, alone, [Cp0, Cp3]). + %% Make Cp6 alone + rpc_cast(Cp5, ?MODULE, crash, [12000]), + rpc_cast(Cp6, ?MODULE, alone, [Cp0, Cp3]). start_procs(Parent, N1, N2, N3, Config) -> S1 = lists:sort([N1, N2, N3]), - ?line ?UNTIL(begin NN = lists:sort(nodes()), S1 =:= NN end), - ?line Pid3 = start_proc3(test1), - ?line Pid4 = rpc:call(N1, ?MODULE, start_proc3, [test2]), - ?line assert_pid(Pid4), - ?line Pid5 = rpc:call(N2, ?MODULE, start_proc3, [test3]), - ?line assert_pid(Pid5), - ?line Pid6 = rpc:call(N3, ?MODULE, start_proc3, [test4]), - ?line assert_pid(Pid6), - ?line yes = global:register_name(test1, Pid3), - ?line yes = global:register_name(test2, Pid4, {global, notify_all_name}), - ?line yes = global:register_name(test3, Pid5, {global, random_notify_name}), + Pid3 = start_proc3(test1), + Pid4 = rpc:call(N1, ?MODULE, start_proc3, [test2]), + assert_pid(Pid4), + Pid5 = rpc:call(N2, ?MODULE, start_proc3, [test3]), + assert_pid(Pid5), + Pid6 = rpc:call(N3, ?MODULE, start_proc3, [test4]), + assert_pid(Pid6), + yes = global:register_name(test1, Pid3), + yes = global:register_name(test2, Pid4, fun global:notify_all_name/3), + yes = global:register_name(test3, Pid5, fun global:random_notify_name/3), Resolve = fun(Name, Pid1, Pid2) -> Parent ! {resolve_called, Name, node()}, {Min, Max} = minmax(Pid1, Pid2), exit(Min, kill), Max end, - ?line yes = global:register_name(test4, Pid6, Resolve). + yes = global:register_name(test4, Pid6, Resolve). + - collect_resolves() -> cr(0). cr(Res) -> receive @@ -3574,7 +3511,7 @@ start_proc() -> receive Pid -> Pid end. - + start_proc(Name) -> Pid = spawn(?MODULE, p_init, [self(), Name]), @@ -3609,7 +3546,7 @@ start_proc_basic(Name) -> end. init_proc_basic(Parent, Name) -> - X = global:register_name(Name, self(), {?MODULE, fix_basic_name}), + X = global:register_name(Name, self(), fun ?MODULE:fix_basic_name/3), Parent ! {self(),X}, loop(). @@ -3618,7 +3555,7 @@ single_node(Time, Node, Config) -> lists:foreach(fun(N) -> _ = erlang:disconnect_node(N) end, nodes()), ?UNTIL(get_known(node()) =:= [node()]), spawn(?MODULE, init_2, []), - test_server:sleep(Time - msec()), + ct:sleep(Time - msec()), net_adm:ping(Node). init_2() -> @@ -3630,12 +3567,12 @@ loop_2() -> receive die -> ok end. - + msec() -> msec(now()). msec(T) -> - element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000. + element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000. assert_pid(Pid) -> if @@ -3680,13 +3617,15 @@ sreq(Pid, Msg) -> alone(N1, N2) -> lists:foreach(fun(Node) -> true = erlang:disconnect_node(Node) end, nodes()), - test_server:sleep(12000), + ct:sleep(12000), net_adm:ping(N1), net_adm:ping(N2), yes = global:register_name(test5, self()). crash(Time) -> - test_server:sleep(Time), + %% ct:sleep/1 will not work because it calls a server process + %% that does not run on other nodes. + timer:sleep(Time), erlang:halt(). loop() -> @@ -3748,23 +3687,23 @@ pr_diff(Str, T0, T1) -> {_, {H,M,S}} = calendar:time_difference(T0, T1), ((H*60+M)*60)+S end, - test_server:format(1,"~13s: ~w (diff: ~w)",[Str, T1, Diff]), + ct:pal(?HI_VERBOSITY,"~13s: ~w (diff: ~w)",[Str, T1, Diff]), if Diff > 100 -> - test_server:format(1,"~s: ** LARGE DIFF ~w~n", [Str, Diff]); + io:format(1,"~s: ** LARGE DIFF ~w~n", [Str, Diff]); true -> ok end. -endif. now_diff({A1,B1,C1},{A2,B2,C2}) -> - C1-C2 + 1000000*((B1-B2) + 1000000*(A1-A2)). + C1-C2 + 1000000*((B1-B2) + 1000000*(A1-A2)). start_node_boot(Name, Config, Boot) -> Pa = filename:dirname(code:which(?MODULE)), Res = test_server:start_node(Name, peer, [{args, " -pa " ++ Pa ++ - " -config " ++ Config ++ - " -boot " ++ atom_to_list(Boot)}]), + " -config " ++ Config ++ + " -boot " ++ atom_to_list(Boot)}]), record_started_node(Res). %% Increase the timeout for when an upcoming connection is teared down @@ -3790,13 +3729,13 @@ start_node(Name0, How, Args, Config) -> Pa = filename:dirname(code:which(?MODULE)), R = test_server:start_node(Name, How, [{args, Args ++ " " ++ - "-kernel net_setuptime 100 " -% "-noshell " + "-kernel net_setuptime 100 " + %% "-noshell " "-pa " ++ Pa}, {linked, false} -]), + ]), %% {linked,false} only seems to work for slave nodes. -% test_server:sleep(1000), + %% ct:sleep(1000), record_started_node(R). start_node_rel(Name0, Rel, Config) -> @@ -3807,14 +3746,14 @@ start_node_rel(Name0, Rel, Config) -> Rel when is_atom(Rel) -> {[{release, atom_to_list(Rel)}], ""}; RelList -> - {RelList, ""} - end, + {RelList, ""} + end, Env = [], Pa = filename:dirname(code:which(?MODULE)), Res = test_server:start_node(Name, peer, [{args, Compat ++ - " -kernel net_setuptime 100 " + " -kernel net_setuptime 100 " " -pa " ++ Pa}, {erl, Release}] ++ Env), record_started_node(Res). @@ -3844,57 +3783,45 @@ stop_nodes(Nodes) -> lists:foreach(fun(Node) -> stop_node(Node) end, Nodes). stop_node(Node) -> - ?line ?t:stop_node(Node). + test_server:stop_node(Node). stop() -> lists:foreach(fun(Node) -> - ?t:stop_node(Node) + test_server:stop_node(Node) end, nodes()). -dbg_logs(Name) -> dbg_logs(Name, ?NODES). - -dbg_logs(Name, Nodes) -> - lists:foreach(fun(N) -> - F = lists:concat([Name, ".log.", N, ".txt"]), - ?line ok = sys:log_to_file({global_name_server, N}, F) - end, Nodes). - - -global_lost_nodes(suite) -> - []; -global_lost_nodes(doc) -> - ["Tests that locally loaded nodes do not loose contact with other nodes."]; +%% Tests that locally loaded nodes do not loose contact with other nodes. global_lost_nodes(Config) when is_list(Config) -> Timeout = 60, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - - ?line {ok, Node1} = start_node(node1, Config), - ?line {ok, Node2} = start_node(node2, Config), + init_condition(Config), + + {ok, Node1} = start_node(node1, Config), + {ok, Node2} = start_node(node2, Config), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - ?line io:format("Nodes: ~p", [nodes()]), - ?line io:format("Nodes at node1: ~p", - [rpc:call(Node1, erlang, nodes, [])]), - ?line io:format("Nodes at node2: ~p", - [rpc:call(Node2, erlang, nodes, [])]), + io:format("Nodes: ~p", [nodes()]), + io:format("Nodes at node1: ~p", + [rpc:call(Node1, erlang, nodes, [])]), + io:format("Nodes at node2: ~p", + [rpc:call(Node2, erlang, nodes, [])]), - ?line rpc_cast(Node1, ?MODULE, global_load, [node_1,Node2,node_2]), - ?line rpc_cast(Node2, ?MODULE, global_load, [node_2,Node1,node_1]), + rpc_cast(Node1, ?MODULE, global_load, [node_1,Node2,node_2]), + rpc_cast(Node2, ?MODULE, global_load, [node_2,Node1,node_1]), lost_nodes_waiter(Node1, Node2), write_high_level_trace(Config), - ?line stop_node(Node1), - ?line stop_node(Node2), - ?line init_condition(Config), + stop_node(Node1), + stop_node(Node2), + init_condition(Config), ok. global_load(MyName, OtherNode, OtherName) -> - ?line yes = global:register_name(MyName, self()), + yes = global:register_name(MyName, self()), io:format("Registered ~p",[MyName]), global_load1(OtherNode, OtherName, 0). @@ -3902,32 +3829,32 @@ global_load1(_OtherNode, _OtherName, 2) -> io:format("*** ~p giving up. No use.", [node()]), init:stop(); global_load1(OtherNode, OtherName, Fails) -> - test_server:sleep(1000), - ?line case catch global:whereis_name(OtherName) of - Pid when is_pid(Pid) -> - io:format("~p says: ~p is still there.", - [node(),OtherName]), - global_load1(OtherNode, OtherName, Fails); - Other -> - io:format("~p says: ~p is lost (~p) Pinging.", - [ node(), OtherName, Other]), - case net_adm:ping(OtherNode) of - pong -> - io:format("Re-established contact to ~p", - [OtherName]); - pang -> - io:format("PANIC! Other node is DEAD.", []), - init:stop() - end, - global_load1(OtherNode, OtherName, Fails+1) - end. + ct:sleep(1000), + case catch global:whereis_name(OtherName) of + Pid when is_pid(Pid) -> + io:format("~p says: ~p is still there.", + [node(),OtherName]), + global_load1(OtherNode, OtherName, Fails); + Other -> + io:format("~p says: ~p is lost (~p) Pinging.", + [ node(), OtherName, Other]), + case net_adm:ping(OtherNode) of + pong -> + io:format("Re-established contact to ~p", + [OtherName]); + pang -> + io:format("PANIC! Other node is DEAD.", []), + init:stop() + end, + global_load1(OtherNode, OtherName, Fails+1) + end. lost_nodes_waiter(N1, N2) -> - ?line net_kernel:monitor_nodes(true), + net_kernel:monitor_nodes(true), receive {nodedown, Node} when Node =:= N1 ; Node =:= N2 -> io:format("~p went down!",[Node]), - ?line ?t:fail("Node went down.") + ct:fail("Node went down.") after 10000 -> ok end, @@ -3935,36 +3862,33 @@ lost_nodes_waiter(N1, N2) -> -mass_death(suite) -> - []; -mass_death(doc) -> - ["Tests the simultaneous death of many processes with registered names"]; +%% Tests the simultaneous death of many processes with registered names. mass_death(Config) when is_list(Config) -> Timeout = 90, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line OrigNames = global:registered_names(), + init_condition(Config), + OrigNames = global:registered_names(), %% Start nodes - ?line Cps = [cp1,cp2,cp3,cp4,cp5], - ?line Nodes = [begin {ok, Node} = start_node(Cp, Config), Node end || - Cp <- Cps], - ?line io:format("Nodes: ~p~n", [Nodes]), - ?line Ns = lists:seq(1, 40), + Cps = [cp1,cp2,cp3,cp4,cp5], + Nodes = [begin {ok, Node} = start_node(Cp, Config), Node end || + Cp <- Cps], + io:format("Nodes: ~p~n", [Nodes]), + Ns = lists:seq(1, 40), %% Start processes with globally registered names on the nodes - ?line {Pids,[]} = rpc:multicall(Nodes, ?MODULE, mass_spawn, [Ns]), - ?line io:format("Pids: ~p~n", [Pids]), + {Pids,[]} = rpc:multicall(Nodes, ?MODULE, mass_spawn, [Ns]), + io:format("Pids: ~p~n", [Pids]), %% Wait... - ?line test_server:sleep(10000), + ct:sleep(10000), %% Check the globally registered names - ?line NewNames = global:registered_names(), - ?line io:format("NewNames: ~p~n", [NewNames]), - ?line Ndiff = lists:sort(NewNames--OrigNames), - ?line io:format("Ndiff: ~p~n", [Ndiff]), - ?line Ndiff = lists:sort(mass_names(Nodes, Ns)), + NewNames = global:registered_names(), + io:format("NewNames: ~p~n", [NewNames]), + Ndiff = lists:sort(NewNames--OrigNames), + io:format("Ndiff: ~p~n", [Ndiff]), + Ndiff = lists:sort(mass_names(Nodes, Ns)), %% %% Kill the root pids - ?line lists:foreach(fun (Pid) -> Pid ! drop_dead end, Pids), + lists:foreach(fun (Pid) -> Pid ! drop_dead end, Pids), %% Start probing and wait for all registered names to disappear {YYYY,MM,DD} = date(), {H,M,S} = time(), @@ -3973,22 +3897,21 @@ mass_death(Config) when is_list(Config) -> wait_mass_death(Nodes, OrigNames, erlang:now(), Config). wait_mass_death(Nodes, OrigNames, Then, Config) -> - ?line Names = global:registered_names(), - ?line - case Names--OrigNames of - [] -> - ?line T = now_diff(erlang:now(), Then) div 1000, - ?line lists:foreach( - fun (Node) -> - stop_node(Node) - end, Nodes), - ?line init_condition(Config), - {comment,lists:flatten(io_lib:format("~.3f s~n", [T/1000.0]))}; - Ndiff -> - ?line io:format("Ndiff: ~p~n", [Ndiff]), - ?line test_server:sleep(1000), - ?line wait_mass_death(Nodes, OrigNames, Then, Config) - end. + Names = global:registered_names(), + case Names--OrigNames of + [] -> + T = now_diff(erlang:now(), Then) div 1000, + lists:foreach( + fun (Node) -> + stop_node(Node) + end, Nodes), + init_condition(Config), + {comment,lists:flatten(io_lib:format("~.3f s~n", [T/1000.0]))}; + Ndiff -> + io:format("Ndiff: ~p~n", [Ndiff]), + ct:sleep(1000), + wait_mass_death(Nodes, OrigNames, Then, Config) + end. mass_spawn([]) -> ok; @@ -4018,7 +3941,7 @@ mass_name(Node, N) -> start_nodes(L, How, Config) -> start_nodes2(L, How, 0, Config), Nodes = collect_nodes(0, length(L)), - ?line ?UNTIL([] =:= Nodes -- nodes()), + ?UNTIL([] =:= Nodes -- nodes()), put(?nodes_tag, Nodes), %% Pinging doesn't help, we have to wait too, for nodes() to become %% correct on the other node. @@ -4042,7 +3965,7 @@ verify_nodes(Nodes, Config) -> verify_nodes([], _N, _Config) -> []; verify_nodes([Node | Rest], N, Config) -> - ?line ?UNTIL( + ?UNTIL( case rpc:call(Node, erlang, nodes, []) of Nodes when is_list(Nodes) -> case N =:= lists:sort([Node | Nodes]) of @@ -4074,7 +3997,7 @@ start_nodes2([Name | Rest], How, N, Config) -> Self ! {N, R}, %% sleeping is necessary, or with peer nodes, they will %% go down again, despite {linked, false}. - test_server:sleep(100000) + ct:sleep(100000) end), start_nodes2(Rest, How, N+1, Config). @@ -4155,14 +4078,12 @@ remove_gg_pub_type([{GG, _, Nodes}|Rest]) -> %% Better do this in a slave node. %% (The transition from links to monitors does not affect this case.) -garbage_messages(suite) -> - []; garbage_messages(Config) when is_list(Config) -> Timeout = 25, ct:timetrap({seconds,Timeout}), init_high_level_trace(Timeout), - ?line init_condition(Config), - ?line [Slave] = start_nodes([garbage_messages], slave, Config), + init_condition(Config), + [Slave] = start_nodes([garbage_messages], slave, Config), Fun = fun() -> {links,L} = process_info(whereis(global_name_server), links), lists:foreach(fun(Pid) -> Pid ! {garbage,to,you} end, L), @@ -4170,15 +4091,15 @@ garbage_messages(Config) when is_list(Config) -> _Any -> ok end end, - ?line Pid = spawn_link(Slave, erlang, apply, [Fun,[]]), - ?t:sleep(2000), - ?line Global = rpc:call(Slave, erlang, whereis, [global_name_server]), - ?line {registered_name,global_name_server} = + Pid = spawn_link(Slave, erlang, apply, [Fun,[]]), + ct:sleep(2000), + Global = rpc:call(Slave, erlang, whereis, [global_name_server]), + {registered_name,global_name_server} = rpc:call(Slave, erlang, process_info, [Global,registered_name]), - ?line true = unlink(Pid), + true = unlink(Pid), write_high_level_trace(Config), - ?line stop_node(Slave), - ?line init_condition(Config), + stop_node(Slave), + init_condition(Config), ok. wait_for_ready_net(Config) -> @@ -4186,13 +4107,13 @@ wait_for_ready_net(Config) -> wait_for_ready_net(Nodes0, Config) -> Nodes = lists:sort(Nodes0), - ?t:format("wait_for_ready_net ~p~n", [Nodes]), + io:format("wait_for_ready_net ~p~n", [Nodes]), ?UNTIL(begin lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and - lists:all(fun(N) -> - LNs = rpc:call(N, erlang, nodes, []), - Nodes =:= lists:sort([N | LNs]) - end, Nodes) + lists:all(fun(N) -> + LNs = rpc:call(N, erlang, nodes, []), + Nodes =:= lists:sort([N | LNs]) + end, Nodes) end). get_known(Node) -> @@ -4207,7 +4128,7 @@ quite_a_few_nodes(Max) -> N = try ulimit("ulimit -u") catch _:_ -> - ulimit("ulimit -p") % can fail... + ulimit("ulimit -p") % can fail... end, lists:min([(N - 40) div 3, Max]). @@ -4264,15 +4185,15 @@ start_tracer() -> Pid = spawn(fun() -> tracer([]) end), case catch register(my_tracer, Pid) of {'EXIT', _} -> - ?t:fail(re_register_my_tracer); + ct:fail(re_register_my_tracer); _ -> ok end. tracer(L) -> receive - % {save, Term} -> - % tracer([{now(),Term} | L]); + %% {save, Term} -> + %% tracer([{now(),Term} | L]); {get, From} -> From ! {trace, lists:reverse(L)}, tracer([]); @@ -4305,7 +4226,7 @@ collect_tracers(Nodes) -> trace_message(M) -> case catch my_tracer ! M of {'EXIT', _} -> - ?t:fail(my_tracer_not_registered); + ct:fail(my_tracer_not_registered); _ -> ok end. diff --git a/lib/kernel/test/global_SUITE_data/global_trace.erl b/lib/kernel/test/global_SUITE_data/global_trace.erl index 69d95f610d..b4af4ed76e 100644 --- a/lib/kernel/test/global_SUITE_data/global_trace.erl +++ b/lib/kernel/test/global_SUITE_data/global_trace.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2016. 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/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl index 0a994c3bf0..594ee6b537 100644 --- a/lib/kernel/test/global_group_SUITE.erl +++ b/lib/kernel/test/global_group_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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,15 +28,17 @@ -export([init_per_testcase/2, end_per_testcase/2]). -%-compile(export_all). +%%-compile(export_all). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(NODES, [node()|nodes()]). -define(UNTIL(Seq), loop_until_true(fun() -> Seq end)). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,5}}]. all() -> [start_gg_proc, no_gg_proc, no_gg_proc_sync, compatible, @@ -46,10 +48,10 @@ groups() -> []. init_per_group(_GroupName, Config) -> - Config. + Config. end_per_group(_GroupName, Config) -> - Config. + Config. init_per_suite(Config) -> @@ -77,15 +79,13 @@ end_per_suite(_Config) -> ok. -define(TESTCASE, testcase_name). --define(testcase, ?config(?TESTCASE, Config)). +-define(testcase, proplists:get_value(?TESTCASE, Config)). -init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog=?t:timetrap(?t:minutes(5)), - [{?TESTCASE, Case}, {watchdog, Dog}|Config]. +init_per_testcase(Case, Config) -> + Config. -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. %%----------------------------------------------------------------- %% Test suites for global groups. @@ -94,198 +94,191 @@ end_per_testcase(_Func, Config) -> %%----------------------------------------------------------------- -start_gg_proc(suite) -> []; -start_gg_proc(doc) -> ["Check that the global_group processes are started automatically. "]; +%% Check that the global_group processes are started automatically. . start_gg_proc(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(120)), - - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd}=file:open(File, [write]), + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "global_group.config"), + {ok, Fd}=file:open(File, [write]), [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), - ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), + config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), - ?line Cp1nn = node_at(Ncp1), - ?line Cp2nn = node_at(Ncp2), - ?line Cp3nn = node_at(Ncp3), + Cp1nn = node_at(Ncp1), + Cp2nn = node_at(Ncp2), + Cp3nn = node_at(Ncp3), - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line {ok, Cp2} = start_node(Ncp2, Config), - ?line {ok, Cp3} = start_node(Ncp3, Config), + {ok, Cp1} = start_node(Ncp1, Config), + {ok, Cp2} = start_node(Ncp2, Config), + {ok, Cp3} = start_node(Ncp3, Config), - ?line [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), - ?line [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), - ?line [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), - % stop the nodes, and make sure names are released. + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line test_server:timetrap_cancel(Dog), + ?UNTIL(undefined =:= global:whereis_name(test)), ok. - -no_gg_proc(suite) -> []; -no_gg_proc(doc) -> ["Start a system without global groups. Nodes are not " - "synced at start (sync_nodes_optional is not defined)"]; + +%% Start a system without global groups. Nodes are not +%% synced at start (sync_nodes_optional is not defined). no_gg_proc(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(200)), - - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "no_global_group.config"), - ?line {ok, Fd} = file:open(File, [write]), - ?line config_no(Fd), - - ?line NN = node_name(atom_to_list(node())), - ?line Cp1nn = list_to_atom("cp1@" ++ NN), - ?line Cp2nn = list_to_atom("cp2@" ++ NN), - ?line Cp3nn = list_to_atom("cp3@" ++ NN), - ?line Cpxnn = list_to_atom("cpx@" ++ NN), - ?line Cpynn = list_to_atom("cpy@" ++ NN), - ?line Cpznn = list_to_atom("cpz@" ++ NN), - - ?line {ok, Cp1} = start_node_no(cp1, Config), - ?line {ok, Cp2} = start_node_no(cp2, Config), - ?line {ok, Cp3} = start_node_no(cp3, Config), - ?line {ok, Cpx} = start_node_no(cpx, Config), - ?line {ok, Cpy} = start_node_no(cpy, Config), - ?line {ok, Cpz} = start_node_no(cpz, Config), + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "no_global_group.config"), + {ok, Fd} = file:open(File, [write]), + config_no(Fd), + + NN = node_name(atom_to_list(node())), + Cp1nn = list_to_atom("cp1@" ++ NN), + Cp2nn = list_to_atom("cp2@" ++ NN), + Cp3nn = list_to_atom("cp3@" ++ NN), + Cpxnn = list_to_atom("cpx@" ++ NN), + Cpynn = list_to_atom("cpy@" ++ NN), + Cpznn = list_to_atom("cpz@" ++ NN), + + {ok, Cp1} = start_node_no(cp1, Config), + {ok, Cp2} = start_node_no(cp2, Config), + {ok, Cp3} = start_node_no(cp3, Config), + {ok, Cpx} = start_node_no(cpx, Config), + {ok, Cpy} = start_node_no(cpy, Config), + {ok, Cpz} = start_node_no(cpz, Config), %% let the nodes know of each other - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), - ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), - ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), + pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), + pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), + pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), + pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), + pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), - ?line wait_for_ready_net(), + wait_for_ready_net(), - ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), - ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), - ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), - ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), - ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), - ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), + [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), + [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), + [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), - % start a proc and register it - ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + %% start a proc and register it + {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), - ?line RegNames = lists:sort([test2,test_server]), + RegNames = lists:sort([test2,test_server]), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])), - ?line undefined = rpc:call(Cp3, global_group, global_groups, []), + undefined = rpc:call(Cp3, global_group, global_groups, []), + + Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, + Cpxnn, Cpynn, Cpznn], + Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), + [] = (Own_nodes -- Own_nodes_should), + [] = (Own_nodes_should -- Own_nodes), + + Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout2) + end, + Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout3) + end, + Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout4) + end, - ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, - Cpxnn, Cpynn, Cpznn], - ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), - ?line [] = (Own_nodes -- Own_nodes_should), - ?line [] = (Own_nodes_should -- Own_nodes), - - ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout2) - end, - ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout3) - end, - ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout4) - end, - - - % start a proc and register it - ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + + %% start a proc and register it + {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), %%------------------------------------ %% Test monitor nodes %%------------------------------------ - ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), - % Kill node Cp1 - ?line Pid2 = + %% Kill node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]), - ?line test_server:sleep(100), - ?line stop_node(Cp1), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ct:sleep(100), + stop_node(Cp1), + ct:sleep(1000), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), - % Kill node Cpz - ?line Pid2 = + %% Kill node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]), - ?line test_server:sleep(100), - ?line stop_node(Cpz), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ct:sleep(100), + stop_node(Cpz), + ct:sleep(1000), - % Restart node Cp1 - ?line Pid2 = + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% Restart node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]), - ?line {ok, Cp1} = start_node_no(cp1, Config), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), - ?line wait_for_ready_net(), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + {ok, Cp1} = start_node_no(cp1, Config), + pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), + pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), + wait_for_ready_net(), - % Restart node Cpz - ?line Pid2 = + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% Restart node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]), - ?line {ok, Cpz} = start_node_no(cpz, Config), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), - ?line wait_for_ready_net(), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + {ok, Cpz} = start_node_no(cpz, Config), + pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), + pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), + wait_for_ready_net(), - % stop the nodes, and make sure names are released. + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), @@ -293,174 +286,169 @@ no_gg_proc(Config) when is_list(Config) -> stop_node(Cpy), stop_node(Cpz), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line test_server:timetrap_cancel(Dog), + ?UNTIL(undefined =:= global:whereis_name(test)), ok. - -no_gg_proc_sync(suite) -> []; -no_gg_proc_sync(doc) -> - ["Start a system without global groups, but syncing the nodes by using " - "sync_nodes_optional."]; -no_gg_proc_sync(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(200)), - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "no_global_group_sync.config"), - ?line {ok, Fd} = file:open(File, [write]), +%% Start a system without global groups, but syncing the nodes by using +%% sync_nodes_optional. +no_gg_proc_sync(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "no_global_group_sync.config"), + {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config), - ?line config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz), - - ?line Cp1nn = node_at(Ncp1), - ?line Cp2nn = node_at(Ncp2), - ?line Cp3nn = node_at(Ncp3), - ?line Cpxnn = node_at(Ncpx), - ?line Cpynn = node_at(Ncpy), - ?line Cpznn = node_at(Ncpz), - - ?line {ok, Cp1} = start_node_no2(Ncp1, Config), - ?line {ok, Cp2} = start_node_no2(Ncp2, Config), - ?line {ok, Cp3} = start_node_no2(Ncp3, Config), - ?line {ok, Cpx} = start_node_no2(Ncpx, Config), - ?line {ok, Cpy} = start_node_no2(Ncpy, Config), - ?line {ok, Cpz} = start_node_no2(Ncpz, Config), + config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz), + + Cp1nn = node_at(Ncp1), + Cp2nn = node_at(Ncp2), + Cp3nn = node_at(Ncp3), + Cpxnn = node_at(Ncpx), + Cpynn = node_at(Ncpy), + Cpznn = node_at(Ncpz), + + {ok, Cp1} = start_node_no2(Ncp1, Config), + {ok, Cp2} = start_node_no2(Ncp2, Config), + {ok, Cp3} = start_node_no2(Ncp3, Config), + {ok, Cpx} = start_node_no2(Ncpx, Config), + {ok, Cpy} = start_node_no2(Ncpy, Config), + {ok, Cpz} = start_node_no2(Ncpz, Config), %% let the nodes know of each other - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), - ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), - ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), + pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), + pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), + pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), + pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), + pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), - ?line wait_for_ready_net(), + wait_for_ready_net(), - ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), - ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), - ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), - ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), - ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), - ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), + [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), + [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), + [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), - % start a proc and register it - ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + %% start a proc and register it + {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), - ?line RegNames = lists:sort([test2,test_server]), + RegNames = lists:sort([test2,test_server]), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])), - ?line undefined = rpc:call(Cp3, global_group, global_groups, []), + undefined = rpc:call(Cp3, global_group, global_groups, []), - ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, - Cpxnn, Cpynn, Cpznn], - ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), - ?line [] = (Own_nodes -- Own_nodes_should), - ?line [] = (Own_nodes_should -- Own_nodes), - - ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout2) - end, - ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout3) - end, - ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout4) - end, - - - % start a proc and register it - ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, + Cpxnn, Cpynn, Cpznn], + Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), + [] = (Own_nodes -- Own_nodes_should), + [] = (Own_nodes_should -- Own_nodes), + + Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout2) + end, + Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout3) + end, + Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout4) + end, + + + %% start a proc and register it + {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), %%------------------------------------ %% Test monitor nodes %%------------------------------------ - ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), - % Kill node Cp1 - ?line Pid2 = + %% Kill node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]), - ?line test_server:sleep(100), - ?line stop_node(Cp1), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ct:sleep(100), + stop_node(Cp1), + ct:sleep(1000), - % Kill node Cpz - ?line Pid2 = + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% Kill node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]), - ?line test_server:sleep(100), - ?line stop_node(Cpz), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ct:sleep(100), + stop_node(Cpz), + ct:sleep(1000), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), - % Restart node Cp1 - ?line Pid2 = + %% Restart node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]), - ?line {ok, Cp1} = start_node_no2(Ncp1, Config), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), - ?line wait_for_ready_net(), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + {ok, Cp1} = start_node_no2(Ncp1, Config), + pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), + pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), + wait_for_ready_net(), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), - % Restart node Cpz - ?line Pid2 = + %% Restart node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]), - ?line {ok, Cpz} = start_node_no2(Ncpz, Config), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), - ?line wait_for_ready_net(), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + {ok, Cpz} = start_node_no2(Ncpz, Config), + pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), + pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), + wait_for_ready_net(), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), - % stop the nodes, and make sure names are released. + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), @@ -468,173 +456,168 @@ no_gg_proc_sync(Config) when is_list(Config) -> stop_node(Cpy), stop_node(Cpz), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line test_server:timetrap_cancel(Dog), + ?UNTIL(undefined =:= global:whereis_name(test)), ok. - -compatible(suite) -> []; -compatible(doc) -> - ["Check that a system without global groups is compatible with the old R4 system."]; -compatible(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(200)), - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "global_group_comp.config"), - ?line {ok, Fd} = file:open(File, [write]), +%% Check that a system without global groups is compatible with the old R4 system. +compatible(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "global_group_comp.config"), + {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config), - ?line config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz), - - ?line Cp1nn = node_at(Ncp1), - ?line Cp2nn = node_at(Ncp2), - ?line Cp3nn = node_at(Ncp3), - ?line Cpxnn = node_at(Ncpx), - ?line Cpynn = node_at(Ncpy), - ?line Cpznn = node_at(Ncpz), - - ?line {ok, Cp1} = start_node_comp(Ncp1, Config), - ?line {ok, Cp2} = start_node_comp(Ncp2, Config), - ?line {ok, Cp3} = start_node_comp(Ncp3, Config), - ?line {ok, Cpx} = start_node_comp(Ncpx, Config), - ?line {ok, Cpy} = start_node_comp(Ncpy, Config), - ?line {ok, Cpz} = start_node_comp(Ncpz, Config), + config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz), + + Cp1nn = node_at(Ncp1), + Cp2nn = node_at(Ncp2), + Cp3nn = node_at(Ncp3), + Cpxnn = node_at(Ncpx), + Cpynn = node_at(Ncpy), + Cpznn = node_at(Ncpz), + + {ok, Cp1} = start_node_comp(Ncp1, Config), + {ok, Cp2} = start_node_comp(Ncp2, Config), + {ok, Cp3} = start_node_comp(Ncp3, Config), + {ok, Cpx} = start_node_comp(Ncpx, Config), + {ok, Cpy} = start_node_comp(Ncpy, Config), + {ok, Cpz} = start_node_comp(Ncpz, Config), %% let the nodes know of each other - ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), - ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), - ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), + pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), + pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), + pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), + pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), + pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), - ?line wait_for_ready_net(), + wait_for_ready_net(), - ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), - ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), - ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), - ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), - ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), - ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), + [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), + [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), + [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), - % start a proc and register it - ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + %% start a proc and register it + {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), - ?line RegNames = lists:sort([test2,test_server]), + RegNames = lists:sort([test2,test_server]), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])), - ?line RegNames = + RegNames = lists:sort( rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])), - ?line undefined = rpc:call(Cp3, global_group, global_groups, []), + undefined = rpc:call(Cp3, global_group, global_groups, []), - ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, - Cpxnn, Cpynn, Cpznn], - ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), - ?line [] = (Own_nodes -- Own_nodes_should), - ?line [] = (Own_nodes_should -- Own_nodes), - - ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout2) - end, - ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout3) - end, - ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), - ?line receive - {pong, Cp2} -> ok - after - 2000 -> test_server:fail(timeout4) - end, - - - % start a proc and register it - ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, + Cpxnn, Cpynn, Cpznn], + Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), + [] = (Own_nodes -- Own_nodes_should), + [] = (Own_nodes_should -- Own_nodes), + + Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout2) + end, + Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout3) + end, + Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> ct:fail(timeout4) + end, + + + %% start a proc and register it + {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), %%------------------------------------ %% Test monitor nodes %%------------------------------------ - ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), - % Kill node Cp1 - ?line Pid2 = + %% Kill node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]), - ?line test_server:sleep(100), - ?line stop_node(Cp1), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ct:sleep(100), + stop_node(Cp1), + ct:sleep(1000), - % Kill node Cpz - ?line Pid2 = + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% Kill node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]), - ?line test_server:sleep(100), - ?line stop_node(Cpz), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ct:sleep(100), + stop_node(Cpz), + ct:sleep(1000), - % Restart node Cp1 - ?line Pid2 = + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% Restart node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]), - ?line {ok, Cp1} = start_node_comp(Ncp1, Config), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), - ?line wait_for_ready_net(), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + {ok, Cp1} = start_node_comp(Ncp1, Config), + pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), + pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), + wait_for_ready_net(), - % Restart node Cpz - ?line Pid2 = + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% Restart node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]), - ?line {ok, Cpz} = start_node_comp(Ncpz, Config), - ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), - ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), - ?line wait_for_ready_net(), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + {ok, Cpz} = start_node_comp(Ncpz, Config), + pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), + pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), + wait_for_ready_net(), - % stop the nodes, and make sure names are released. + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), @@ -642,147 +625,137 @@ compatible(Config) when is_list(Config) -> stop_node(Cpy), stop_node(Cpz), - ?line ?UNTIL(undefined =:= global:whereis_name(test)), - ?line test_server:timetrap_cancel(Dog), + ?UNTIL(undefined =:= global:whereis_name(test)), ok. - -one_grp(suite) -> []; -one_grp(doc) -> ["Test a system with only one global group. "]; -one_grp(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(120)), - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, [write]), +%% Test a system with only one global group. . +one_grp(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "global_group.config"), + {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), - ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), + config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line {ok, Cp2} = start_node(Ncp2, Config), - ?line {ok, Cp3} = start_node(Ncp3, Config), + {ok, Cp1} = start_node(Ncp1, Config), + {ok, Cp2} = start_node(Ncp2, Config), + {ok, Cp3} = start_node(Ncp3, Config), - % sleep a while to make the global_group to sync... - test_server:sleep(1000), + %% sleep a while to make the global_group to sync... + ct:sleep(1000), - % start a proc and register it - ?line {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + %% start a proc and register it + {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), - % test that it is registered at all nodes - ?line Pid = rpc:call(Cp1, global, whereis_name, [test]), - ?line Pid = rpc:call(Cp2, global, whereis_name, [test]), - ?line Pid = rpc:call(Cp3, global, whereis_name, [test]), + %% test that it is registered at all nodes + Pid = rpc:call(Cp1, global, whereis_name, [test]), + Pid = rpc:call(Cp2, global, whereis_name, [test]), + Pid = rpc:call(Cp3, global, whereis_name, [test]), - % try to register the same name - ?line no = rpc:call(Cp1, global, register_name, [test, self()]), + %% try to register the same name + no = rpc:call(Cp1, global, register_name, [test, self()]), - % let process exit, check that it is unregistered automatically + %% let process exit, check that it is unregistered automatically Pid ! die, - ?line - ?UNTIL(begin + ?UNTIL(begin (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp3, global, whereis_name, [test])) end), - % test re_register - ?line {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), - ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test]), + %% test re_register + {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + Pid2 = rpc:call(Cp3, global, whereis_name, [test]), Pid3 = rpc:call(Cp3, ?MODULE, start_proc_rereg, [test]), - ?line Pid3 = rpc:call(Cp3, global, whereis_name, [test]), + Pid3 = rpc:call(Cp3, global, whereis_name, [test]), - % test sending + %% test sending rpc:call(Cp1, global, send, [test, {ping, self()}]), receive {pong, Cp3} -> ok after - 2000 -> test_server:fail(timeout1) + 2000 -> ct:fail(timeout1) end, rpc:call(Cp3, global, send, [test, {ping, self()}]), receive {pong, Cp3} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line rpc:call(Cp3, global, unregister_name, [test]), - ?line undefined = rpc:call(Cp1, global, whereis_name, [test]), - ?line undefined = rpc:call(Cp2, global, whereis_name, [test]), - ?line undefined = rpc:call(Cp3, global, whereis_name, [test]), + rpc:call(Cp3, global, unregister_name, [test]), + undefined = rpc:call(Cp1, global, whereis_name, [test]), + undefined = rpc:call(Cp2, global, whereis_name, [test]), + undefined = rpc:call(Cp3, global, whereis_name, [test]), Pid3 ! die, - ?line ?UNTIL(undefined =:= rpc:call(Cp3, global, whereis_name, [test])), + ?UNTIL(undefined =:= rpc:call(Cp3, global, whereis_name, [test])), - % register a proc - ?line {_, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), + %% register a proc + {_, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), - % stop the nodes, and make sure names are released. + %% stop the nodes, and make sure names are released. stop_node(Cp3), - ?line ?UNTIL(undefined =:= rpc:call(Cp1, global, whereis_name, [test])), + ?UNTIL(undefined =:= rpc:call(Cp1, global, whereis_name, [test])), Pid2 ! die, stop_node(Cp1), stop_node(Cp2), - ?line test_server:timetrap_cancel(Dog), ok. - -one_grp_x(suite) -> []; -one_grp_x(doc) -> ["Check a system with only one global group. " - "Start the nodes with different time intervals. "]; -one_grp_x(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(120)), - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, [write]), +%% Check a system with only one global group. +%% Start the nodes with different time intervals. +one_grp_x(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "global_group.config"), + {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), - ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), + config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), - ?line {ok, Cp1} = start_node(Ncp1, Config), - % sleep a while to make the global_group to sync... - test_server:sleep(1000), + {ok, Cp1} = start_node(Ncp1, Config), + %% sleep a while to make the global_group to sync... + ct:sleep(1000), - % start a proc and register it - ?line {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + %% start a proc and register it + {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), - ?line {ok, Cp2} = start_node(Ncp2, Config), - % sleep a while to make the global_group to sync... - test_server:sleep(1000), + {ok, Cp2} = start_node(Ncp2, Config), + %% sleep a while to make the global_group to sync... + ct:sleep(1000), - % test that it is registered at all nodes - ?line Pid = rpc:call(Cp1, global, whereis_name, [test]), - ?line Pid = rpc:call(Cp2, global, whereis_name, [test]), + %% test that it is registered at all nodes + Pid = rpc:call(Cp1, global, whereis_name, [test]), + Pid = rpc:call(Cp2, global, whereis_name, [test]), - ?line {ok, Cp3} = start_node(Ncp3, Config), - % sleep a while to make the global_group to sync... - test_server:sleep(1000), + {ok, Cp3} = start_node(Ncp3, Config), + %% sleep a while to make the global_group to sync... + ct:sleep(1000), - ?line Pid = rpc:call(Cp3, global, whereis_name, [test]), + Pid = rpc:call(Cp3, global, whereis_name, [test]), - % try to register the same name - ?line no = rpc:call(Cp1, global, register_name, [test, self()]), + %% try to register the same name + no = rpc:call(Cp1, global, register_name, [test, self()]), - % let process exit, check that it is unregistered automatically + %% let process exit, check that it is unregistered automatically Pid ! die, - ?line - ?UNTIL(begin + ?UNTIL(begin (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and (undefined =:= rpc:call(Cp3, global, whereis_name, [test])) end), - % test re_register - ?line {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), - ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test]), + %% test re_register + {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + Pid2 = rpc:call(Cp3, global, whereis_name, [test]), Pid2 ! die, @@ -790,296 +763,291 @@ one_grp_x(Config) when is_list(Config) -> stop_node(Cp2), stop_node(Cp3), - ?line test_server:timetrap_cancel(Dog), ok. - -two_grp(suite) -> []; -two_grp(doc) -> ["Test a two global group system. "]; -two_grp(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(200)), - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, [write]), +%% Test a two global group system. . +two_grp(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "global_group.config"), + {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config), - ?line config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq), - - ?line Cp1nn = node_at(Ncp1), - ?line Cp2nn = node_at(Ncp2), - ?line Cp3nn = node_at(Ncp3), - ?line Cpxnn = node_at(Ncpx), - ?line Cpynn = node_at(Ncpy), - ?line Cpznn = node_at(Ncpz), - - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line {ok, Cp2} = start_node(Ncp2, Config), - ?line {ok, Cp3} = start_node(Ncp3, Config), - ?line {ok, Cpx} = start_node(Ncpx, Config), - ?line {ok, Cpy} = start_node(Ncpy, Config), - ?line {ok, Cpz} = start_node(Ncpz, Config), + config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq), + + Cp1nn = node_at(Ncp1), + Cp2nn = node_at(Ncp2), + Cp3nn = node_at(Ncp3), + Cpxnn = node_at(Ncpx), + Cpynn = node_at(Ncpy), + Cpznn = node_at(Ncpz), + + {ok, Cp1} = start_node(Ncp1, Config), + {ok, Cp2} = start_node(Ncp2, Config), + {ok, Cp3} = start_node(Ncp3, Config), + {ok, Cpx} = start_node(Ncpx, Config), + {ok, Cpy} = start_node(Ncpy, Config), + {ok, Cpz} = start_node(Ncpz, Config), %% The groups (cpq not started): %% [{nc1, [cp1,cp2,cp3]}, {nc2, [cpx,cpy,cpz]}, {nc3, [cpq]}] - % sleep a while to make the global_groups to sync... - test_server:sleep(1000), - - % check the global group names - ?line {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []), - ?line {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []), - ?line {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []), - ?line {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []), - ?line {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []), - ?line {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []), - - % check the global group nodes - ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp1, global_group, own_nodes, []), - ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []), - ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp3, global_group, own_nodes, []), - ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpx, global_group, own_nodes, []), - ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpy, global_group, own_nodes, []), - ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpz, global_group, own_nodes, []), - - - % start a proc and register it - ?line {Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), - - ?line Pid1 = rpc:call(Cp1, global_group, send, [test, {io, from_cp1}]), - ?line Pid1 = rpc:call(Cpx, global_group, send, [test, {io, from_cpx}]), - ?line Pid1 = rpc:call(Cp1, global_group, send, [{group,nc1}, test, - {io, from_cp1}]), - ?line [test] = + %% sleep a while to make the global_groups to sync... + ct:sleep(1000), + + %% check the global group names + {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []), + {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []), + {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []), + {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []), + {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []), + {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []), + + %% check the global group nodes + [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp1, global_group, own_nodes, []), + [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []), + [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp3, global_group, own_nodes, []), + [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpx, global_group, own_nodes, []), + [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpy, global_group, own_nodes, []), + [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpz, global_group, own_nodes, []), + + + %% start a proc and register it + {Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + + Pid1 = rpc:call(Cp1, global_group, send, [test, {io, from_cp1}]), + Pid1 = rpc:call(Cpx, global_group, send, [test, {io, from_cpx}]), + Pid1 = rpc:call(Cp1, global_group, send, [{group,nc1}, test, + {io, from_cp1}]), + [test] = rpc:call(Cpx, global_group, registered_names, [{node, Cp1nn}]), - ?line [test] = + [test] = rpc:call(Cpx, global_group, registered_names, [{group, nc1}]), - ?line [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpxnn}]), - ?line [] = rpc:call(Cpx, global_group, registered_names, [{group, nc2}]), - ?line Pid1 = rpc:call(Cpx, global_group, send, [{group,nc1}, test, - {io, from_cp1}]), - ?line {badarg,{test,{io,from_cpx}}} = + [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpxnn}]), + [] = rpc:call(Cpx, global_group, registered_names, [{group, nc2}]), + Pid1 = rpc:call(Cpx, global_group, send, [{group,nc1}, test, + {io, from_cp1}]), + {badarg,{test,{io,from_cpx}}} = rpc:call(Cp1, global_group, send, [{group,nc2}, test, {io, from_cpx}]), - ?line {badarg,{test,{io,from_cpx}}} = + {badarg,{test,{io,from_cpx}}} = rpc:call(Cpx, global_group, send, [{group,nc2}, test, {io, from_cpx}]), - % test that it is registered at all nodes - ?line Pid1 = rpc:call(Cp1, global, whereis_name, [test]), - ?line Pid1 = rpc:call(Cp2, global, whereis_name, [test]), - ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test]), - ?line undefined = rpc:call(Cpx, global, whereis_name, [test]), - ?line undefined = rpc:call(Cpy, global, whereis_name, [test]), - ?line undefined = rpc:call(Cpz, global, whereis_name, [test]), - - % start a proc and register it - ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), - - % test that it is registered at all nodes - ?line Pid1 = rpc:call(Cp1, global, whereis_name, [test]), - ?line Pid1 = rpc:call(Cp2, global, whereis_name, [test]), - ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test]), - ?line PidX = rpc:call(Cpx, global, whereis_name, [test]), - ?line PidX = rpc:call(Cpy, global, whereis_name, [test]), - ?line PidX = rpc:call(Cpz, global, whereis_name, [test]), - + %% test that it is registered at all nodes + Pid1 = rpc:call(Cp1, global, whereis_name, [test]), + Pid1 = rpc:call(Cp2, global, whereis_name, [test]), + Pid1 = rpc:call(Cp3, global, whereis_name, [test]), + undefined = rpc:call(Cpx, global, whereis_name, [test]), + undefined = rpc:call(Cpy, global, whereis_name, [test]), + undefined = rpc:call(Cpz, global, whereis_name, [test]), + + %% start a proc and register it + {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + + %% test that it is registered at all nodes + Pid1 = rpc:call(Cp1, global, whereis_name, [test]), + Pid1 = rpc:call(Cp2, global, whereis_name, [test]), + Pid1 = rpc:call(Cp3, global, whereis_name, [test]), + PidX = rpc:call(Cpx, global, whereis_name, [test]), + PidX = rpc:call(Cpy, global, whereis_name, [test]), + PidX = rpc:call(Cpz, global, whereis_name, [test]), + Pid1 ! die, %% If we don't wait for global on other nodes to have updated its %% tables, 'test' may still be defined at the point when it is %% tested a few lines below. - ?line - ?UNTIL(begin + ?UNTIL(begin Pid = rpc:call(Cp2, global, whereis_name, [test]), undefined =:= Pid end), - % start a proc and register it - ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + %% start a proc and register it + {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), - % test that it is registered at all nodes - ?line Pid2 = rpc:call(Cp1, global, whereis_name, [test2]), - ?line Pid2 = rpc:call(Cp2, global, whereis_name, [test2]), - ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test2]), - ?line PidX = rpc:call(Cpx, global, whereis_name, [test]), - ?line PidX = rpc:call(Cpy, global, whereis_name, [test]), - ?line PidX = rpc:call(Cpz, global, whereis_name, [test]), - - ?line undefined = rpc:call(Cp1, global, whereis_name, [test]), - ?line undefined = rpc:call(Cp2, global, whereis_name, [test]), - ?line undefined = rpc:call(Cp3, global, whereis_name, [test]), - ?line undefined = rpc:call(Cpx, global, whereis_name, [test2]), - ?line undefined = rpc:call(Cpy, global, whereis_name, [test2]), - ?line undefined = rpc:call(Cpz, global, whereis_name, [test2]), - + %% test that it is registered at all nodes + Pid2 = rpc:call(Cp1, global, whereis_name, [test2]), + Pid2 = rpc:call(Cp2, global, whereis_name, [test2]), + Pid2 = rpc:call(Cp3, global, whereis_name, [test2]), + PidX = rpc:call(Cpx, global, whereis_name, [test]), + PidX = rpc:call(Cpy, global, whereis_name, [test]), + PidX = rpc:call(Cpz, global, whereis_name, [test]), + + undefined = rpc:call(Cp1, global, whereis_name, [test]), + undefined = rpc:call(Cp2, global, whereis_name, [test]), + undefined = rpc:call(Cp3, global, whereis_name, [test]), + undefined = rpc:call(Cpx, global, whereis_name, [test2]), + undefined = rpc:call(Cpy, global, whereis_name, [test2]), + undefined = rpc:call(Cpz, global, whereis_name, [test2]), - ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + + Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line Pid2 = rpc:call(Cp3, global_group, send, [test2, {ping, self()}]), + Pid2 = rpc:call(Cp3, global_group, send, [test2, {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpx, global_group, send, [test, {ping, self()}]), + PidX = rpc:call(Cpx, global_group, send, [test, {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpy, global_group, send, [test, {ping, self()}]), + PidX = rpc:call(Cpy, global_group, send, [test, {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpz, global_group, send, [test, {ping, self()}]), + PidX = rpc:call(Cpz, global_group, send, [test, {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1nn}, test2, - {ping, self()}]), + Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1nn}, test2, + {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2nn}, test2, - {ping, self()}]), + Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2nn}, test2, + {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3nn}, test2, - {ping, self()}]), + Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3nn}, test2, + {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpznn}, test, - {ping, self()}]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpznn}, test, + {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpy, global_group, send, [{node, Cpxnn}, test, - {ping, self()}]), + PidX = rpc:call(Cpy, global_group, send, [{node, Cpxnn}, test, + {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpz, global_group, send, [{node, Cpynn}, test, - {ping, self()}]), + PidX = rpc:call(Cpz, global_group, send, [{node, Cpynn}, test, + {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line Pid2 = rpc:call(Cpx, global_group, send, [{group, nc1}, test2, - {ping, self()}]), + Pid2 = rpc:call(Cpx, global_group, send, [{group, nc1}, test2, + {ping, self()}]), receive {pong, Cp2} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, - ?line PidX = rpc:call(Cpy, global_group, send, [{group, nc2}, test, - {ping, self()}]), + PidX = rpc:call(Cpy, global_group, send, [{group, nc2}, test, + {ping, self()}]), receive {pong, Cpx} -> ok after - 2000 -> test_server:fail(timeout2) + 2000 -> ct:fail(timeout2) end, %%------------------------------------ %% Test monitor nodes %%------------------------------------ - ?line Pid2 = + Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), - ?line PidX = + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), - % Kill node Cp1 - ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, - {wait_nodedown, Cp1}]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, - {wait_nodedown, Cp1}]), - ?line test_server:sleep(100), - ?line stop_node(Cp1), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodedown), - ?line PidX = + %% Kill node Cp1 + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodedown, Cp1}]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodedown, Cp1}]), + ct:sleep(100), + stop_node(Cp1), + ct:sleep(1000), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodedown), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]), - % Kill node Cpz - ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, - {wait_nodedown, Cpz}]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, - {wait_nodedown, Cpz}]), - ?line test_server:sleep(100), - ?line stop_node(Cpz), - ?line test_server:sleep(1000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodedown), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), - ?line Pid2 = + %% Kill node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodedown, Cpz}]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodedown, Cpz}]), + ct:sleep(100), + stop_node(Cpz), + ct:sleep(1000), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodedown), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]), - % Restart node Cp1 - ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []), - ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, - {wait_nodeup, Cp1}]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, - {wait_nodeup, Cp1}]), - ?line test_server:sleep(100), - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line test_server:sleep(5000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodeup), - ?line PidX = + %% Restart node Cp1 + [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []), + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodeup, Cp1}]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodeup, Cp1}]), + ct:sleep(100), + {ok, Cp1} = start_node(Ncp1, Config), + ct:sleep(5000), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodeup), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]), - % Restart node Cpz - ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, - {wait_nodeup, Cpz}]), - ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, - {wait_nodeup, Cpz}]), - ?line test_server:sleep(100), - ?line {ok, Cpz} = start_node(Ncpz, Config), - ?line test_server:sleep(5000), - - ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodeup), - ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), - ?line Pid2 = + %% Restart node Cpz + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodeup, Cpz}]), + PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodeup, Cpz}]), + ct:sleep(100), + {ok, Cpz} = start_node(Ncpz, Config), + ct:sleep(5000), + + ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodeup), + ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]), @@ -1093,72 +1061,68 @@ two_grp(Config) when is_list(Config) -> stop_node(Cpy), stop_node(Cpz), - ?line test_server:timetrap_cancel(Dog), ok. - -hidden_groups(suite) -> []; -hidden_groups(doc) -> ["Test hidden global groups."]; -hidden_groups(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(200)), - ?line Dir = ?config(priv_dir, Config), - ?line File = filename:join(Dir, "global_group.config"), - ?line {ok, Fd} = file:open(File, [write]), +%% Test hidden global groups. +hidden_groups(Config) when is_list(Config) -> + Dir = proplists:get_value(priv_dir, Config), + File = filename:join(Dir, "global_group.config"), + {ok, Fd} = file:open(File, [write]), [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config), - ?line config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq), - - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line {ok, Cp2} = start_node(Ncp2, Config), - ?line {ok, Cp3} = start_node(Ncp3, Config), - ?line {ok, Cpx} = start_node(Ncpx, Config), - ?line {ok, Cpy} = start_node(Ncpy, Config), - ?line {ok, Cpz} = start_node(Ncpz, Config), - ?line {ok, Cpq} = start_node(Ncpq, Config), - - % sleep a while to make the global_groups to sync... - test_server:sleep(1000), - - % check the global group names - ?line {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []), - ?line {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []), - ?line {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []), - ?line {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []), - ?line {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []), - ?line {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []), - - % check the global group nodes - ?line [Cp1, Cp2, Cp3] = rpc:call(Cp1, global_group, own_nodes, []), - ?line [Cp1, Cp2, Cp3] = rpc:call(Cp2, global_group, own_nodes, []), - ?line [Cp1, Cp2, Cp3] = rpc:call(Cp3, global_group, own_nodes, []), - ?line [Cpx, Cpy, Cpz] = rpc:call(Cpx, global_group, own_nodes, []), - ?line [Cpx, Cpy, Cpz] = rpc:call(Cpy, global_group, own_nodes, []), - ?line [Cpx, Cpy, Cpz] = rpc:call(Cpz, global_group, own_nodes, []), - ?line [Cpq] = rpc:call(Cpq, global_group, own_nodes, []), - - % Make some inter group connections - ?line pong = rpc:call(Cp1, net_adm, ping, [Cpx]), - ?line pong = rpc:call(Cpy, net_adm, ping, [Cp2]), - ?line pong = rpc:call(Cp3, net_adm, ping, [Cpx]), - ?line pong = rpc:call(Cpz, net_adm, ping, [Cp3]), - ?line pong = rpc:call(Cpq, net_adm, ping, [Cp1]), - ?line pong = rpc:call(Cpz, net_adm, ping, [Cpq]), - - % Check that no inter group connections are visible + config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq), + + {ok, Cp1} = start_node(Ncp1, Config), + {ok, Cp2} = start_node(Ncp2, Config), + {ok, Cp3} = start_node(Ncp3, Config), + {ok, Cpx} = start_node(Ncpx, Config), + {ok, Cpy} = start_node(Ncpy, Config), + {ok, Cpz} = start_node(Ncpz, Config), + {ok, Cpq} = start_node(Ncpq, Config), + + %% sleep a while to make the global_groups to sync... + ct:sleep(1000), + + %% check the global group names + {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []), + {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []), + {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []), + {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []), + {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []), + {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []), + + %% check the global group nodes + [Cp1, Cp2, Cp3] = rpc:call(Cp1, global_group, own_nodes, []), + [Cp1, Cp2, Cp3] = rpc:call(Cp2, global_group, own_nodes, []), + [Cp1, Cp2, Cp3] = rpc:call(Cp3, global_group, own_nodes, []), + [Cpx, Cpy, Cpz] = rpc:call(Cpx, global_group, own_nodes, []), + [Cpx, Cpy, Cpz] = rpc:call(Cpy, global_group, own_nodes, []), + [Cpx, Cpy, Cpz] = rpc:call(Cpz, global_group, own_nodes, []), + [Cpq] = rpc:call(Cpq, global_group, own_nodes, []), + + %% Make some inter group connections + pong = rpc:call(Cp1, net_adm, ping, [Cpx]), + pong = rpc:call(Cpy, net_adm, ping, [Cp2]), + pong = rpc:call(Cp3, net_adm, ping, [Cpx]), + pong = rpc:call(Cpz, net_adm, ping, [Cp3]), + pong = rpc:call(Cpq, net_adm, ping, [Cp1]), + pong = rpc:call(Cpz, net_adm, ping, [Cpq]), + + %% Check that no inter group connections are visible NC1Nodes = lists:sort([Cp1, Cp2, Cp3]), NC2Nodes = lists:sort([Cpx, Cpy, Cpz]), - ?line NC1Nodes = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]), - ?line NC1Nodes = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]), - ?line NC1Nodes = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]), - ?line NC2Nodes = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]), - ?line NC2Nodes = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]), - ?line NC2Nodes = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]), + NC1Nodes = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]), + NC1Nodes = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]), + NC1Nodes = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]), + NC2Nodes = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]), + NC2Nodes = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]), + NC2Nodes = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]), NC12Nodes = lists:append(NC1Nodes, NC2Nodes), - ?line false = lists:any(fun(N) -> lists:member(N, NC12Nodes) end, - rpc:call(Cpq, erlang, nodes, [])), + false = lists:any(fun(N) -> lists:member(N, NC12Nodes) end, + rpc:call(Cpq, erlang, nodes, [])), stop_node(Cp1), @@ -1169,63 +1133,68 @@ hidden_groups(Config) when is_list(Config) -> stop_node(Cpz), stop_node(Cpq), - ?line test_server:timetrap_cancel(Dog), ok. - -test_exit(suite) -> []; -test_exit(doc) -> ["Checks when the search process exits. "]; -test_exit(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(120)), - ?line NN = node_name(atom_to_list(node())), - ?line Cp1nn = list_to_atom("cp1@" ++ NN), +%% Checks when the search process exits. . +test_exit(Config) when is_list(Config) -> + NN = node_name(atom_to_list(node())), + Cp1nn = list_to_atom("cp1@" ++ NN), - ?line {ok, Cp1} = start_node(cp1, Config), - ?line {ok, Cp2} = start_node(cp2, Config), - ?line {ok, Cp3} = start_node(cp3, Config), + {ok, Cp1} = start_node(cp1, Config), + {ok, Cp2} = start_node(cp2, Config), + {ok, Cp3} = start_node(cp3, Config), - test_server:sleep(1000), + ct:sleep(1000), - ?line {error, illegal_function_call} = + {error, illegal_function_call} = rpc:call(Cp1, global_group, registered_names_test, [{node, Cp1nn}]), - ?line {badarg,_} = + {badarg,_} = rpc:call(Cp1, global_group, send, [king, "The message"]), - ?line undefined = rpc:call(Cp1, global_group, whereis_name, [king]), - - % stop the nodes, and make sure names are released. + undefined = rpc:call(Cp1, global_group, whereis_name, [king]), + + % make sure the search process really exits after every global_group operations + ProcessCount0 = rpc:call(Cp1, erlang, system_info, [process_count]), + _ = rpc:call(Cp1, global_group, whereis_name, [{node, Cp1nn}, whatever_pid_name]), + ProcessCount1 = rpc:call(Cp1, erlang, system_info, [process_count]), + _ = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + ProcessCount2 = rpc:call(Cp1, erlang, system_info, [process_count]), + _ = rpc:call(Cp1, global_group, send, [{node, Cp1nn}, whatever_pid_name, msg]), + ProcessCount3 = rpc:call(Cp1, erlang, system_info, [process_count]), + ProcessCount0 = ProcessCount1 = ProcessCount2 = ProcessCount3, + + %% stop the nodes, and make sure names are released. stop_node(Cp1), stop_node(Cp2), stop_node(Cp3), - % sleep to let the nodes die - test_server:sleep(1000), + %% sleep to let the nodes die + ct:sleep(1000), - ?line test_server:timetrap_cancel(Dog), ok. - + start_node(Name, Config) -> Pa=filename:dirname(code:which(?MODULE)), - Dir=?config(priv_dir, Config), + Dir=proplists:get_value(priv_dir, Config), ConfFile = " -config " ++ filename:join(Dir, "global_group"), test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). start_node_no(Name, Config) -> Pa=filename:dirname(code:which(?MODULE)), - Dir=?config(priv_dir, Config), + Dir=proplists:get_value(priv_dir, Config), ConfFile = " -config " ++ filename:join(Dir, "no_global_group"), test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). start_node_no2(Name, Config) -> Pa=filename:dirname(code:which(?MODULE)), - Dir=?config(priv_dir, Config), + Dir=proplists:get_value(priv_dir, Config), ConfFile = " -config " ++ filename:join(Dir, "no_global_group_sync"), test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). start_node_comp(Name, Config) -> Pa=filename:dirname(code:which(?MODULE)), - Dir=?config(priv_dir, Config), + Dir=proplists:get_value(priv_dir, Config), ConfFile = " -config " ++ filename:join(Dir, "global_group_comp"), test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). @@ -1242,17 +1211,17 @@ node_name(Name, Config) -> lists:concat([Name,U,?testcase,U,Pid,U,U,L]). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). wait_for_ready_net() -> Nodes = lists:sort(?NODES), ?UNTIL(begin lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and - lists:all(fun(N) -> - LNs = rpc:call(N, erlang, nodes, []), - Nodes =:= lists:sort([N | LNs]) - end, Nodes) + lists:all(fun(N) -> + LNs = rpc:call(N, erlang, nodes, []), + Nodes =:= lists:sort([N | LNs]) + end, Nodes) end). get_known(Node) -> @@ -1262,11 +1231,11 @@ get_known(Node) -> config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " - " '~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000}," - "{global_groups, [{nc1, hidden, ['~s@~s','~s@~s','~s@~s']}, " - "{nc2, hidden, ['~s@~s','~s@~s','~s@~s']}, " - "{nc3, normal, ['~s@~s']}]} ] }]. ~n", + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000}," + "{global_groups, [{nc1, hidden, ['~s@~s','~s@~s','~s@~s']}, " + "{nc2, hidden, ['~s@~s','~s@~s','~s@~s']}, " + "{nc3, normal, ['~s@~s']}]} ] }]. ~n", [Ncp1, M, Ncp2, M, Ncp3, M, Ncpx, M, Ncpy, M, Ncpz, M, Ncp1, M, Ncp2, M, Ncp3, M, @@ -1276,11 +1245,11 @@ config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) -> config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " - " '~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000}," - "{global_groups, [{nc1, ['~s@~s','~s@~s','~s@~s']}, " - " {nc2, ['~s@~s','~s@~s','~s@~s']}, " - "{nc3, ['~s@~s']}]} ] }]. ~n", + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000}," + "{global_groups, [{nc1, ['~s@~s','~s@~s','~s@~s']}, " + " {nc2, ['~s@~s','~s@~s','~s@~s']}, " + "{nc3, ['~s@~s']}]} ] }]. ~n", [Ncp1, M, Ncp2, M, Ncp3, M, Ncpx, M, Ncpy, M, Ncpz, M, Ncp1, M, Ncp2, M, Ncp3, M, @@ -1293,9 +1262,9 @@ config_no(Fd) -> config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " - " '~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000}," - "{global_groups, []} ] }] .~n", + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000}," + "{global_groups, []} ] }] .~n", [Ncp1, M, Ncp2, M, Ncp3, M, Ncpx, M, Ncpy, M, Ncpz, M]). @@ -1303,8 +1272,8 @@ config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) -> config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " - " '~s@~s','~s@~s','~s@~s']}," - "{sync_nodes_timeout, 1000} ] }] .~n", + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000} ] }] .~n", [Ncp1, M, Ncp2, M, Ncp3, M, Ncpx, M, Ncpy, M, Ncpz, M]). @@ -1325,7 +1294,7 @@ start_proc(Name) -> receive {Pid, Res} -> {Pid, Res} end. - + start_proc_rereg(Name) -> Pid = spawn(?MODULE, init2, [self(), Name]), receive @@ -1437,9 +1406,9 @@ assert_loop(Cp, CpName, Name, NamePid, Loop) -> Loop -> ok; Other1 -> - test_server:fail(Other1) + ct:fail(Other1) after 5000 -> - test_server:fail(timeout) + ct:fail(timeout) end. loop_until_true(Fun) -> diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl index 02954aa54c..22db24de5f 100644 --- a/lib/kernel/test/heart_SUITE.erl +++ b/lib/kernel/test/heart_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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. @@ -19,7 +19,7 @@ %% -module(heart_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, start/1, restart/1, @@ -27,46 +27,55 @@ node_start_immediately_after_crash/1, node_start_soon_after_crash/1, set_cmd/1, clear_cmd/1, get_cmd/1, - dont_drop/1, kill_pid/1]). + callback_api/1, + options_api/1, + dont_drop/1, kill_pid/1, heart_no_kill/1]). -export([init_per_testcase/2, end_per_testcase/2]). --export([start_heart_stress/1, mangle/1, suicide_by_heart/0]). +-export([start_heart_stress/1, mangle/1, suicide_by_heart/0, non_suicide_by_heart/0]). -define(DEFAULT_TIMEOUT_SECS, 120). +-define(UNIQ_NODE_NAME, + list_to_atom(?MODULE_STRING ++ "__" ++ + atom_to_list(?FUNCTION_NAME) ++ "_" ++ + integer_to_list(erlang:unique_integer([positive])))). + init_per_testcase(_Func, Config) -> - Dog=test_server:timetrap(test_server:seconds(?DEFAULT_TIMEOUT_SECS)), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Func, Config) -> +end_per_testcase(_Func, _Config) -> Nodes = nodes(), lists:foreach(fun(X) -> NNam = list_to_atom(hd(string:tokens(atom_to_list(X),"@"))), case NNam of heart_test -> - ?t:format(1, "WARNING: Killed ~p~n", [X]), + ct:pal(?HI_VERBOSITY, "WARNING: Killed ~p~n", [X]), rpc:cast(X, erlang, halt, []); _ -> ok end - end, Nodes), - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog). + end, Nodes). %%----------------------------------------------------------------- %% Test suite for heart. %% Should be started in a CC view with: %% erl -sname master -rsh ctrsh %%----------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [ start, restart, reboot, node_start_immediately_after_crash, node_start_soon_after_crash, set_cmd, clear_cmd, get_cmd, - kill_pid + callback_api, + options_api, + kill_pid, + heart_no_kill ]. groups() -> @@ -93,7 +102,7 @@ end_per_suite(Config) when is_list(Config) -> start_check(Type, Name) -> start_check(Type, Name, []). start_check(Type, Name, Envs) -> - Args = case ?t:os_type() of + Args = case test_server:os_type() of {win32,_} -> "+t50000 -heart " ++ env_encode([{"HEART_COMMAND", no_reboot}|Envs]); _ -> @@ -103,32 +112,30 @@ start_check(Type, Name, Envs) -> loose -> loose_node:start(Name, Args, ?DEFAULT_TIMEOUT_SECS); _ -> - ?t:start_node(Name, Type, [{args, Args}]) + test_server:start_node(Name, Type, [{args, Args}]) end, erlang:monitor_node(Node, true), case rpc:call(Node, erlang, whereis, [heart]) of Pid when is_pid(Pid) -> ok; _ -> - test_server:fail(heart_not_started) + ct:fail(heart_not_started) end, {ok, Node}. -start(doc) -> []; -start(suite) -> {req, [{time, 10}]}; start(Config) when is_list(Config) -> - {ok, Node} = start_check(slave, heart_test), + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), rpc:call(Node, init, reboot, []), receive {nodedown, Node} -> ok - after 2000 -> test_server:fail(node_not_closed) + after 2000 -> ct:fail(node_not_closed) end, - test_server:sleep(5000), + timer:sleep(5000), case net_adm:ping(Node) of pang -> ok; _ -> - test_server:fail(node_rebooted) + ct:fail(node_rebooted) end, test_server:stop_node(Node). @@ -141,34 +148,24 @@ start(Config) when is_list(Config) -> %% restart %% Purpose: %% Check that a node is up and running after a init:restart/0 -restart(doc) -> []; -restart(suite) -> - case ?t:os_type() of - {Fam, _} when Fam == unix; Fam == win32 -> - {req, [{time,10}]}; - _ -> - {skip, "Only run on unix and win32"} - end; restart(Config) when is_list(Config) -> - {ok, Node} = start_check(loose, heart_test), + {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME), rpc:call(Node, init, restart, []), receive {nodedown, Node} -> ok - after 2000 -> - test_server:fail(node_not_closed) + after 5000 -> + ct:fail(node_not_closed) end, - test_server:sleep(5000), + timer:sleep(5000), node_check_up_down(Node, 2000), loose_node:stop(Node). %% reboot %% Purpose: %% Check that a node is up and running after a init:reboot/0 -reboot(doc) -> []; -reboot(suite) -> {req, [{time, 10}]}; reboot(Config) when is_list(Config) -> - {ok, Node} = start_check(slave, heart_test), + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), ok = rpc:call(Node, heart, set_cmd, [atom_to_list(lib:progname()) ++ @@ -178,9 +175,9 @@ reboot(Config) when is_list(Config) -> {nodedown, Node} -> ok after 2000 -> - test_server:fail(node_not_closed) + ct:fail(node_not_closed) end, - test_server:sleep(5000), + timer:sleep(5000), node_check_up_down(Node, 2000), ok. @@ -192,7 +189,6 @@ reboot(Config) when is_list(Config) -> %% May currently dump core in beam debug build due to lock-order violation %% This should be removed when a non-lockad information retriever is implemented %% for crash dumps -node_start_immediately_after_crash(suite) -> {req, [{time, 10}]}; node_start_immediately_after_crash(Config) when is_list(Config) -> Config2 = ignore_cores:setup(?MODULE, node_start_immediately_after_crash, Config, true), try @@ -203,7 +199,8 @@ node_start_immediately_after_crash(Config) when is_list(Config) -> node_start_immediately_after_crash_test(Config) when is_list(Config) -> - {ok, Node} = start_check(loose, heart_test_imm, [{"ERL_CRASH_DUMP_SECONDS", "0"}]), + {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME, + [{"ERL_CRASH_DUMP_SECONDS", "0"}]), ok = rpc:call(Node, heart, set_cmd, [atom_to_list(lib:progname()) ++ @@ -225,13 +222,13 @@ node_start_immediately_after_crash_test(Config) when is_list(Config) -> T0 = now(), receive {nodedown, Node} -> - test_server:format("Took ~.2f s. for node to go down~n", [timer:now_diff(now(), T0)/1000000]), + io:format("Took ~.2f s. for node to go down~n", [timer:now_diff(now(), T0)/1000000]), ok %% timeout is very liberal here. nodedown is received in about 1 s. on linux (palantir) %% and in about 10 s. on solaris (carcharoth) - after (15000*test_server:timetrap_scale_factor()) -> test_server:fail(node_not_closed) + after (15000*test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed) end, - test_server:sleep(3000), + timer:sleep(3000), node_check_up_down(Node, 2000), loose_node:stop(Node). @@ -244,7 +241,6 @@ node_start_immediately_after_crash_test(Config) when is_list(Config) -> %% May currently dump core in beam debug build due to lock-order violation %% This should be removed when a non-lockad information retriever is implemented %% for crash dumps -node_start_soon_after_crash(suite) -> {req, [{time, 10}]}; node_start_soon_after_crash(Config) when is_list(Config) -> Config2 = ignore_cores:setup(?MODULE, node_start_soon_after_crash, Config, true), try @@ -254,7 +250,8 @@ node_start_soon_after_crash(Config) when is_list(Config) -> end. node_start_soon_after_crash_test(Config) when is_list(Config) -> - {ok, Node} = start_check(loose, heart_test_soon, [{"ERL_CRASH_DUMP_SECONDS", "10"}]), + {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME, + [{"ERL_CRASH_DUMP_SECONDS", "10"}]), ok = rpc:call(Node, heart, set_cmd, [atom_to_list(lib:progname()) ++ @@ -274,9 +271,9 @@ node_start_soon_after_crash_test(Config) when is_list(Config) -> rpc:cast(Node, Mod, do, []), receive {nodedown, Node} -> ok - after (15000*test_server:timetrap_scale_factor()) -> test_server:fail(node_not_closed) + after (15000*test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed) end, - test_server:sleep(20000), + timer:sleep(20000), node_check_up_down(Node, 15000), loose_node:stop(Node). @@ -289,16 +286,15 @@ node_check_up_down(Node, Tmo) -> receive {nodedown, Node} -> ok after Tmo -> - test_server:fail(node_not_closed2) + ct:fail(node_not_closed2) end; _ -> - test_server:fail(node_not_rebooted) + ct:fail(node_not_rebooted) end. %% Only tests bad command, correct behaviour is tested in reboot/1. -set_cmd(suite) -> []; set_cmd(Config) when is_list(Config) -> - {ok, Node} = start_check(slave, heart_test), + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), Cmd = wrong_atom, {error, {bad_cmd, Cmd}} = rpc:call(Node, heart, set_cmd, [Cmd]), Cmd1 = lists:duplicate(2047, $a), @@ -310,9 +306,8 @@ set_cmd(Config) when is_list(Config) -> stop_node(Node), ok. -clear_cmd(suite) -> {req,[{time,15}]}; clear_cmd(Config) when is_list(Config) -> - {ok, Node} = start_check(slave, heart_test), + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), ok = rpc:call(Node, heart, set_cmd, [atom_to_list(lib:progname()) ++ " -noshell -heart " ++ name(Node) ++ "&"]), @@ -321,14 +316,14 @@ clear_cmd(Config) when is_list(Config) -> {nodedown, Node} -> ok after 2000 -> - test_server:fail(node_not_closed) + ct:fail(node_not_closed) end, - test_server:sleep(5000), + timer:sleep(5000), case net_adm:ping(Node) of pong -> erlang:monitor_node(Node, true); _ -> - test_server:fail(node_not_rebooted) + ct:fail(node_not_rebooted) end, ok = rpc:call(Node, heart, set_cmd, ["erl -noshell -heart " ++ name(Node) ++ "&"]), @@ -338,20 +333,19 @@ clear_cmd(Config) when is_list(Config) -> {nodedown, Node} -> ok after 2000 -> - test_server:fail(node_not_closed) + ct:fail(node_not_closed) end, - test_server:sleep(5000), + timer:sleep(5000), case net_adm:ping(Node) of pang -> ok; _ -> - test_server:fail(node_rebooted) + ct:fail(node_rebooted) end, ok. -get_cmd(suite) -> []; get_cmd(Config) when is_list(Config) -> - {ok, Node} = start_check(slave, heart_test), + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), ShortCmd = "test", ok = rpc:call(Node, heart, set_cmd, [ShortCmd]), @@ -365,15 +359,76 @@ get_cmd(Config) when is_list(Config) -> stop_node(Node), ok. -dont_drop(suite) -> +callback_api(Config) when is_list(Config) -> + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), + none = rpc:call(Node, heart, get_callback, []), + M0 = self(), + F0 = ok, + {error, {bad_callback, {M0,F0}}} = rpc:call(Node, heart, set_callback, [M0,F0]), + none = rpc:call(Node, heart, get_callback, []), + M1 = lists:duplicate(28, $a), + F1 = lists:duplicate(28, $b), + {error, {bad_callback, {M1,F1}}} = rpc:call(Node, heart, set_callback, [M1,F1]), + none = rpc:call(Node, heart, get_callback, []), + + M2 = heart_check_module, + F2 = cb_ok, + F3 = cb_error, + Code0 = generate(M2, [], [ + atom_to_list(F2) ++ "() -> ok.", + atom_to_list(F3) ++ "() -> exit(\"callback_error (as intended)\")." + ]), + {module, M2} = rpc:call(Node, erlang, load_module, [M2, Code0]), + ok = rpc:call(Node, M2, F2, []), + ok = rpc:call(Node, heart, set_callback, [M2,F2]), + {ok, {M2,F2}} = rpc:call(Node, heart, get_callback, []), + ok = rpc:call(Node, heart, clear_callback, []), + none = rpc:call(Node, heart, get_callback, []), + ok = rpc:call(Node, heart, set_callback, [M2,F2]), + {ok, {M2,F2}} = rpc:call(Node, heart, get_callback, []), + ok = rpc:call(Node, heart, set_callback, [M2,F3]), + receive {nodedown, Node} -> ok + after 5000 -> ct:fail(node_not_killed) + end, + stop_node(Node), + ok. + +options_api(Config) when is_list(Config) -> + {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME), + none = rpc:call(Node, heart, get_options, []), + M0 = self(), + F0 = ok, + {error, {bad_options, {M0,F0}}} = rpc:call(Node, heart, set_options, [{M0,F0}]), + none = rpc:call(Node, heart, get_options, []), + Ls = lists:duplicate(28, $b), + {error, {bad_options, Ls}} = rpc:call(Node, heart, set_options, [Ls]), + none = rpc:call(Node, heart, get_options, []), + + ok = rpc:call(Node, heart, set_options, [[check_schedulers]]), + {ok, [check_schedulers]} = rpc:call(Node, heart, get_options, []), + ok = rpc:call(Node, heart, set_options, [[]]), + none = rpc:call(Node, heart, get_options, []), + + ok = rpc:call(Node, heart, set_options, [[check_schedulers]]), + {ok, [check_schedulers]} = rpc:call(Node, heart, get_options, []), + {error, {bad_options, Ls}} = rpc:call(Node, heart, set_options, [Ls]), + {ok, [check_schedulers]} = rpc:call(Node, heart, get_options, []), + + receive after 3000 -> ok end, %% wait 3 secs + + ok = rpc:call(Node, heart, set_options, [[]]), + none = rpc:call(Node, heart, get_options, []), + stop_node(Node), + ok. + + %%% Removed as it may crash epmd/distribution in colourful %%% ways. While we ARE finding out WHY, it would %%% be nice for others to be able to run the kernel test suite -%%% without "exploding machines", so thats why I removed it for now. - []; -dont_drop(doc) -> - ["Tests that the heart command does not get dropped when ", - "set just before halt on very high I/O load."]; +%%% without "exploding machines", so that's why I removed it for now. + +%% Tests that the heart command does not get dropped when +%% set just before halt on very high I/O load.. dont_drop(Config) when is_list(Config) -> %%% Have to do it some times to make it happen... [ok,ok,ok,ok,ok,ok,ok,ok,ok,ok] = do_dont_drop(Config,10), @@ -395,7 +450,7 @@ do_dont_drop(Config,N) -> Env = [{"HEART_COMMAND", FirstCmd}], Func = "start_heart_stress", Arg = NN3 ++ "@" ++ Host ++ " " ++ - filename:join(?config(data_dir, Config), "simple_echo"), + filename:join(proplists:get_value(data_dir, Config), "simple_echo"), start_node_run(Name,Env,Func,Arg), case wait_for_any_of(list_to_atom(NN2 ++ "@" ++ Host), list_to_atom(NN3 ++ "@" ++ Host)) of @@ -428,16 +483,13 @@ wait_for_any_of(N1,N2,Times) -> end. -kill_pid(suite) -> - []; -kill_pid(doc) -> - ["Tests that heart kills the old erlang node before executing ", - "heart command."]; +%% Tests that heart kills the old erlang node before executing +%% heart command. kill_pid(Config) when is_list(Config) -> ok = do_kill_pid(Config). do_kill_pid(_Config) -> - Name = heart_test, + Name = ?UNIQ_NODE_NAME, Env = [{"HEART_COMMAND", "nickeNyfikenFarEttJobb"}], {ok,Node} = start_node_run(Name,Env,suicide_by_heart,[]), ok = wait_for_node(Node,15), @@ -447,6 +499,30 @@ do_kill_pid(_Config) -> false end. + +heart_no_kill(suite) -> + []; +heart_no_kill(doc) -> + ["Tests that heart doesn't kill the old erlang node when ", + "HEART_NO_KILL is set."]; +heart_no_kill(Config) when is_list(Config) -> + ok = do_no_kill(Config). + +do_no_kill(_Config) -> + Name = heart_test, + {ok,Node} = start_node_run(Name,[],non_suicide_by_heart,[]), + io:format("Node is ~p~n", [Node]), + ok = wait_for_node(Node,15), + io:format("wait_for_node is ~p~n", [ok]), + erlang:monitor_node(Node, true), + receive {nodedown,Node} -> false + after 30000 -> + io:format("Node didn't die..\n"), + rpc:call(Node,init,stop,[]), + io:format("done init:stop..\n"), + ok + end. + wait_for_node(_,0) -> false; wait_for_node(Node,N) -> @@ -565,6 +641,20 @@ suicide_by_heart() -> sallad end. +non_suicide_by_heart() -> + P = open_port({spawn,"heart -ht 11 -pid "++os:getpid()}, + [exit_status, {env, [{"HEART_NO_KILL", "TRUE"}]}, + {packet,2}]), + receive X -> X end, + %% Just hang and wait for heart to timeout + receive + {P,{exit_status,_}} -> + ok + after + 20000 -> + exit(timeout) + end. + %% generate a module from binary generate(Module, Attributes, FunStrings) -> diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl index db61c4003b..fde65bf5c4 100644 --- a/lib/kernel/test/ignore_cores.erl +++ b/lib/kernel/test/ignore_cores.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. 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,7 +28,7 @@ -module(ignore_cores). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]). @@ -53,7 +53,7 @@ init(Config) -> fini(Config) -> #ignore_cores{org_cwd = OrgCWD, org_path = OrgPath, - org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config), ok = file:set_cwd(OrgCWD), true = code:set_path(OrgPath), case OrgPWD of @@ -70,10 +70,10 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite), is_list(Config) -> #ignore_cores{org_cwd = OrgCWD, org_path = OrgPath, - org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config), Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath), true = code:set_path(Path), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), IgnDir = filename:join([PrivDir, atom_to_list(Suite) ++ "_" @@ -94,7 +94,7 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite), end, ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>), %% cores are dumped in /cores on MacOS X - CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of + CoresDir = case {test_server:os_type(), filelib:is_dir("/cores")} of {{unix,darwin}, true} -> filelib:fold_files("/cores", "^core.*$", @@ -119,7 +119,7 @@ restore(Config) -> org_path = OrgPath, org_pwd_env = OrgPWD, ign_dir = IgnDir, - cores_dir = CoresDir} = ?config(ignore_cores, Config), + cores_dir = CoresDir} = proplists:get_value(ignore_cores, Config), try case CoresDir of false -> @@ -155,5 +155,5 @@ restore(Config) -> dir(Config) -> - #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config), + #ignore_cores{ign_dir = Dir} = proplists:get_value(ignore_cores, Config), Dir. diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index 5ba06bb032..ba0d075ef2 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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. @@ -19,7 +19,7 @@ %% -module(inet_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/src/inet_dns.hrl"). @@ -40,13 +40,16 @@ lookup_bad_search_option/1, getif/1, getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1, - parse_strict_address/1, simple_netns/1, simple_netns_open/1]). + parse_strict_address/1, simple_netns/1, simple_netns_open/1, + simple_bind_to_device/1, simple_bind_to_device_open/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0, test_netns/0]). -export([init_per_testcase/2, end_per_testcase/2]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [t_gethostbyaddr, t_gethostbyname, t_getaddr, @@ -56,7 +59,8 @@ all() -> gethostnative_debug_level, gethostnative_soft_restart, lookup_bad_search_option, getif, getif_ifr_name_overflow, getservbyname_overflow, - getifaddrs, parse_strict_address, simple_netns, simple_netns_open]. + getifaddrs, parse_strict_address, simple_netns, simple_netns_open, + simple_bind_to_device, simple_bind_to_device_open]. groups() -> [{parse, [], [parse_hosts, parse_address]}]. @@ -97,35 +101,30 @@ init_per_testcase(lookup_bad_search_option, Config) -> Prev = ets:lookup(Db, Key), ets:delete(Db, Key), ets:insert(Db, {Key,[lookup_bad_search_option]}), - ?t:format("Misconfigured resolver lookup order", []), - Dog = test_server:timetrap(test_server:seconds(60)), - [{Key,Prev},{watchdog,Dog}|Config]; + io:format("Misconfigured resolver lookup order", []), + [{Key,Prev}|Config]; init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(60)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(lookup_bad_search_option, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), Db = inet_db, Key = res_lookup, - Prev = ?config(Key, Config), + Prev = proplists:get_value(Key, Config), ets:delete(Db, Key), ets:insert(Db, Prev), - ?t:format("Restored resolver lookup order", []); -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). + io:format("Restored resolver lookup order", []); +end_per_testcase(_Func, _Config) -> + ok. t_gethostbyaddr() -> required(v4). -t_gethostbyaddr(doc) -> "Test the inet:gethostbyaddr/1 function."; +%% Test the inet:gethostbyaddr/1 function. t_gethostbyaddr(Config) when is_list(Config) -> {Name,FullName,IPStr,{A,B,C,D}=IP,Aliases,_,_} = ct:get_config(test_host_ipv4_only), Rname = integer_to_list(D) ++ "." ++ - integer_to_list(C) ++ "." ++ - integer_to_list(B) ++ "." ++ - integer_to_list(A) ++ ".in-addr.arpa", + integer_to_list(C) ++ "." ++ + integer_to_list(B) ++ "." ++ + integer_to_list(A) ++ ".in-addr.arpa", {ok,HEnt} = inet:gethostbyaddr(IPStr), {ok,HEnt} = inet:gethostbyaddr(IP), {error,Error} = inet:gethostbyaddr(Name), @@ -142,11 +141,13 @@ t_gethostbyaddr(Config) when is_list(Config) -> ok; _ -> io:format("alias list: ~p", [HEnt#hostent.h_aliases]), - io:format("check alias list: ~p", [[Aliases,[Rname]]]), + io:format( + "check alias list: ~p", [[Aliases,tl(Aliases),[Rname]]]), io:format("name: ~p", [HEnt#hostent.h_name]), io:format("check name: ~p", [[Name,FullName]]), - check_elems([{HEnt#hostent.h_name,[Name,FullName]}, - {HEnt#hostent.h_aliases,[[],Aliases,[Rname]]}]) + check_elems( + [{HEnt#hostent.h_name,[Name,FullName]}, + {HEnt#hostent.h_aliases,[[],Aliases,tl(Aliases),[Rname]]}]) end, {_DName, _DFullName, DIPStr, DIP, _, _, _} = ct:get_config(test_dummy_host), @@ -155,79 +156,78 @@ t_gethostbyaddr(Config) when is_list(Config) -> ok. t_gethostbyaddr_v6() -> required(v6). -t_gethostbyaddr_v6(doc) -> "Test the inet:gethostbyaddr/1 inet6 function."; +%% Test the inet:gethostbyaddr/1 inet6 function. t_gethostbyaddr_v6(Config) when is_list(Config) -> - ?line {Name6, FullName6, IPStr6, IP6, Aliases6} = + {Name6, FullName6, IPStr6, IP6, Aliases6} = ct:get_config(test_host_ipv6_only), - ?line case inet:gethostbyaddr(IPStr6) of + case inet:gethostbyaddr(IPStr6) of %% Even if IPv6 is not supported, the native resolver may succeed %% looking up the host. DNS lookup will probably fail. {error,nxdomain} -> {skip, "IPv6 test fails! IPv6 not supported on this host!?"}; {ok,HEnt6} -> - ?line {ok,HEnt6} = inet:gethostbyaddr(IP6), - ?line {error,Error6} = inet:gethostbyaddr(Name6), - ?line ok = io:format("Failure reason: ~p: ~s", - [Error6, inet:format_error(Error6)]), - ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6, - h_length = 16, - h_addr_list = [IP6]}, - ?line HEnt6_ = HEnt6, - ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]}, - {HEnt6#hostent.h_aliases,[[],Aliases6]}]), - - ?line {_DName6, _DFullName6, DIPStr6, DIP6, _} = - ct:get_config(test_dummy_ipv6_host), - ?line {error,nxdomain} = inet:gethostbyaddr(DIPStr6), - ?line {error,nxdomain} = inet:gethostbyaddr(DIP6), + {ok,HEnt6} = inet:gethostbyaddr(IP6), + {error,Error6} = inet:gethostbyaddr(Name6), + ok = io:format("Failure reason: ~p: ~s", + [Error6, inet:format_error(Error6)]), + HEnt6_ = HEnt6#hostent{h_addrtype = inet6, + h_length = 16, + h_addr_list = [IP6]}, + HEnt6_ = HEnt6, + check_elems( + [{HEnt6#hostent.h_name,[Name6,FullName6]}, + {HEnt6#hostent.h_aliases,[[],Aliases6,tl(Aliases6)]}]), + + {_DName6, _DFullName6, DIPStr6, DIP6, _} = + ct:get_config(test_dummy_ipv6_host), + {error,nxdomain} = inet:gethostbyaddr(DIPStr6), + {error,nxdomain} = inet:gethostbyaddr(DIP6), ok end. t_gethostbyname() -> required(v4). -t_gethostbyname(doc) -> "Test the inet:gethostbyname/1 function."; -t_gethostbyname(suite) -> []; +%% Test the inet:gethostbyname/1 function. t_gethostbyname(Config) when is_list(Config) -> - ?line {Name,FullName,IPStr,IP,Aliases,IP_46_Str,_} = + {Name,FullName,IPStr,IP,Aliases,IP_46_Str,_} = ct:get_config(test_host_ipv4_only), - ?line {ok,_} = inet:gethostbyname(IPStr), - ?line {ok,HEnt} = inet:gethostbyname(Name), - ?line {ok,HEnt} = inet:gethostbyname(list_to_atom(Name)), - ?line HEnt_ = HEnt#hostent{h_addrtype = inet, - h_length = 4, - h_addr_list = [IP]}, - - ?line HEnt_ = HEnt, - ?line check_elems([{HEnt#hostent.h_name,[Name,FullName]}, - {HEnt#hostent.h_aliases,[[],Aliases]}]), - ?line {ok,HEntF} = inet:gethostbyname(FullName), - ?line HEntF_ = HEntF#hostent{h_name = FullName, - h_addrtype = inet, - h_length = 4, - h_addr_list = [IP]}, - ?line HEntF_ = HEntF, - ?line check_elems([{HEnt#hostent.h_aliases,[[],Aliases]}]), + {ok,_} = inet:gethostbyname(IPStr), + {ok,HEnt} = inet:gethostbyname(Name), + {ok,HEnt} = inet:gethostbyname(list_to_atom(Name)), + HEnt_ = HEnt#hostent{h_addrtype = inet, + h_length = 4, + h_addr_list = [IP]}, + + HEnt_ = HEnt, + check_elems([{HEnt#hostent.h_name,[Name,FullName]}, + {HEnt#hostent.h_aliases,[[],Aliases,tl(Aliases)]}]), + {ok,HEntF} = inet:gethostbyname(FullName), + HEntF_ = HEntF#hostent{h_name = FullName, + h_addrtype = inet, + h_length = 4, + h_addr_list = [IP]}, + HEntF_ = HEntF, + check_elems([{HEnt#hostent.h_aliases,[[],Aliases,tl(Aliases)]}]), %% - ?line FullNameU = toupper(FullName), - ?line {ok,HEntU} = inet:gethostbyname(FullNameU), - ?line FullNameU = toupper(HEntU#hostent.h_name), - ?line #hostent{ + FullNameU = toupper(FullName), + {ok,HEntU} = inet:gethostbyname(FullNameU), + FullNameU = toupper(HEntU#hostent.h_name), + #hostent{ h_addrtype = inet, h_length = 4, h_addr_list = [IP]} = HEntU, - ?line check_elems( - [{[toupper(H) || H <- HEntU#hostent.h_aliases], - [[],[toupper(A) || A <- Aliases]]}]), + check_elems( + [{[toupper(H) || H <- HEntU#hostent.h_aliases], + [[],[toupper(A) || A <- Aliases]]}]), - ?line {DName, _DFullName, _DIPStr, _DIP, _, _, _} = + {DName, _DFullName, _DIPStr, _DIP, _, _, _} = ct:get_config(test_dummy_host), - ?line {error,nxdomain} = inet:gethostbyname(DName), - ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str), + {error,nxdomain} = inet:gethostbyname(DName), + {error,nxdomain} = inet:gethostbyname(IP_46_Str), ok. t_gethostbyname_v6() -> required(v6). -t_gethostbyname_v6(doc) -> "Test the inet:gethostbyname/1 inet6 function."; -t_gethostbyname_v6(suite) -> []; +%% Test the inet:gethostbyname/1 inet6 function. t_gethostbyname_v6(Config) when is_list(Config) -> {Name, FullName, IPStr, IP, Aliases} = ct:get_config(test_host_ipv6_only), @@ -242,7 +242,7 @@ t_gethostbyname_v6(Config) when is_list(Config) -> h_length = 16} = HEnt, check_elems( [{HEnt#hostent.h_name,[Name,FullName]}, - {HEnt#hostent.h_aliases,[[],Aliases]}]); + {HEnt#hostent.h_aliases,[[],Aliases,tl(Aliases)]}]); [IP46] -> % IPv4 compatible address {ok,HEnt4} = inet:gethostbyname(Name, inet), #hostent{h_addrtype = inet, @@ -262,7 +262,7 @@ t_gethostbyname_v6(Config) when is_list(Config) -> h_addrtype = inet6, h_length = 16} = HEntF, check_elems( - [{HEnt#hostent.h_aliases,[[],Aliases]}]); + [{HEnt#hostent.h_aliases,[[],Aliases,tl(Aliases)]}]); [IP46F] -> % IPv4 compatible address {ok,HEnt4F} = inet:gethostbyname(FullName, inet), #hostent{h_addrtype = inet, @@ -287,33 +287,31 @@ check_elem(Val, [Val|_], _) -> ok; check_elem(Val, [_|Tests], Tests0) -> check_elem(Val, Tests, Tests0); check_elem(Val, [], Tests0) -> - ?t:fail({no_match,Val,Tests0}). + ct:fail({no_match,Val,Tests0}). t_getaddr() -> required(v4). -t_getaddr(doc) -> "Test the inet:getaddr/2 function."; -t_getaddr(suite) -> []; +%% Test the inet:getaddr/2 function. t_getaddr(Config) when is_list(Config) -> - ?line {Name,FullName,IPStr,IP,_,IP_46_Str,IP46} = + {Name,FullName,IPStr,IP,_,IP_46_Str,IP46} = ct:get_config(test_host_ipv4_only), - ?line {ok,IP} = inet:getaddr(list_to_atom(Name), inet), - ?line {ok,IP} = inet:getaddr(Name, inet), - ?line {ok,IP} = inet:getaddr(FullName, inet), - ?line {ok,IP} = inet:getaddr(IP, inet), - ?line {ok,IP} = inet:getaddr(IPStr, inet), - ?line {error,nxdomain} = inet:getaddr(IP_46_Str, inet), - ?line {error,eafnosupport} = inet:getaddr(IP46, inet), - - ?line {DName, DFullName, DIPStr, DIP, _, _, _} = ct:get_config(test_dummy_host), - ?line {error,nxdomain} = inet:getaddr(DName, inet), - ?line {error,nxdomain} = inet:getaddr(DFullName, inet), - ?line {ok,DIP} = inet:getaddr(DIPStr, inet), - ?line {ok,DIP} = inet:getaddr(DIP, inet), + {ok,IP} = inet:getaddr(list_to_atom(Name), inet), + {ok,IP} = inet:getaddr(Name, inet), + {ok,IP} = inet:getaddr(FullName, inet), + {ok,IP} = inet:getaddr(IP, inet), + {ok,IP} = inet:getaddr(IPStr, inet), + {error,nxdomain} = inet:getaddr(IP_46_Str, inet), + {error,eafnosupport} = inet:getaddr(IP46, inet), + + {DName, DFullName, DIPStr, DIP, _, _, _} = ct:get_config(test_dummy_host), + {error,nxdomain} = inet:getaddr(DName, inet), + {error,nxdomain} = inet:getaddr(DFullName, inet), + {ok,DIP} = inet:getaddr(DIPStr, inet), + {ok,DIP} = inet:getaddr(DIP, inet), ok. t_getaddr_v6() -> required(v4) ++ required(v6). -t_getaddr_v6(doc) -> "Test the inet:getaddr/2 function."; -t_getaddr_v6(suite) -> []; +%% Test the inet:getaddr/2 function. t_getaddr_v6(Config) when is_list(Config) -> {Name,FullName,IPStr,IP,_} = ct:get_config(test_host_ipv6_only), @@ -341,16 +339,15 @@ t_getaddr_v6(Config) when is_list(Config) -> end. ipv4_to_ipv6() -> required(v4). -ipv4_to_ipv6(doc) -> "Test if IPv4 address is converted to IPv6 address."; -ipv4_to_ipv6(suite) -> []; +%% Test if IPv4 address is converted to IPv6 address. ipv4_to_ipv6(Config) when is_list(Config) -> %% Test what happens if an IPv4 address is looked up in an IPv6 context. %% If the native resolver succeeds to look it up, an IPv4 compatible %% address should be returned. If no IPv6 support on this host, an %% error should beturned. - ?line {_Name,_FullName,IPStr,_IP,Aliases,IP_46_Str,IP_46} = + {_Name,_FullName,IPStr,_IP,Aliases,IP_46_Str,IP_46} = ct:get_config(test_host_ipv4_only), - ?line IP4to6Res = + IP4to6Res = case inet:getaddr(IPStr, inet6) of {ok,IP_46} -> io:format("IPv4->IPv6: success~n"), @@ -362,36 +359,34 @@ ipv4_to_ipv6(Config) when is_list(Config) -> io:format("IPv6->IPv4: eafnosupport~n"), E; Other -> - ?line ?t:fail({ipv4_to_ipv6_lookup_failed,Other}) + ct:fail({ipv4_to_ipv6_lookup_failed,Other}) end, - ?line case {IP4to6Res,inet:gethostbyname(IPStr, inet6)} of - {true,{ok,HEnt}} -> - ?line HEnt_ = HEnt#hostent{h_addrtype = inet6, - h_length = 16, - h_addr_list = [IP_46]}, - ?line HEnt_ = HEnt, - ?line check_elems([{HEnt#hostent.h_name,[IP_46_Str,IPStr]}, - {HEnt#hostent.h_aliases,[[],Aliases]}]); - {_,IP4to6Res} -> ok - end, + case {IP4to6Res,inet:gethostbyname(IPStr, inet6)} of + {true,{ok,HEnt}} -> + HEnt_ = HEnt#hostent{h_addrtype = inet6, + h_length = 16, + h_addr_list = [IP_46]}, + HEnt_ = HEnt, + check_elems([{HEnt#hostent.h_name,[IP_46_Str,IPStr]}, + {HEnt#hostent.h_aliases,[[],Aliases,tl(Aliases)]}]); + {_,IP4to6Res} -> ok + end, ok. -host_and_addr() -> required(hosts). -host_and_addr(doc) -> ["Test looking up hosts and addresses. Use 'ypcat hosts' ", - "or the local eqivalent to find all hosts."]; -host_and_addr(suite) -> []; -host_and_addr(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(5)), +host_and_addr() -> + [{timetrap,{minutes,5}}|required(hosts)]. - ?line lists:foreach(fun try_host/1, get_hosts(Config)), - ?line test_server:timetrap_cancel(Dog), +%% Test looking up hosts and addresses. Use 'ypcat hosts' +%% or the local eqivalent to find all hosts. +host_and_addr(Config) when is_list(Config) -> + lists:foreach(fun try_host/1, get_hosts(Config)), ok. try_host({Ip0, Host}) -> - ?line {ok,Ip} = inet:getaddr(Ip0, inet), - ?line {ok,{hostent, _, _, inet, _, Ips1}} = inet:gethostbyaddr(Ip), - ?line {ok,{hostent, _, _, inet, _, _Ips2}} = inet:gethostbyname(Host), - ?line true = lists:member(Ip, Ips1), + {ok,Ip} = inet:getaddr(Ip0, inet), + {ok,{hostent, _, _, inet, _, Ips1}} = inet:gethostbyaddr(Ip), + {ok,{hostent, _, _, inet, _, _Ips2}} = inet:gethostbyname(Host), + true = lists:member(Ip, Ips1), ok. %% Get all hosts from the system using 'ypcat hosts' or the local @@ -438,105 +433,139 @@ get_hosts([C|Rest], Cur, Ip, Result) -> get_hosts(Rest, [C|Cur], Ip, Result); get_hosts([], _, _, Result) -> Result. - + parse_hosts(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line HostFile = filename:join(DataDir, "hosts"), - ?line inet_parse:hosts(HostFile), - ?line HostFileErr1 = filename:join(DataDir, "hosts_err1"), - ?line inet_parse:hosts(HostFileErr1), - ?line Resolv = filename:join(DataDir,"resolv.conf"), - ?line inet_parse:resolv(Resolv), - ?line ResolvErr1 = filename:join(DataDir,"resolv.conf.err1"), - ?line inet_parse:resolv(ResolvErr1). + DataDir = proplists:get_value(data_dir,Config), + HostFile = filename:join(DataDir, "hosts"), + inet_parse:hosts(HostFile), + HostFileErr1 = filename:join(DataDir, "hosts_err1"), + inet_parse:hosts(HostFileErr1), + Resolv = filename:join(DataDir,"resolv.conf"), + inet_parse:resolv(Resolv), + ResolvErr1 = filename:join(DataDir,"resolv.conf.err1"), + inet_parse:resolv(ResolvErr1). parse_address(Config) when is_list(Config) -> - V4Strict = + V4Reversable = [{{0,0,0,0},"0.0.0.0"}, - {{1,2,3,4},"1.2.3.4"}, + {{1,2,3,4},"1.2.3.4"}, {{253,252,251,250},"253.252.251.250"}, {{1,2,255,254},"1.2.255.254"}], - V6Strict = + V6Reversable = [{{0,0,0,0,0,0,0,0},"::"}, + {{0,0,0,0,0,0,0,1},"::1"}, + {{0,0,0,0,0,0,0,2},"::0.0.0.2"}, {{15,0,0,0,0,0,0,2},"f::2"}, - {{15,16#f11,0,0,0,0,256,2},"f:f11::0100:2"}, - {{0,0,0,0,0,0,0,16#17},"::17"}, - {{16#700,0,0,0,0,0,0,0},"0700::"}, - {{0,0,0,0,0,0,2,1},"::2:1"}, + {{15,16#f11,0,0,0,0,256,2},"f:f11::100:2"}, + {{16#700,0,0,0,0,0,0,0},"700::"}, + {{0,0,0,0,0,0,2,1},"::0.2.0.1"}, {{0,0,0,0,0,3,2,1},"::3:2:1"}, {{0,0,0,0,4,3,2,1},"::4:3:2:1"}, {{0,0,0,5,4,3,2,1},"::5:4:3:2:1"}, {{0,0,6,5,4,3,2,1},"::6:5:4:3:2:1"}, - {{0,7,6,5,4,3,2,1},"::7:6:5:4:3:2:1"}, + {{0,7,6,5,4,3,2,1},"0:7:6:5:4:3:2:1"}, {{7,0,0,0,0,0,0,0},"7::"}, {{7,6,0,0,0,0,0,0},"7:6::"}, {{7,6,5,0,0,0,0,0},"7:6:5::"}, {{7,6,5,4,0,0,0,0},"7:6:5:4::"}, {{7,6,5,4,3,0,0,0},"7:6:5:4:3::"}, {{7,6,5,4,3,2,0,0},"7:6:5:4:3:2::"}, - {{7,6,5,4,3,2,1,0},"7:6:5:4:3:2:1::"}, + {{7,6,5,4,3,2,1,0},"7:6:5:4:3:2:1:0"}, + {{0,0,6,5,4,3,0,0},"::6:5:4:3:0:0"}, + {{0,0,6,5,4,0,0,0},"0:0:6:5:4::"}, + {{8,0,0,5,4,0,0,1},"8::5:4:0:0:1"}, + {{8,0,0,5,0,0,0,1},"8:0:0:5::1"}, + {{0,7,6,5,4,3,2,0},"0:7:6:5:4:3:2:0"}, + {{0,0,6,5,4,3,0,0},"::6:5:4:3:0:0"}, + {{0,0,0,5,4,0,0,0},"::5:4:0:0:0"}, + {{0,0,0,0,4,0,0,0},"::4:0:0:0"}, + {{0,0,0,5,0,0,0,0},"0:0:0:5::"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22:5c33:c440:55c0:c66c:77:0088"}, + "c11:c22:5c33:c440:55c0:c66c:77:88"}, + {{0,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, + "0:c22:5c33:c440:55c0:c66c:77:88"}, {{16#c11,0,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11::5c33:c440:55c0:c66c:77:0088"}, + "c11:0:5c33:c440:55c0:c66c:77:88"}, {{16#c11,16#c22,0,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22::c440:55c0:c66c:77:0088"}, + "c11:c22:0:c440:55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22:5c33::55c0:c66c:77:0088"}, + "c11:c22:5c33:0:55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,16#c66c,16#77,16#88}, - "c11:0c22:5c33:c440::c66c:77:0088"}, + "c11:c22:5c33:c440:0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,16#77,16#88}, - "c11:0c22:5c33:c440:55c0::77:0088"}, + "c11:c22:5c33:c440:55c0:0:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,0,16#88}, - "c11:0c22:5c33:c440:55c0:c66c::0088"}, + "c11:c22:5c33:c440:55c0:c66c:0:88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,0}, + "c11:c22:5c33:c440:55c0:c66c:77:0"}, + {{0,0,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, + "::5c33:c440:55c0:c66c:77:88"}, {{16#c11,0,0,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11::c440:55c0:c66c:77:0088"}, + "c11::c440:55c0:c66c:77:88"}, {{16#c11,16#c22,0,0,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22::55c0:c66c:77:0088"}, + "c11:c22::55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,0,16#c66c,16#77,16#88}, - "c11:0c22:5c33::c66c:77:0088"}, + "c11:c22:5c33::c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,0,16#77,16#88}, - "c11:0c22:5c33:c440::77:0088"}, + "c11:c22:5c33:c440::77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,0,16#88}, - "c11:0c22:5c33:c440:55c0::0088"}, + "c11:c22:5c33:c440:55c0::88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,0,0}, + "c11:c22:5c33:c440:55c0:c66c::"}, + {{0,0,0,16#c440,16#55c0,16#c66c,16#77,16#88}, + "::c440:55c0:c66c:77:88"}, {{16#c11,0,0,0,16#55c0,16#c66c,16#77,16#88}, - "c11::55c0:c66c:77:0088"}, + "c11::55c0:c66c:77:88"}, {{16#c11,16#c22,0,0,0,16#c66c,16#77,16#88}, - "c11:0c22::c66c:77:0088"}, + "c11:c22::c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,0,0,16#77,16#88}, - "c11:0c22:5c33::77:0088"}, + "c11:c22:5c33::77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,0,0,16#88}, - "c11:0c22:5c33:c440::0088"}, + "c11:c22:5c33:c440::88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,0,0}, + "c11:c22:5c33:c440:55c0::"}, + {{0,0,0,0,16#55c0,16#c66c,16#77,16#88}, + "::55c0:c66c:77:88"}, {{16#c11,0,0,0,0,16#c66c,16#77,16#88}, - "c11::c66c:77:0088"}, + "c11::c66c:77:88"}, {{16#c11,16#c22,0,0,0,0,16#77,16#88}, - "c11:0c22::77:0088"}, + "c11:c22::77:88"}, {{16#c11,16#c22,16#5c33,0,0,0,0,16#88}, - "c11:0c22:5c33::0088"}, + "c11:c22:5c33::88"}, + {{16#c11,16#c22,16#5c33,16#c440,0,0,0,0}, + "c11:c22:5c33:c440::"}, + {{0,0,0,0,0,16#c66c,16#77,16#88}, + "::c66c:77:88"}, {{16#c11,0,0,0,0,0,16#77,16#88}, - "c11::77:0088"}, + "c11::77:88"}, {{16#c11,16#c22,0,0,0,0,0,16#88}, - "c11:0c22::0088"}, - {{0,0,0,0,0,65535,258,65534},"::FFFF:1.2.255.254"}, + "c11:c22::88"}, + {{16#c11,16#c22,16#5c33,0,0,0,0,0}, + "c11:c22:5c33::"}, + {{0,0,0,0,0,65535,258,65534},"::ffff:1.2.255.254"}, + {{16#fe80,12345,0,0,0,0,0,16#12},"fe80::12%012345"}, {{16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff}, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"} - |[{{D2,0,0,0,0,P,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, - erlang:integer_to_list(D2, 16)++"::"++Q++S} - || {{D1,D2,D3,D4},S} <- V4Strict, - {P,Q} <- [{0,""},{16#17,"17:"},{16#ff0,"0ff0:"}]]], + |[{list_to_tuple(P++[(D1 bsl 8) bor D2,(D3 bsl 8) bor D4]), + Q++S} + || {{D1,D2,D3,D4},S} <- + tl(V4Reversable), + {P,Q} <- + [{[0,0,0,0,0,16#ffff],"::ffff:"}, + {[0,0,0,0,0,0],"::"}]]], V4Sloppy = [{{10,1,16#98,16#76},"10.0x019876"}, {{8#12,1,8#130,8#321},"012.01.054321"}, - {{255,255,255,255},"255.255.255.0377"}, - {{255,255,255,255},"0Xff.000000000377.0x0000ff.255"}, - {{255,255,255,255},"255.255.65535"}, - {{255,255,255,255},"255.0xFF.0177777"}, - {{255,255,255,255},"255.16777215"}, - {{255,255,255,255},"00377.0XFFFFFF"}, - {{255,255,255,255},"4294967295"}, - {{255,255,255,255},"0xffffffff"}, - {{255,255,255,255},"00000000000037777777777"}, + {{252,253,254,255},"252.253.254.0377"}, + {{252,253,254,255},"0Xfc.000000000375.0x0000fe.255"}, + {{252,253,254,255},"252.253.65279"}, + {{252,253,254,255},"252.0xFD.0177377"}, + {{252,253,254,255},"252.16645887"}, + {{252,253,254,255},"00374.0XFDFEFF"}, + {{252,253,254,255},"4244504319"}, + {{252,253,254,255},"0xfcfdfeff"}, + {{252,253,254,255},"00000000000037477377377"}, {{16#12,16#34,16#56,16#78},"0x12345678"}, {{16#12,16#34,16#56,16#78},"0x12.0x345678"}, {{16#12,16#34,16#56,16#78},"0x12.0X34.0x5678"}, @@ -548,8 +577,14 @@ parse_address(Config) when is_list(Config) -> {{0,0,0,0},"0.00.0.0"}, {{0,0,0,0},"0.0.000000000000.0"}], V6Sloppy = - [{{0,0,0,0,0,65535,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4},S} - || {{D1,D2,D3,D4},S} <- V4Strict++V4Sloppy], + [{{16#a,16#b,16#c,16#0,16#0,16#d,16#e,16#f},"A:B:C::d:e:f"}, + {{16#fe80,0,0,0,0,0,0,16#12},"fe80::12%XXXXXXX"}] + ++ + [{{P,0,0,0,0,D2,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, + Q++erlang:integer_to_list(D2, 16)++":"++S} + || {{D1,D2,D3,D4},S} <- V4Reversable, + {P,Q} <- + [{16#2001,"2001::"},{16#177,"177::"},{16#ff0,"Ff0::"}]], V4Err = ["0.256.0.1", "1.2.3.4.5", @@ -593,28 +628,36 @@ parse_address(Config) when is_list(Config) -> "fec0::fFfF:127.0.0.1."], t_parse_address (parse_ipv6_address, - V6Strict++V6Sloppy++V6Err++V4Err), + false, + V6Reversable++V6Sloppy++V6Err++V4Err), t_parse_address (parse_ipv6strict_address, - V6Strict++V6Err++V4Err++[S || {_,S} <- V6Sloppy]), + true, + V6Reversable++V6Err++V4Err), t_parse_address (parse_ipv4_address, - V4Strict++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Strict]), + false, + V4Reversable++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Reversable]), t_parse_address (parse_ipv4strict_address, - V4Strict++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Strict]). + true, + V4Reversable++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Reversable]). -t_parse_address(Func, []) -> +t_parse_address(Func, _Reversable, []) -> io:format("~p done.~n", [Func]), ok; -t_parse_address(Func, [{Addr,String}|L]) -> +t_parse_address(Func, Reversable, [{Addr,String}|L]) -> io:format("~p = ~p.~n", [Addr,String]), {ok,Addr} = inet:Func(String), - t_parse_address(Func, L); -t_parse_address(Func, [String|L]) -> + case Reversable of + true ->String = inet:ntoa(Addr); + false -> ok + end, + t_parse_address(Func, Reversable, L); +t_parse_address(Func, Reversable, [String|L]) -> io:format("~p.~n", [String]), {error,einval} = inet:Func(String), - t_parse_address(Func, L). + t_parse_address(Func, Reversable, L). parse_strict_address(Config) when is_list(Config) -> {ok, {127,0,0,1}} = @@ -624,42 +667,37 @@ parse_strict_address(Config) when is_list(Config) -> {ok, {3089,3106,23603,50240,0,0,119,136}} = inet:parse_strict_address("c11:0c22:5c33:c440::077:0088"). -t_gethostnative(suite) ->[]; -t_gethostnative(doc) ->[]; t_gethostnative(Config) when is_list(Config) -> -%% this will result in 26 bytes sent which causes problem in Windows -%% if the port-program has not assured stdin to be read in BINARY mode -%% OTP-2555 - ?line case inet_gethost_native:gethostbyname( - "a23456789012345678901234") of + %% this will result in 26 bytes sent which causes problem in Windows + %% if the port-program has not assured stdin to be read in BINARY mode + %% OTP-2555 + case inet_gethost_native:gethostbyname( + "a23456789012345678901234") of {error,notfound} -> - ?line ok; + ok; {error,no_data} -> - ?line ok + ok end. -gethostnative_parallell(suite) -> - []; -gethostnative_parallell(doc) -> - ["Check that the emulator survives crashes in gethost_native"]; +%% Check that the emulator survives crashes in gethost_native. gethostnative_parallell(Config) when is_list(Config) -> - ?line {ok,Hostname} = inet:gethostname(), - ?line {ok,_} = inet:gethostbyname(Hostname), + {ok,Hostname} = inet:gethostname(), + {ok,_} = inet:gethostbyname(Hostname), case whereis(inet_gethost_native) of Pid when is_pid(Pid) -> - ?line do_gethostnative_parallell(); + do_gethostnative_parallell(); _ -> - ?line {skipped, "Not running native gethostbyname"} + {skipped, "Not running native gethostbyname"} end. do_gethostnative_parallell() -> - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok,Node} = ?t:start_node(gethost_parallell, slave, - [{args, "-pa " ++ PA}]), - ?line ok = rpc:call(Node, ?MODULE, parallell_gethost, []), - ?line receive after 10000 -> ok end, - ?line pong = net_adm:ping(Node), - ?line ?t:stop_node(Node), + PA = filename:dirname(code:which(?MODULE)), + {ok,Node} = test_server:start_node(gethost_parallell, slave, + [{args, "-pa " ++ PA}]), + ok = rpc:call(Node, ?MODULE, parallell_gethost, []), + receive after 10000 -> ok end, + pong = net_adm:ping(Node), + test_server:stop_node(Node), ok. parallell_gethost() -> @@ -752,7 +790,7 @@ wait_for_gethost(N) -> %% This is what I call an exit tuple :) exit({inet,gethostbyname, returned, Otherwise, 'when', 'N','=',N,'and','hostname','=',Hostname,'and', - kill_gethost_n,'=',get(kill_gethost_n)}) + kill_gethost_n,'=',get(kill_gethost_n)}) end, case whereis(inet_gethost_native) of Pid when is_pid(Pid) -> @@ -764,23 +802,20 @@ wait_for_gethost(N) -> end, wait_for_gethost(N-1) end. - -cname_loop(suite) -> - []; -cname_loop(doc) -> - ["Check that the resolver handles a CNAME loop"]; + +%% Check that the resolver handles a CNAME loop. cname_loop(Config) when is_list(Config) -> %% getbyname (hostent_by_domain) - ?line ok = inet_db:add_rr("mydomain.com", in, ?S_CNAME, ttl, "mydomain.com"), - ?line {error,nxdomain} = inet_db:getbyname("mydomain.com", ?S_A), - ?line ok = inet_db:del_rr("mydomain.com", in, ?S_CNAME, "mydomain.com"), + ok = inet_db:add_rr("mydomain.com", in, ?S_CNAME, ttl, "mydomain.com"), + {error,nxdomain} = inet_db:getbyname("mydomain.com", ?S_A), + ok = inet_db:del_rr("mydomain.com", in, ?S_CNAME, "mydomain.com"), %% res_hostent_by_domain RR = #dns_rr{domain = "mydomain.com", class = in, type = ?S_CNAME, data = "mydomain.com"}, Rec = #dns_rec{anlist = [RR]}, - ?line {error,nxdomain} = inet_db:res_hostent_by_domain("mydomain.com", ?S_A, Rec), + {error,nxdomain} = inet_db:res_hostent_by_domain("mydomain.com", ?S_A, Rec), ok. @@ -795,80 +830,75 @@ cname_loop(Config) when is_list(Config) -> lookup_processes=20}). gethostnative_soft_restart() -> required(hosts). -gethostnative_soft_restart(suite) -> - []; -gethostnative_soft_restart(doc) -> - ["Check that no name lookups fails during soft restart " - "of inet_gethost_native"]; + +%% Check that no name lookups fails during soft restart +%% of inet_gethost_native. gethostnative_soft_restart(Config) when is_list(Config) -> - ?line gethostnative_control(Config, - #gethostnative_control{ - control_seq=[soft_restart]}). + gethostnative_control(Config, + #gethostnative_control{ + control_seq=[soft_restart]}). gethostnative_debug_level() -> required(hosts). -gethostnative_debug_level(suite) -> - []; -gethostnative_debug_level(doc) -> - ["Check that no name lookups fails during debug level change " - "of inet_gethost_native"]; + +%% Check that no name lookups fails during debug level change +%% of inet_gethost_native. gethostnative_debug_level(Config) when is_list(Config) -> - ?line gethostnative_control(Config, - #gethostnative_control{ - control_seq=[{debug_level,1}, - {debug_level,0}]}). + gethostnative_control(Config, + #gethostnative_control{ + control_seq=[{debug_level,1}, + {debug_level,0}]}). gethostnative_control(Config, Optrec) -> - ?line case inet_db:res_option(lookup) of - [native] -> - case whereis(inet_gethost_native) of - Pid when is_pid(Pid) -> - ?line gethostnative_control_1(Config, Optrec); - _ -> - ?line {skipped, "Not running native gethostbyname"} - end; - _ -> - ?line {skipped, "Native not only lookup metod"} - end. + case inet_db:res_option(lookup) of + [native] -> + case whereis(inet_gethost_native) of + Pid when is_pid(Pid) -> + gethostnative_control_1(Config, Optrec); + _ -> + {skipped, "Not running native gethostbyname"} + end; + _ -> + {skipped, "Native not only lookup metod"} + end. gethostnative_control_1(Config, #gethostnative_control{ - control_seq=Seq, - control_interval=Interval, - lookup_delay=Delay, - lookup_count=Cnt, - lookup_processes=N}) -> - ?line {ok, Hostname} = inet:gethostname(), - ?line {ok, _} = inet:gethostbyname(Hostname), - ?line Hosts = + control_seq=Seq, + control_interval=Interval, + lookup_delay=Delay, + lookup_count=Cnt, + lookup_processes=N}) -> + {ok, Hostname} = inet:gethostname(), + {ok, _} = inet:gethostbyname(Hostname), + Hosts = [Hostname|[H || {_,H} <- get_hosts(Config)] ++[H++D || H <- ["www.","www1.","www2.",""], D <- ["erlang.org","erlang.se"]] ++[H++"cslab.ericsson.net" || H <- ["morgoth.","hades.","styx."]]], %% Spawn some processes to do parallel lookups while %% I repeatedly do inet_gethost_native:control/1. - ?line TrapExit = process_flag(trap_exit, true), - ?line gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts), - ?line test_server:format( - "First intermission: now starting control sequence ~w\n", - [Seq]), - ?line erlang:display(first_intermission), - ?line gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts), - ?line erlang:display(second_intermission), - ?line test_server:format( - "Second intermission: now stopping control sequence ~w\n", - [Seq]), - ?line gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts), - ?line true = process_flag(trap_exit, TrapExit), - ?line ok. + TrapExit = process_flag(trap_exit, true), + gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts), + io:format( + "First intermission: now starting control sequence ~w\n", + [Seq]), + erlang:display(first_intermission), + gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts), + erlang:display(second_intermission), + io:format( + "Second intermission: now stopping control sequence ~w\n", + [Seq]), + gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts), + true = process_flag(trap_exit, TrapExit), + ok. gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts) -> - ?line Tag = make_ref(), - ?line Parent = self(), - ?line Lookupers = + Tag = make_ref(), + Parent = self(), + Lookupers = [spawn_link( fun () -> - random:seed(), lookup_loop(Hosts, Delay, Tag, Parent, Cnt, Hosts) end) || _ <- lists:seq(1, N)], @@ -878,7 +908,7 @@ gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts) -> gethostnative_control_3(Tag, Reason) -> receive {Tag,Error} -> - ?line gethostnative_control_3(Tag, Error) + gethostnative_control_3(Tag, Error) after 0 -> Reason end. @@ -893,27 +923,26 @@ control_loop([Op|Ops], Interval, Tag, Lookupers, Seq) -> Seq). control_loop_1(Op, Interval, Tag, Lookupers) -> - ?line - receive - {'EXIT',Pid,Reason} -> - ?line case Reason of - Tag -> % Done - ?line control_loop_1 - (Op, Interval, Tag, - lists:delete(Pid, Lookupers)); - _ -> - ?line io:format("Lookuper ~p died: ~p", - [Pid,Reason]), - ?line test_server:fail("Lookuper died") - end - after Interval -> - ?line if Op =/= undefined -> - ?line ok = inet_gethost_native:control(Op); - true -> - ?line ok - end, - ?line Lookupers - end. + receive + {'EXIT',Pid,Reason} -> + case Reason of + Tag -> % Done + control_loop_1 + (Op, Interval, Tag, + lists:delete(Pid, Lookupers)); + _ -> + io:format("Lookuper ~p died: ~p", + [Pid,Reason]), + ct:fail("Lookuper died") + end + after Interval -> + if Op =/= undefined -> + ok = inet_gethost_native:control(Op); + true -> + ok + end, + Lookupers + end. lookup_loop(_, _Delay, Tag, _Parent, 0, _Hosts) -> exit(Tag); @@ -924,21 +953,18 @@ lookup_loop([H|Hs], Delay, Tag, Parent, Cnt, Hosts) -> {ok,_Hent} -> ok; {error,nxdomain} -> ok; Error -> - ?line io:format("Name lookup error for ~p for ~p: ~p", - [self(),H,Error]), + io:format("Name lookup error for ~p for ~p: ~p", + [self(),H,Error]), Parent ! {Tag,Error} end, receive - after random:uniform(Delay) -> + after rand:uniform(Delay) -> lookup_loop(Hs, Delay, Tag, Parent, Cnt-1, Hosts) end. -lookup_bad_search_option(suite) -> - []; -lookup_bad_search_option(doc) -> - ["Test lookup with erroneously configured lookup option (OTP-12133)"]; +%% Test lookup with erroneously configured lookup option (OTP-12133). lookup_bad_search_option(Config) when is_list(Config) -> %% Manipulation of resolver config is done in init_per_testcase %% and end_per_testcase to ensure cleanup. @@ -948,24 +974,21 @@ lookup_bad_search_option(Config) when is_list(Config) -> -getif(suite) -> - []; -getif(doc) -> - ["Tests basic functionality of getiflist, getif, and ifget"]; +%% Tests basic functionality of getiflist, getif, and ifget. getif(Config) when is_list(Config) -> - ?line case os:type() of - {unix,Osname} -> - ?line do_getif(Osname); - {_,_} -> - {skip,"inet:getif/0 probably not supported"} - end. + case os:type() of + {unix,Osname} -> + do_getif(Osname); + {_,_} -> + {skip,"inet:getif/0 probably not supported"} + end. do_getif(Osname) -> - ?line {ok,Hostname} = inet:gethostname(), - ?line {ok,Address} = inet:getaddr(Hostname, inet), - ?line {ok,Loopback} = inet:getaddr("localhost", inet), - ?line {ok,Interfaces} = inet:getiflist(), - ?line HWAs = + {ok,Hostname} = inet:gethostname(), + {ok,Address} = inet:getaddr(Hostname, inet), + {ok,Loopback} = inet:getaddr("localhost", inet), + {ok,Interfaces} = inet:getiflist(), + HWAs = lists:sort( lists:foldl( fun (I, Acc) -> @@ -974,10 +997,10 @@ do_getif(Osname) -> {ok,[]} -> Acc end end, [], Interfaces)), - ?line io:format("HWAs = ~p~n", [HWAs]), - ?line (Osname =/= sunos) - andalso ((length(HWAs) > 0) orelse (?t:fail(no_HWAs))), - ?line Addresses = + io:format("HWAs = ~p~n", [HWAs]), + (Osname =/= sunos) + andalso ((length(HWAs) > 0) orelse (ct:fail(no_HWAs))), + Addresses = lists:sort( lists:foldl( fun (I, Acc) -> @@ -986,139 +1009,145 @@ do_getif(Osname) -> {ok,[]} -> Acc end end, [], Interfaces)), - ?line {ok,Getif} = inet:getif(), - ?line Addresses = lists:sort([A || {A,_,_} <- Getif]), - ?line true = ip_member(Address, Addresses), - ?line true = ip_member(Loopback, Addresses), - ?line ok. - -getif_ifr_name_overflow(doc) -> - "Test long interface names do not overrun buffer"; + {ok,Getif} = inet:getif(), + Addresses = lists:sort([A || {A,_,_} <- Getif]), + true = ip_member(Address, Addresses), + true = ip_member(Loopback, Addresses), + ok. + +%% Test long interface names do not overrun buffer. getif_ifr_name_overflow(Config) when is_list(Config) -> - ?line case os:type() of - {unix,Osname} -> - ?line do_getif_ifr_name_overflow(Osname); - {_,_} -> - {skip,"inet:ifget/2 probably not supported"} - end. + case os:type() of + {unix,Osname} -> + do_getif_ifr_name_overflow(Osname); + {_,_} -> + {skip,"inet:ifget/2 probably not supported"} + end. do_getif_ifr_name_overflow(_) -> %% emulator should not crash - ?line {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]), + {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]), ok. -getservbyname_overflow(doc) -> - "Test long service names do not overrun buffer"; +%% Test long service names do not overrun buffer. getservbyname_overflow(Config) when is_list(Config) -> %% emulator should not crash - ?line {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp), + {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp), ok. -getifaddrs(doc) -> - "Test inet:gifaddrs/0"; +%% Test inet:gifaddrs/0. getifaddrs(Config) when is_list (Config) -> - ?line {ok,IfAddrs} = inet:getifaddrs(), - ?line ?t:format("IfAddrs = ~p.~n", [IfAddrs]), - ?line - case - {os:type(), - [If || - {If,Opts} <- IfAddrs, - lists:keymember(hwaddr, 1, Opts)]} of - {{unix,sunos},[]} -> ok; - {OT,[]} -> - ?t:fail({should_have_hwaddr,OT}); - _ -> ok - end, - ?line Addrs = + {ok,IfAddrs} = inet:getifaddrs(), + io:format("IfAddrs = ~p.~n", [IfAddrs]), + case + {os:type(), + [If || + {If,Opts} <- IfAddrs, + lists:keymember(hwaddr, 1, Opts)]} of + {{unix,sunos},[]} -> ok; + {OT,[]} -> + ct:fail({should_have_hwaddr,OT}); + _ -> ok + end, + Addrs = [element(1, A) || A <- ifaddrs(IfAddrs)], - ?line ?t:format("Addrs = ~p.~n", [Addrs]), - ?line [check_addr(Addr) || Addr <- Addrs], + io:format("Addrs = ~p.~n", [Addrs]), + [check_addr(Addr) || Addr <- Addrs], ok. -check_addr(Addr) +check_addr({addr,Addr}) when tuple_size(Addr) =:= 8, element(1, Addr) band 16#FFC0 =:= 16#FE80 -> - ?line ?t:format("Addr: ~p link local; SKIPPED!~n", [Addr]), + io:format("Addr: ~p link local; SKIPPED!~n", [Addr]), ok; -check_addr(Addr) -> - ?line ?t:format("Addr: ~p.~n", [Addr]), - ?line Ping = "ping", - ?line Pong = "pong", - ?line {ok,L} = gen_tcp:listen(0, [{ip,Addr},{active,false}]), - ?line {ok,P} = inet:port(L), - ?line {ok,S1} = gen_tcp:connect(Addr, P, [{active,false}]), - ?line {ok,S2} = gen_tcp:accept(L), - ?line ok = gen_tcp:send(S2, Ping), - ?line {ok,Ping} = gen_tcp:recv(S1, length(Ping)), - ?line ok = gen_tcp:send(S1, Pong), - ?line ok = gen_tcp:close(S1), - ?line {ok,Pong} = gen_tcp:recv(S2, length(Pong)), - ?line ok = gen_tcp:close(S2), - ?line ok = gen_tcp:close(L), - ok. +check_addr({addr,Addr}) -> + io:format("Addr: ~p.~n", [Addr]), + Ping = "ping", + Pong = "pong", + {ok,L} = gen_tcp:listen(0, [{ip,Addr},{active,false}]), + {ok,P} = inet:port(L), + {ok,S1} = gen_tcp:connect(Addr, P, [{active,false}]), + {ok,S2} = gen_tcp:accept(L), + ok = gen_tcp:send(S2, Ping), + {ok,Ping} = gen_tcp:recv(S1, length(Ping)), + ok = gen_tcp:send(S1, Pong), + ok = gen_tcp:close(S1), + {ok,Pong} = gen_tcp:recv(S2, length(Pong)), + ok = gen_tcp:close(S2), + ok = gen_tcp:close(L). -record(ifopts, {name,flags,addrs=[],hwaddr}). ifaddrs([]) -> []; ifaddrs([{If,Opts}|IOs]) -> - ?line #ifopts{flags=Flags} = Ifopts = - check_ifopts(Opts, #ifopts{name=If}), - ?line case Flags =/= undefined andalso lists:member(up, Flags) of - true -> - Ifopts#ifopts.addrs; - false -> - [] - end++ifaddrs(IOs). - -check_ifopts([], #ifopts{name=If,flags=Flags,addrs=Raddrs}=Ifopts) -> + #ifopts{flags=F} = Ifopts = check_ifopts(Opts, #ifopts{name=If}), + case F of + {flags,Flags} -> + case lists:member(running, Flags) of + true -> Ifopts#ifopts.addrs; + false -> [] + end ++ ifaddrs(IOs); + undefined -> + ifaddrs(IOs) + end. + +check_ifopts([], #ifopts{flags=F,addrs=Raddrs}=Ifopts) -> Addrs = lists:reverse(Raddrs), R = Ifopts#ifopts{addrs=Addrs}, - ?t:format("~p.~n", [R]), + io:format("~p.~n", [R]), %% See how we did... - if is_list(Flags) -> ok; - true -> - ?t:fail({flags_undefined,If}) - end, + {flags,Flags} = F, case lists:member(broadcast, Flags) of true -> [case A of - {_,_,_} -> A; - {T,_} when tuple_size(T) =:= 8 -> A; - _ -> - ?t:fail({broaddr_missing,If,A}) + {{addr,_},{netmask,_},{broadaddr,_}} -> + A; + {{addr,T},{netmask,_}} when tuple_size(T) =:= 8 -> + A end || A <- Addrs]; false -> - [case A of {_,_} -> A; - _ -> - ?t:fail({should_have_netmask,If,A}) - end || A <- Addrs] + case lists:member(pointtopoint, Flags) of + true -> + [case A of + {{addr,_},{netmask,_},{dstaddr,_}} -> + A + end || A <- Addrs]; + false -> + [case A of + {{addr,_},{netmask,_}} -> + A + end || A <- Addrs] + end end, R; -check_ifopts([{flags,Flags}|Opts], #ifopts{flags=undefined}=Ifopts) -> - check_ifopts(Opts, Ifopts#ifopts{flags=Flags}); -check_ifopts([{flags,Fs}|Opts], #ifopts{flags=Flags}=Ifopts) -> - case Fs of +check_ifopts([{flags,_}=F|Opts], #ifopts{flags=undefined}=Ifopts) -> + check_ifopts(Opts, Ifopts#ifopts{flags=F}); +check_ifopts([{flags,_}=F|Opts], #ifopts{flags=Flags}=Ifopts) -> + case F of Flags -> - check_ifopts(Opts, Ifopts#ifopts{}); + check_ifopts(Opts, Ifopts); _ -> - ?t:fail({multiple_flags,Fs,Ifopts}) + ct:fail({multiple_flags,F,Ifopts}) end; check_ifopts( - [{addr,Addr},{netmask,Netmask},{broadaddr,Broadaddr}|Opts], + [{addr,_}=A,{netmask,_}=N,{dstaddr,_}=D|Opts], #ifopts{addrs=Addrs}=Ifopts) -> - check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask,Broadaddr}|Addrs]}); + check_ifopts(Opts, Ifopts#ifopts{addrs=[{A,N,D}|Addrs]}); check_ifopts( - [{addr,Addr},{netmask,Netmask}|Opts], + [{addr,_}=A,{netmask,_}=N,{broadaddr,_}=B|Opts], #ifopts{addrs=Addrs}=Ifopts) -> - check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask}|Addrs]}); -check_ifopts([{addr,Addr}|Opts], #ifopts{addrs=Addrs}=Ifopts) -> - check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr}|Addrs]}); -check_ifopts([{hwaddr,Hwaddr}|Opts], #ifopts{hwaddr=undefined}=Ifopts) + check_ifopts(Opts, Ifopts#ifopts{addrs=[{A,N,B}|Addrs]}); +check_ifopts( + [{addr,_}=A,{netmask,_}=N|Opts], + #ifopts{addrs=Addrs}=Ifopts) -> + check_ifopts(Opts, Ifopts#ifopts{addrs=[{A,N}|Addrs]}); +check_ifopts([{addr,_}=A|Opts], #ifopts{addrs=Addrs}=Ifopts) -> + check_ifopts(Opts, Ifopts#ifopts{addrs=[{A}|Addrs]}); +check_ifopts([{hwaddr,Hwaddr}=H|Opts], #ifopts{hwaddr=undefined}=Ifopts) when is_list(Hwaddr) -> - check_ifopts(Opts, Ifopts#ifopts{hwaddr=Hwaddr}); -check_ifopts([{hwaddr,HwAddr}|_], #ifopts{}=Ifopts) -> - ?t:fail({multiple_hwaddrs,HwAddr,Ifopts}). + check_ifopts(Opts, Ifopts#ifopts{hwaddr=H}); +check_ifopts([{hwaddr,_}=H|_], #ifopts{}=Ifopts) -> + ct:fail({multiple_hwaddrs,H,Ifopts}). %% Works just like lists:member/2, except that any {127,_,_,_} tuple %% matches any other {127,_,_,_}. We do this to handle Linux systems @@ -1152,9 +1181,13 @@ simple_netns(Config) when is_list(Config) -> jog_netns_opt(L), ok = gen_tcp:close(L), %% - {ok,S} = gen_sctp:open(), - jog_netns_opt(S), - ok = gen_sctp:close(S); + case gen_sctp:open() of + {ok,S} -> + jog_netns_opt(S), + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; {error,einval} -> {skip,"setns() not supported"} end. @@ -1168,24 +1201,28 @@ jog_netns_opt(S) -> ok. +%% Smoke test netns support. simple_netns_open(Config) when is_list(Config) -> + %% Note: {error,enoent} will be returned if the run-time executable + %% has support for netns, but /proc/self/ns/net is missing. case gen_udp:open(0, [binary,{netns,"/"},inet]) of {ok,U} -> ok = gen_udp:close(U); - {error,E1} when E1 =:= einval; E1 =:= eperm -> + {error,E1} when E1 =:= einval; E1 =:= eperm; E1 =:= enoent -> ok end, case gen_tcp:listen(0, [binary,{netns,"/"},inet]) of {ok,T} -> ok = gen_tcp:close(T); - {error,E2} when E2 =:= einval; E2 =:= eperm -> + {error,E2} when E2 =:= einval; E2 =:= eperm; E2 =:= enoent -> ok end, try gen_sctp:open(0, [binary,{netns,"/"},inet]) of {ok,S} -> ok = gen_sctp:close(S); {error,E3} - when E3 =:= einval; E3 =:= eperm; E3 =:= eprotonosupport -> + when E3 =:= einval; E3 =:= eperm; + E3 =:= enoent; E3 =:= eprotonosupport -> ok catch error:badarg -> @@ -1258,3 +1295,67 @@ cmd(CmdString) -> io:put_chars(["# ",CmdString,io_lib:nl()]), io:put_chars([os:cmd(CmdString++" ; echo ' =>' $?")]), ok. + +-define(CAP_NET_RAW, 13). %% from /usr/include/linux/capability.h + +can_bind_to_device({unix, linux}, {Major, _, _}) + when Major > 2 -> + Status = os:cmd("cat /proc/self/status | grep CapEff"), + [_, CapEffStr] = string:tokens(Status, [$\n, $\t]), + CapEff = list_to_integer(CapEffStr, 16), + if CapEff band (1 bsl ?CAP_NET_RAW) =/= 0 -> + ok; + true -> + {skip,"insufficient capabilities, CAP_NET_RAW not granted"} + end; +can_bind_to_device(_OS, _Version) -> + {skip,"socket option bind_to_device not supported on this OS or version"}. + +simple_bind_to_device(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0), + jog_bind_to_device_opt(U), + ok = gen_udp:close(U), + %% + {ok,L} = gen_tcp:listen(0, []), + jog_bind_to_device_opt(L), + ok = gen_tcp:close(L), + %% + case gen_sctp:open() of + {ok,S} -> + jog_bind_to_device_opt(S), + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +%% Smoke test bind_to_device support. +simple_bind_to_device_open(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_udp:close(U), + {ok,T} = gen_tcp:listen(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_tcp:close(T), + + case gen_sctp:open(0, [binary,{bind_to_device,<<"lo">>},inet]) of + {ok,S} -> + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +jog_bind_to_device_opt(S) -> + %% This is just jogging the option mechanics + ok = inet:setopts(S, [{bind_to_device,<<>>}]), + {ok,[{bind_to_device,<<>>}]} = inet:getopts(S, [bind_to_device]), + ok = inet:setopts(S, [{bind_to_device,<<"lo">>}]), + {ok,[{bind_to_device,<<"lo">>}]} = inet:getopts(S, [bind_to_device]), + ok. diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl index ace4ccb8bd..6691ad9c06 100644 --- a/lib/kernel/test/inet_res_SUITE.erl +++ b/lib/kernel/test/inet_res_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2016. 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,7 +20,6 @@ -module(inet_res_SUITE). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/src/inet_dns.hrl"). @@ -43,7 +42,24 @@ -define(RUN_NAMED, "run-named"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +%% This test suite use a script ?RUN_NAMED that tries to start +%% a temporary local nameserver BIND 8 or 9 that must be installed +%% on your machine. +%% +%% For example, on Ubuntu 14.04, as root: +%% apt-get install bind9 +%% Now, that is not enough since Apparmor will not allow +%% the nameserver daemon /usr/sbin/named to read from the test directory. +%% Assuming that you run tests in /ldisk/daily_build, and still on +%% Ubuntu 14.04, make /usr/apparmor.d/local/usr.sbin.named contain: +%% /ldisk/daily_build/** r, +%% And yes; the trailing comma must be there... + + + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [basic, resolve, edns0, txt_record, files_monitor, @@ -78,8 +94,8 @@ zone_dir(TC) -> end. init_per_testcase(Func, Config) -> - PrivDir = ?config(priv_dir, Config), - DataDir = ?config(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), try ns_init(zone_dir(Func), PrivDir, DataDir) of NsSpec -> Lookup = inet_db:res_option(lookup), @@ -89,29 +105,27 @@ init_per_testcase(Func, Config) -> inet_db:ins_alt_ns(IP, Port); _ -> ok end, - Dog = test_server:timetrap(test_server:seconds(20)), - [{nameserver,NsSpec},{res_lookup,Lookup},{watchdog,Dog}|Config] + [{nameserver,NsSpec},{res_lookup,Lookup}|Config] catch SkipReason -> {skip,SkipReason} end. end_per_testcase(_Func, Config) -> - test_server:timetrap_cancel(?config(watchdog, Config)), - inet_db:set_lookup(?config(res_lookup, Config)), - NsSpec = ?config(nameserver, Config), + inet_db:set_lookup(proplists:get_value(res_lookup, Config)), + NsSpec = proplists:get_value(nameserver, Config), case NsSpec of {_,{IP,Port},_} -> inet_db:del_alt_ns(IP, Port); _ -> ok end, - ns_end(NsSpec, ?config(priv_dir, Config)). + ns_end(NsSpec, proplists:get_value(priv_dir, Config)). %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Nameserver control ns(Config) -> - {_ZoneDir,NS,_P} = ?config(nameserver, Config), + {_ZoneDir,NS,_P} = proplists:get_value(nameserver, Config), NS. ns_init(ZoneDir, PrivDir, DataDir) -> @@ -120,7 +134,7 @@ ns_init(ZoneDir, PrivDir, DataDir) -> {unix,_} -> PortNum = case {os:type(),os:version()} of {{unix,solaris},{M,V,_}} when M =< 5, V < 10 -> - 11895 + random:uniform(100); + 11895 + rand:uniform(100); _ -> {ok,S} = gen_udp:open(0, [{reuseaddr,true}]), {ok,PNum} = inet:port(S), @@ -278,8 +292,7 @@ proxy_ns({proxy,_,_,ProxyNS}) -> ProxyNS. %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -basic(doc) -> - ["Lookup an A record with different API functions"]; +%% Lookup an A record with different API functions. basic(Config) when is_list(Config) -> NS = ns(Config), Name = "ns.otptest", @@ -341,8 +354,7 @@ basic(Config) when is_list(Config) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -resolve(doc) -> - ["Lookup different records using resolve/2..4"]; +%% Lookup different records using resolve/2..4. resolve(Config) when is_list(Config) -> Class = in, NS = ns(Config), @@ -472,8 +484,7 @@ check_msg(Class, Type, Msg, AnList, NsList) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -edns0(doc) -> - ["Test EDNS and truncation"]; +%% Test EDNS and truncation. edns0(Config) when is_list(Config) -> NS = ns(Config), Domain = "otptest", @@ -534,10 +545,7 @@ inet_res_filter(Anlist, Class, Type) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -txt_record(suite) -> - []; -txt_record(doc) -> - ["Tests TXT records"]; +%% Tests TXT records. txt_record(Config) when is_list(Config) -> D1 = "cslab.ericsson.net", D2 = "mail1.cslab.ericsson.net", @@ -556,10 +564,7 @@ txt_record(Config) when is_list(Config) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -files_monitor(suite) -> - []; -files_monitor(doc) -> - ["Tests monitoring of /etc/hosts and /etc/resolv.conf, but not them"]; +%% Tests monitoring of /etc/hosts and /etc/resolv.conf, but not them. files_monitor(Config) when is_list(Config) -> Search = inet_db:res_option(search), HostsFile = inet_db:res_option(hosts_file), @@ -574,7 +579,7 @@ files_monitor(Config) when is_list(Config) -> end. do_files_monitor(Config) -> - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), {ok,Hostname} = inet:gethostname(), io:format("Hostname = ~p.~n", [Hostname]), FQDN = @@ -648,8 +653,7 @@ do_files_monitor(Config) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -last_ms_answer(doc) -> - ["Answer just when timeout is triggered (OTP-9221)"]; +%% Answer just when timeout is triggered (OTP-9221). last_ms_answer(Config) when is_list(Config) -> NS = ns(Config), Name = "ns.otptest", diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named index d9befb352d..d67295773a 100755 --- a/lib/kernel/test/inet_res_SUITE_data/run-named +++ b/lib/kernel/test/inet_res_SUITE_data/run-named @@ -2,7 +2,7 @@ ## ## %CopyrightBegin% ## -## Copyright Ericsson AB 2009-2012. All Rights Reserved. +## Copyright Ericsson AB 2009-2016. 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/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 1262f36fae..ada9c2689c 100644 --- a/lib/kernel/test/inet_sockopt_SUITE.erl +++ b/lib/kernel/test/inet_sockopt_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2017. 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. @@ -19,7 +19,7 @@ %% -module(inet_sockopt_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(C_GET_IPPROTO_TCP,1). @@ -52,6 +52,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, simple/1, loop_all/1, simple_raw/1, simple_raw_getbin/1, + multiple_raw/1, multiple_raw_getbin/1, doc_examples_raw/1,doc_examples_raw_getbin/1, large_raw/1,large_raw_getbin/1,combined/1,combined_getbin/1, ipv6_v6only_udp/1, ipv6_v6only_tcp/1, ipv6_v6only_sctp/1, @@ -61,10 +62,13 @@ -export([init_per_testcase/2, end_per_testcase/2]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [simple, loop_all, simple_raw, simple_raw_getbin, + multiple_raw, multiple_raw_getbin, doc_examples_raw, doc_examples_raw_getbin, large_raw, large_raw_getbin, combined, combined_getbin, ipv6_v6only_udp, ipv6_v6only_tcp, ipv6_v6only_sctp, @@ -88,242 +92,311 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(60)), - [{watchdog,Dog}|Config]. + Config. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. -simple(suite) -> []; -simple(doc) -> "Test inet:setopt/getopt simple functionality."; +%% Test inet:setopt/getopt simple functionality. simple(Config) when is_list(Config) -> - ?line XOpt = case os:type() of - {unix,_} -> [{reuseaddr,true}]; - _ -> [] - end, - ?line Opt = [{nodelay,true}, - {keepalive,true},{packet,4}, - {active,false}|XOpt], - ?line OptTags = [X || {X,_} <- Opt], - ?line {S1,S2} = create_socketpair(Opt, Opt), - ?line {ok,Opt} = inet:getopts(S1,OptTags), - ?line {ok,Opt} = inet:getopts(S2,OptTags), - ?line COpt = [{X,case X of nodelay -> false;_ -> Y end} || {X,Y} <- Opt], - ?line inet:setopts(S1,COpt), - ?line {ok,COpt} = inet:getopts(S1,OptTags), - ?line {ok,Opt} = inet:getopts(S2,OptTags), - ?line gen_tcp:close(S1), - ?line gen_tcp:close(S2), + XOpt = case os:type() of + {unix,_} -> [{reuseaddr,true}]; + _ -> [] + end, + Opt = [{nodelay,true}, + {keepalive,true},{packet,4}, + {active,false}|XOpt], + OptTags = [X || {X,_} <- Opt], + {S1,S2} = create_socketpair(Opt, Opt), + {ok,Opt} = inet:getopts(S1,OptTags), + {ok,Opt} = inet:getopts(S2,OptTags), + COpt = [{X,case X of nodelay -> false;_ -> Y end} || {X,Y} <- Opt], + inet:setopts(S1,COpt), + {ok,COpt} = inet:getopts(S1,OptTags), + {ok,Opt} = inet:getopts(S2,OptTags), + gen_tcp:close(S1), + gen_tcp:close(S2), ok. -loop_all(suite) -> []; -loop_all(doc) -> "Loop through all socket options and check that they work"; +%% Loop through all socket options and check that they work. loop_all(Config) when is_list(Config) -> - ?line ListenFailures = + ListenFailures = lists:foldr(make_check_fun(listen,1),[],all_listen_options()), - ?line ConnectFailures = + ConnectFailures = lists:foldr(make_check_fun(connect,2),[],all_connect_options()), - ?line case ListenFailures++ConnectFailures of - [] -> - ?line ok; - Failed -> - ?line {comment,lists:flatten( - io_lib:format("Non mandatory failed:~w", - [Failed]))} - end. + case ListenFailures++ConnectFailures of + [] -> + ok; + Failed -> + {comment,lists:flatten( + io_lib:format("Non mandatory failed:~w", + [Failed]))} + end. -simple_raw(suite) -> []; -simple_raw(doc) -> "Test simple setopt/getopt of raw options."; +%% Test simple setopt/getopt of raw options. simple_raw(Config) when is_list(Config) -> do_simple_raw(Config,false). -simple_raw_getbin(suite) -> []; -simple_raw_getbin(doc) -> "Test simple setopt/getopt of raw options, " - "with binaries in getopt."; + +%% Test simple setopt/getopt of raw options, with binaries in getopt. simple_raw_getbin(Config) when is_list(Config) -> do_simple_raw(Config,true). do_simple_raw(Config,Binary) when is_list(Config) -> - ?line Port = start_helper(Config), - ?line SolSocket = ask_helper(Port,?C_GET_SOL_SOCKET), - ?line SoKeepAlive = ask_helper(Port,?C_GET_SO_KEEPALIVE), - ?line OptionTrue = {raw,SolSocket,SoKeepAlive,<<1:32/native>>}, - ?line OptionFalse = {raw,SolSocket,SoKeepAlive,<<0:32/native>>}, - ?line {S1,S2} = create_socketpair([OptionTrue],[{keepalive,true}]), - ?line {ok,[{keepalive,true}]} = inet:getopts(S1,[keepalive]), - ?line {ok,[{keepalive,true}]} = inet:getopts(S2,[keepalive]), - ?line {ok,[{raw,SolSocket,SoKeepAlive,X1B}]} = + Port = start_helper(Config), + SolSocket = ask_helper(Port,?C_GET_SOL_SOCKET), + SoKeepAlive = ask_helper(Port,?C_GET_SO_KEEPALIVE), + OptionTrue = {raw,SolSocket,SoKeepAlive,<<1:32/native>>}, + OptionFalse = {raw,SolSocket,SoKeepAlive,<<0:32/native>>}, + {S1,S2} = create_socketpair([OptionTrue],[{keepalive,true}]), + {ok,[{keepalive,true}]} = inet:getopts(S1,[keepalive]), + {ok,[{keepalive,true}]} = inet:getopts(S2,[keepalive]), + {ok,[{raw,SolSocket,SoKeepAlive,X1B}]} = inet:getopts(S1,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]), - ?line X1 = nintbin2int(X1B), - ?line {ok,[{raw,SolSocket,SoKeepAlive,X2B}]} = + X1 = nintbin2int(X1B), + {ok,[{raw,SolSocket,SoKeepAlive,X2B}]} = inet:getopts(S2,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]), - ?line X2 = nintbin2int(X2B), - ?line true = X1 > 0, - ?line true = X2 > 0, - ?line inet:setopts(S1,[{keepalive,false}]), - ?line inet:setopts(S2,[OptionFalse]), - ?line {ok,[{keepalive,false}]} = inet:getopts(S1,[keepalive]), - ?line {ok,[{keepalive,false}]} = inet:getopts(S2,[keepalive]), - ?line {ok,[{raw,SolSocket,SoKeepAlive,Y1B}]} = + X2 = nintbin2int(X2B), + true = X1 > 0, + true = X2 > 0, + inet:setopts(S1,[{keepalive,false}]), + inet:setopts(S2,[OptionFalse]), + {ok,[{keepalive,false}]} = inet:getopts(S1,[keepalive]), + {ok,[{keepalive,false}]} = inet:getopts(S2,[keepalive]), + {ok,[{raw,SolSocket,SoKeepAlive,Y1B}]} = inet:getopts(S1,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]), - ?line Y1 = nintbin2int(Y1B), - ?line {ok,[{raw,SolSocket,SoKeepAlive,Y2B}]} = + Y1 = nintbin2int(Y1B), + {ok,[{raw,SolSocket,SoKeepAlive,Y2B}]} = inet:getopts(S2,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]), - ?line Y2 = nintbin2int(Y2B), - ?line true = Y1 == 0, - ?line true = Y2 == 0, - ?line gen_tcp:close(S1), - ?line gen_tcp:close(S2), - ?line stop_helper(Port), + Y2 = nintbin2int(Y2B), + true = Y1 == 0, + true = Y2 == 0, + gen_tcp:close(S1), + gen_tcp:close(S2), + stop_helper(Port), ok. - + nintbin2int(<<Int:32/native>>) -> Int; nintbin2int(<<Int:24/native>>) -> Int; nintbin2int(<<Int:16/native>>) -> Int; nintbin2int(<<Int:8/native>>) -> Int; nintbin2int(<<>>) -> 0. -doc_examples_raw(suite) -> []; -doc_examples_raw(doc) -> "Test that the example code from the documentation " - "works"; + + +%% Test setopt/getopt of multiple raw options. +multiple_raw(Config) when is_list(Config) -> + do_multiple_raw(Config,false). + +%% Test setopt/getopt of multiple raw options, with binaries in +%% getopt. +multiple_raw_getbin(Config) when is_list(Config) -> + do_multiple_raw(Config,true). + +do_multiple_raw(Config, Binary) -> + Port = start_helper(Config), + SolSocket = ask_helper(Port, ?C_GET_SOL_SOCKET), + SoKeepalive = ask_helper(Port, ?C_GET_SO_KEEPALIVE), + SoKeepaliveTrue = {raw,SolSocket,SoKeepalive,<<1:32/native>>}, + SoKeepaliveFalse = {raw,SolSocket,SoKeepalive,<<0:32/native>>}, + SoReuseaddr = ask_helper(Port, ?C_GET_SO_REUSEADDR), + SoReuseaddrTrue = {raw,SolSocket,SoReuseaddr,<<1:32/native>>}, + SoReuseaddrFalse = {raw,SolSocket,SoReuseaddr,<<0:32/native>>}, + {S1,S2} = + create_socketpair( + [SoReuseaddrFalse,SoKeepaliveTrue], + [SoKeepaliveFalse,SoReuseaddrTrue]), + {ok,[{reuseaddr,false},{keepalive,true}]} = + inet:getopts(S1, [reuseaddr,keepalive]), + {ok, + [{raw,SolSocket,SoReuseaddr,S1R1}, + {raw,SolSocket,SoKeepalive,S1K1}]} = + inet:getopts( + S1, + [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)}, + {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]), + true = nintbin2int(S1R1) =:= 0, + true = nintbin2int(S1K1) =/= 0, + {ok,[{keepalive,false},{reuseaddr,true}]} = + inet:getopts(S2, [keepalive,reuseaddr]), + {ok, + [{raw,SolSocket,SoKeepalive,S2K1}, + {raw,SolSocket,SoReuseaddr,S2R1}]} = + inet:getopts( + S2, + [{raw,SolSocket,SoKeepalive,binarify(4, Binary)}, + {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]), + true = nintbin2int(S2K1) =:= 0, + true = nintbin2int(S2R1) =/= 0, + %% + ok = inet:setopts( + S1, [SoReuseaddrTrue,SoKeepaliveFalse]), + ok = inet:setopts( + S2, [SoKeepaliveTrue,SoReuseaddrFalse]), + {ok, + [{raw,SolSocket,SoReuseaddr,S1R2}, + {raw,SolSocket,SoKeepalive,S1K2}]} = + inet:getopts( + S1, + [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)}, + {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]), + true = nintbin2int(S1R2) =/= 0, + true = nintbin2int(S1K2) =:= 0, + {ok, + [{raw,SolSocket,SoKeepalive,S2K2}, + {raw,SolSocket,SoReuseaddr,S2R2}]} = + inet:getopts( + S2, + [{raw,SolSocket,SoKeepalive,binarify(4, Binary)}, + {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]), + true = nintbin2int(S2K2) =/= 0, + true = nintbin2int(S2R2) =:= 0, + %% + gen_tcp:close(S1), + gen_tcp:close(S2), + stop_helper(Port), + ok. + + + +%% Test that the example code from the documentation works. doc_examples_raw(Config) when is_list(Config) -> do_doc_examples_raw(Config,false). -doc_examples_raw_getbin(suite) -> []; -doc_examples_raw_getbin(doc) -> "Test that the example code from the " - "documentation works when getopt uses " - "binaries"; + +%% Test that the example code from the documentation works when getopt +%% uses binaries. doc_examples_raw_getbin(Config) when is_list(Config) -> do_doc_examples_raw(Config,true). + do_doc_examples_raw(Config,Binary) when is_list(Config) -> - ?line Port = start_helper(Config), - ?line Proto = ask_helper(Port,?C_GET_IPPROTO_TCP), - ?line TcpInfo = ask_helper(Port,?C_GET_TCP_INFO), - ?line TcpInfoSize = ask_helper(Port,?C_GET_TCP_INFO_SIZE), - ?line TcpiSackedOffset = ask_helper(Port,?C_GET_OFF_TCPI_SACKED), - ?line TcpiOptionsOffset = ask_helper(Port,?C_GET_OFF_TCPI_OPTIONS), - ?line TcpiSackedSize = ask_helper(Port,?C_GET_SIZ_TCPI_SACKED), - ?line TcpiOptionsSize = ask_helper(Port,?C_GET_SIZ_TCPI_OPTIONS), - ?line TcpLinger2 = ask_helper(Port,?C_GET_TCP_LINGER2), - ?line stop_helper(Port), + Port = start_helper(Config), + Proto = ask_helper(Port,?C_GET_IPPROTO_TCP), + TcpInfo = ask_helper(Port,?C_GET_TCP_INFO), + TcpInfoSize = ask_helper(Port,?C_GET_TCP_INFO_SIZE), + TcpiSackedOffset = ask_helper(Port,?C_GET_OFF_TCPI_SACKED), + TcpiOptionsOffset = ask_helper(Port,?C_GET_OFF_TCPI_OPTIONS), + TcpiSackedSize = ask_helper(Port,?C_GET_SIZ_TCPI_SACKED), + TcpiOptionsSize = ask_helper(Port,?C_GET_SIZ_TCPI_OPTIONS), + TcpLinger2 = ask_helper(Port,?C_GET_TCP_LINGER2), + stop_helper(Port), case all_ok([Proto,TcpInfo,TcpInfoSize,TcpiSackedOffset, TcpiOptionsOffset,TcpiSackedSize,TcpiOptionsSize, TcpLinger2]) of false -> {skipped,"Does not run on this OS."}; true -> - ?line {Sock,I} = create_socketpair([],[]), - ?line {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} = + {Sock,I} = create_socketpair([],[]), + {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} = inet:getopts(Sock,[{raw,Proto,TcpLinger2,binarify(4,Binary)}]), - ?line NewLinger = OrigLinger div 2, - ?line ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2, - <<NewLinger:32/native>>}]), - ?line {ok,[{raw,Proto,TcpLinger2,<<NewLinger:32/native>>}]} = + NewLinger = OrigLinger div 2, + ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2, + <<NewLinger:32/native>>}]), + {ok,[{raw,Proto,TcpLinger2,<<NewLinger:32/native>>}]} = inet:getopts(Sock,[{raw,Proto,TcpLinger2,binarify(4,Binary)}]), - ?line ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2, - <<OrigLinger:32/native>>}]), - ?line {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} = + ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2, + <<OrigLinger:32/native>>}]), + {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} = inet:getopts(Sock,[{raw,Proto,TcpLinger2,binarify(4,Binary)}]), - ?line {ok,[{raw,_,_,Info}]} = + {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,Proto,TcpInfo, binarify(TcpInfoSize,Binary)}]), - ?line Bit1 = TcpiSackedSize * 8, - ?line <<_:TcpiSackedOffset/binary, - TcpiSacked:Bit1/native,_/binary>> = + Bit1 = TcpiSackedSize * 8, + <<_:TcpiSackedOffset/binary, + TcpiSacked:Bit1/native,_/binary>> = Info, - ?line 0 = TcpiSacked, - ?line Bit2 = TcpiOptionsSize * 8, - ?line <<_:TcpiOptionsOffset/binary, - TcpiOptions:Bit2/native,_/binary>> = + 0 = TcpiSacked, + Bit2 = TcpiOptionsSize * 8, + <<_:TcpiOptionsOffset/binary, + TcpiOptions:Bit2/native,_/binary>> = Info, - ?line true = TcpiOptions =/= 0, - ?line gen_tcp:close(Sock), - ?line gen_tcp:close(I), + true = TcpiOptions =/= 0, + gen_tcp:close(Sock), + gen_tcp:close(I), ok end. - -large_raw(suite) -> []; -large_raw(doc) -> "Test structs and large/too large buffers when raw"; + +%% Test structs and large/too large buffers when raw. large_raw(Config) when is_list(Config) -> do_large_raw(Config,false). -large_raw_getbin(suite) -> []; -large_raw_getbin(doc) -> "Test structs and large/too large buffers when raw" - "using binaries to getopts"; + +%% Test structs and large/too large buffers when raw +%% using binaries to getopts. large_raw_getbin(Config) when is_list(Config) -> do_large_raw(Config,true). + do_large_raw(Config,Binary) when is_list(Config) -> - ?line Port = start_helper(Config), - ?line Proto = ask_helper(Port,?C_GET_SOL_SOCKET), - ?line Linger = ask_helper(Port,?C_GET_SO_LINGER), - ?line LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE), - ?line LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF), - ?line LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER), - ?line LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF), - ?line LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER), - ?line stop_helper(Port), + Port = start_helper(Config), + Proto = ask_helper(Port,?C_GET_SOL_SOCKET), + Linger = ask_helper(Port,?C_GET_SO_LINGER), + LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE), + LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF), + LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER), + LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF), + LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER), + stop_helper(Port), case all_ok([Proto,Linger,LingerSize,LingerOnOffOffset, LingerLingerOffset,LingerOnOffSize,LingerLingerSize]) of false -> {skipped,"Does not run on this OS."}; true -> - ?line {Sock1,Sock2} = create_socketpair([{linger,{true,10}}], - [{linger,{false,0}}]), - ?line LargeSize = 1024, % Solaris can take up to 1024*9, - % linux 1024*63... - ?line TooLargeSize = 1024*64, - ?line {ok,[{raw,Proto,Linger,Linger1}]} = + {Sock1,Sock2} = create_socketpair([{linger,{true,10}}], + [{linger,{false,0}}]), + LargeSize = 1024, % Solaris can take up to 1024*9, + % linux 1024*63... + TooLargeSize = 1024*64, + {ok,[{raw,Proto,Linger,Linger1}]} = inet:getopts(Sock1,[{raw,Proto,Linger, binarify(LargeSize,Binary)}]), - ?line {ok,[{raw,Proto,Linger,Linger2}]} = + {ok,[{raw,Proto,Linger,Linger2}]} = inet:getopts(Sock2,[{raw,Proto,Linger, binarify(LingerSize,Binary)}]), - ?line true = byte_size(Linger1) =:= LingerSize, - ?line LingerLingerBits = LingerLingerSize * 8, - ?line LingerOnOffBits = LingerOnOffSize * 8, - ?line <<_:LingerLingerOffset/binary, - Ling1:LingerLingerBits/native,_/binary>> = Linger1, - ?line <<_:LingerOnOffOffset/binary, - Off1:LingerOnOffBits/native,_/binary>> = Linger1, - ?line <<_:LingerOnOffOffset/binary, - Off2:LingerOnOffBits/native,_/binary>> = Linger2, - ?line true = Off1 =/= 0, - ?line true = Off2 == 0, - ?line true = Ling1 == 10, - ?line {error,einval} = + true = byte_size(Linger1) =:= LingerSize, + LingerLingerBits = LingerLingerSize * 8, + LingerOnOffBits = LingerOnOffSize * 8, + <<_:LingerLingerOffset/binary, + Ling1:LingerLingerBits/native,_/binary>> = Linger1, + <<_:LingerOnOffOffset/binary, + Off1:LingerOnOffBits/native,_/binary>> = Linger1, + <<_:LingerOnOffOffset/binary, + Off2:LingerOnOffBits/native,_/binary>> = Linger2, + true = Off1 =/= 0, + true = Off2 == 0, + true = Ling1 == 10, + {error,einval} = inet:getopts(Sock1,[{raw,Proto,Linger,TooLargeSize}]), - ?line gen_tcp:close(Sock1), - ?line gen_tcp:close(Sock2), + gen_tcp:close(Sock1), + gen_tcp:close(Sock2), ok end. -combined(suite) -> []; -combined(doc) -> "Test raw structs combined w/ other options "; +%% Test raw structs combined w/ other options . combined(Config) when is_list(Config) -> do_combined(Config,false). -combined_getbin(suite) -> []; -combined_getbin(doc) -> "Test raw structs combined w/ other options and " - "binarise in getopts"; + +%% Test raw structs combined w/ other options and +%% binarise in getopts. combined_getbin(Config) when is_list(Config) -> do_combined(Config,true). + do_combined(Config,Binary) when is_list(Config) -> - ?line Port = start_helper(Config), - ?line Proto = ask_helper(Port,?C_GET_SOL_SOCKET), - ?line Linger = ask_helper(Port,?C_GET_SO_LINGER), - ?line LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE), - ?line LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF), - ?line LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER), - ?line LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF), - ?line LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER), - ?line stop_helper(Port), + Port = start_helper(Config), + Proto = ask_helper(Port,?C_GET_SOL_SOCKET), + Linger = ask_helper(Port,?C_GET_SO_LINGER), + LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE), + LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF), + LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER), + LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF), + LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER), + stop_helper(Port), case all_ok([Proto,Linger,LingerSize,LingerOnOffOffset, LingerLingerOffset,LingerOnOffSize,LingerLingerSize]) of false -> {skipped,"Does not run on this OS."}; true -> - ?line LingerLingerBits = LingerLingerSize * 8, - ?line LingerOnOffBits = LingerOnOffSize * 8, - ?line {LingerOn,LingerOff} = + LingerLingerBits = LingerLingerSize * 8, + LingerOnOffBits = LingerOnOffSize * 8, + {LingerOn,LingerOff} = case LingerOnOffOffset < LingerLingerOffset of true -> Pad1 = @@ -343,11 +416,11 @@ do_combined(Config,Binary) when is_list(Config) -> lists:duplicate(Pad3Siz, 0)), {<<Pad1/binary,1:LingerOnOffBits/native, - Pad2/binary,10:LingerLingerBits/native, - Pad3/binary>>, + Pad2/binary,10:LingerLingerBits/native, + Pad3/binary>>, <<Pad1/binary,0:LingerOnOffBits/native, - Pad2/binary,0:LingerLingerBits/native, - Pad3/binary>>}; + Pad2/binary,0:LingerLingerBits/native, + Pad3/binary>>}; false -> Pad1 = list_to_binary( @@ -366,177 +439,174 @@ do_combined(Config,Binary) when is_list(Config) -> lists:duplicate(Pad3Siz, 0)), {<<Pad1/binary,1:LingerLingerBits/native, - Pad2/binary,10:LingerOnOffBits/native, - Pad3/binary>>, + Pad2/binary,10:LingerOnOffBits/native, + Pad3/binary>>, <<Pad1/binary,0:LingerLingerBits/native, - Pad2/binary,0:LingerOnOffBits/native, - Pad3/binary>>} + Pad2/binary,0:LingerOnOffBits/native, + Pad3/binary>>} end, - ?line RawLingerOn = {raw,Proto,Linger,LingerOn}, - ?line RawLingerOff = {raw,Proto,Linger,LingerOff}, - ?line {Sock1,Sock2} = + RawLingerOn = {raw,Proto,Linger,LingerOn}, + RawLingerOff = {raw,Proto,Linger,LingerOff}, + {Sock1,Sock2} = create_socketpair([{keepalive,true}, RawLingerOn], [{keepalive,false}, RawLingerOff]), - ?line {ok,[{raw,Proto,Linger,Linger1},{keepalive,Keep1}]} = + {ok,[{raw,Proto,Linger,Linger1},{keepalive,Keep1}]} = inet:getopts(Sock1,[{raw,Proto,Linger, binarify(LingerSize,Binary)},keepalive]), - ?line {ok,[{raw,Proto,Linger,Linger2},{keepalive,Keep2}]} = + {ok,[{raw,Proto,Linger,Linger2},{keepalive,Keep2}]} = inet:getopts(Sock2,[{raw,Proto,Linger, binarify(LingerSize,Binary)},keepalive]), - ?line true = byte_size(Linger1) =:= LingerSize, - ?line <<_:LingerLingerOffset/binary, - Ling1:LingerLingerBits/native,_/binary>> = Linger1, - ?line <<_:LingerOnOffOffset/binary, - Off1:LingerOnOffBits/native,_/binary>> = Linger1, - ?line <<_:LingerOnOffOffset/binary, - Off2:LingerOnOffBits/native,_/binary>> = Linger2, - ?line true = Off1 =/= 0, - ?line true = Off2 == 0, - ?line true = Ling1 == 10, - ?line true = Keep1 =:= true, - ?line true = Keep2 =:= false, - ?line {Sock3,Sock4} = + true = byte_size(Linger1) =:= LingerSize, + <<_:LingerLingerOffset/binary, + Ling1:LingerLingerBits/native,_/binary>> = Linger1, + <<_:LingerOnOffOffset/binary, + Off1:LingerOnOffBits/native,_/binary>> = Linger1, + <<_:LingerOnOffOffset/binary, + Off2:LingerOnOffBits/native,_/binary>> = Linger2, + true = Off1 =/= 0, + true = Off2 == 0, + true = Ling1 == 10, + true = Keep1 =:= true, + true = Keep2 =:= false, + {Sock3,Sock4} = create_socketpair([RawLingerOn,{keepalive,true}], [RawLingerOff,{keepalive,false}]), - ?line {ok,[{raw,Proto,Linger,Linger3},{keepalive,Keep3}]} = + {ok,[{raw,Proto,Linger,Linger3},{keepalive,Keep3}]} = inet:getopts(Sock3,[{raw,Proto,Linger, binarify(LingerSize,Binary)},keepalive]), - ?line {ok,[{raw,Proto,Linger,Linger4},{keepalive,Keep4}]} = + {ok,[{raw,Proto,Linger,Linger4},{keepalive,Keep4}]} = inet:getopts(Sock4,[{raw,Proto,Linger, binarify(LingerSize,Binary)},keepalive]), - ?line true = byte_size(Linger3) =:= LingerSize, - ?line <<_:LingerLingerOffset/binary, - Ling3:LingerLingerBits/native,_/binary>> = Linger3, - ?line <<_:LingerOnOffOffset/binary, - Off3:LingerOnOffBits/native,_/binary>> = Linger3, - ?line <<_:LingerOnOffOffset/binary, - Off4:LingerOnOffBits/native,_/binary>> = Linger4, - ?line true = Off3 =/= 0, - ?line true = Off4 == 0, - ?line true = Ling3 == 10, - ?line true = Keep3 =:= true, - ?line true = Keep4 =:= false, - ?line {Sock5,Sock6} = + true = byte_size(Linger3) =:= LingerSize, + <<_:LingerLingerOffset/binary, + Ling3:LingerLingerBits/native,_/binary>> = Linger3, + <<_:LingerOnOffOffset/binary, + Off3:LingerOnOffBits/native,_/binary>> = Linger3, + <<_:LingerOnOffOffset/binary, + Off4:LingerOnOffBits/native,_/binary>> = Linger4, + true = Off3 =/= 0, + true = Off4 == 0, + true = Ling3 == 10, + true = Keep3 =:= true, + true = Keep4 =:= false, + {Sock5,Sock6} = create_socketpair([{packet,4},RawLingerOn,{keepalive,true}], [{packet,2},RawLingerOff,{keepalive,false}]), - ?line {ok,[{packet,Pack5},{raw,Proto,Linger,Linger5}, - {keepalive,Keep5}]} = + {ok,[{packet,Pack5},{raw,Proto,Linger,Linger5}, + {keepalive,Keep5}]} = inet:getopts(Sock5,[packet,{raw,Proto,Linger, binarify(LingerSize,Binary)}, keepalive]), - ?line {ok,[{packet,Pack6},{raw,Proto,Linger,Linger6}, - {keepalive,Keep6}]} = + {ok,[{packet,Pack6},{raw,Proto,Linger,Linger6}, + {keepalive,Keep6}]} = inet:getopts(Sock6,[packet,{raw,Proto,Linger, binarify(LingerSize,Binary)}, keepalive]), - ?line true = byte_size(Linger5) =:= LingerSize, - ?line <<_:LingerLingerOffset/binary, - Ling5:LingerLingerBits/native,_/binary>> = Linger5, - ?line <<_:LingerOnOffOffset/binary, - Off5:LingerOnOffBits/native,_/binary>> = Linger5, - ?line <<_:LingerOnOffOffset/binary, - Off6:LingerOnOffBits/native,_/binary>> = Linger6, - ?line true = Off5 =/= 0, - ?line true = Off6 == 0, - ?line true = Ling5 == 10, - ?line true = Keep5 =:= true, - ?line true = Keep6 =:= false, - ?line true = Pack5 =:= 4, - ?line true = Pack6 =:= 2, - ?line inet:setopts(Sock6,[{packet,4},RawLingerOn, - {keepalive,true}]), - ?line {ok,[{packet,Pack7},{raw,Proto,Linger,Linger7}, - {keepalive,Keep7}]} = + true = byte_size(Linger5) =:= LingerSize, + <<_:LingerLingerOffset/binary, + Ling5:LingerLingerBits/native,_/binary>> = Linger5, + <<_:LingerOnOffOffset/binary, + Off5:LingerOnOffBits/native,_/binary>> = Linger5, + <<_:LingerOnOffOffset/binary, + Off6:LingerOnOffBits/native,_/binary>> = Linger6, + true = Off5 =/= 0, + true = Off6 == 0, + true = Ling5 == 10, + true = Keep5 =:= true, + true = Keep6 =:= false, + true = Pack5 =:= 4, + true = Pack6 =:= 2, + inet:setopts(Sock6,[{packet,4},RawLingerOn, + {keepalive,true}]), + {ok,[{packet,Pack7},{raw,Proto,Linger,Linger7}, + {keepalive,Keep7}]} = inet:getopts(Sock6,[packet,{raw,Proto,Linger, binarify(LingerSize,Binary)}, keepalive]), - ?line <<_:LingerOnOffOffset/binary, - Off7:LingerOnOffBits/native,_/binary>> = Linger7, - ?line true = Off7 =/= 0, - ?line true = Keep7 =:= true, - ?line true = Pack7 =:= 4, - ?line gen_tcp:close(Sock1), - ?line gen_tcp:close(Sock2), - ?line gen_tcp:close(Sock3), - ?line gen_tcp:close(Sock4), - ?line gen_tcp:close(Sock5), - ?line gen_tcp:close(Sock6), + <<_:LingerOnOffOffset/binary, + Off7:LingerOnOffBits/native,_/binary>> = Linger7, + true = Off7 =/= 0, + true = Keep7 =:= true, + true = Pack7 =:= 4, + gen_tcp:close(Sock1), + gen_tcp:close(Sock2), + gen_tcp:close(Sock3), + gen_tcp:close(Sock4), + gen_tcp:close(Sock5), + gen_tcp:close(Sock6), ok end. -ipv6_v6only_udp(suite) -> []; -ipv6_v6only_udp(doc) -> "Test socket option ipv6_v6only for UDP"; +%% Test socket option ipv6_v6only for UDP. ipv6_v6only_udp(Config) when is_list(Config) -> ipv6_v6only(Config, gen_udp). -ipv6_v6only_tcp(suite) -> []; -ipv6_v6only_tcp(doc) -> "Test socket option ipv6_v6only for TCP"; +%% Test socket option ipv6_v6only for TCP. ipv6_v6only_tcp(Config) when is_list(Config) -> ipv6_v6only(Config, gen_tcp). -ipv6_v6only_sctp(suite) -> []; -ipv6_v6only_sctp(doc) -> "Test socket option ipv6_v6only for SCTP"; +%% Test socket option ipv6_v6only for SCTP. ipv6_v6only_sctp(Config) when is_list(Config) -> ipv6_v6only(Config, gen_sctp). ipv6_v6only(Config, Module) when is_list(Config) -> - ?line case ipv6_v6only_open(Module, []) of - {ok,S1} -> - ?line case inet:getopts(S1, [ipv6_v6only]) of - {ok,[{ipv6_v6only,Default}]} - when is_boolean(Default) -> - ?line ok = - ipv6_v6only_close(Module, S1), - ?line ipv6_v6only(Config, Module, Default); - {ok,[]} -> - ?line io:format("Not implemented.~n", []), - %% This list of OS:es where the option is - %% supposed to be not implemented is just - %% a guess, and may grow with time. - ?line case {os:type(),os:version()} of - {{unix,linux},{2,M,_}} - when M =< 4 -> ok - end, - %% At least this should work - ?line {ok,S2} = - ipv6_v6only_open( - Module, - [{ipv6_v6only,true}]), - ?line ok = - ipv6_v6only_close(Module, S2) - end; - {error,_} -> - {skipped,"Socket type not supported"} - end. + case ipv6_v6only_open(Module, []) of + {ok,S1} -> + case inet:getopts(S1, [ipv6_v6only]) of + {ok,[{ipv6_v6only,Default}]} + when is_boolean(Default) -> + ok = + ipv6_v6only_close(Module, S1), + ipv6_v6only(Config, Module, Default); + {ok,[]} -> + io:format("Not implemented.~n", []), + %% This list of OS:es where the option is + %% supposed to be not implemented is just + %% a guess, and may grow with time. + case {os:type(),os:version()} of + {{unix,linux},{2,M,_}} + when M =< 4 -> ok + end, + %% At least this should work + {ok,S2} = + ipv6_v6only_open( + Module, + [{ipv6_v6only,true}]), + ok = + ipv6_v6only_close(Module, S2) + end; + {error,_} -> + {skipped,"Socket type not supported"} + end. ipv6_v6only(Config, Module, Default) when is_list(Config) -> - ?line io:format("Default ~w.~n", [Default]), - ?line {ok,S1} = + io:format("Default ~w.~n", [Default]), + {ok,S1} = ipv6_v6only_open(Module, [{ipv6_v6only,Default}]), - ?line {ok,[{ipv6_v6only,Default}]} = + {ok,[{ipv6_v6only,Default}]} = inet:getopts(S1, [ipv6_v6only]), - ?line ok = + ok = ipv6_v6only_close(Module, S1), - ?line NotDefault = not Default, - ?line case ipv6_v6only_open(Module, [{ipv6_v6only,NotDefault}]) of - {ok,S2} -> - ?line io:format("Read-write.~n", []), - ?line {ok,[{ipv6_v6only,NotDefault}]} = - inet:getopts(S2, [ipv6_v6only]), - ok; - {error,einval} -> - ?line io:format("Read-only.~n", []), - %% This option is known to be read-only and true - %% on Windows and OpenBSD - ?line case os:type() of - {unix,openbsd} when Default =:= true -> ok; - {win32,_} when Default =:= true -> ok - end - end. + NotDefault = not Default, + case ipv6_v6only_open(Module, [{ipv6_v6only,NotDefault}]) of + {ok,S2} -> + io:format("Read-write.~n", []), + {ok,[{ipv6_v6only,NotDefault}]} = + inet:getopts(S2, [ipv6_v6only]), + ok; + {error,einval} -> + io:format("Read-only.~n", []), + %% This option is known to be read-only and true + %% on Windows and OpenBSD + case os:type() of + {unix,openbsd} when Default =:= true -> ok; + {win32,_} when Default =:= true -> ok + end + end. ipv6_v6only_open(Module, Opts) -> Module:case Module of @@ -548,47 +618,46 @@ ipv6_v6only_close(Module, Socket) -> Module:close(Socket). -use_ipv6_v6only_udp(suite) -> []; -use_ipv6_v6only_udp(doc) -> "Test using socket option ipv6_v6only for UDP"; +%% Test using socket option ipv6_v6only for UDP. use_ipv6_v6only_udp(Config) when is_list(Config) -> - ?line case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of - {ok,S6} -> - ?line case inet:getopts(S6, [ipv6_v6only]) of - {ok,[{ipv6_v6only,true}]} -> - use_ipv6_v6only_udp(Config, S6); - {ok,Other} -> - {skipped,{getopts,Other}} - end; - {error,_} -> - {skipped,"Socket type not supported"} - end. + case gen_udp:open(0, [inet6,{ip,{0,0,0,0,0,0,0,1}}, {ipv6_v6only,true}]) of + {ok,S6} -> + case inet:getopts(S6, [ipv6_v6only]) of + {ok,[{ipv6_v6only,true}]} -> + use_ipv6_v6only_udp(Config, S6); + {ok,Other} -> + {skipped,{getopts,Other}} + end; + {error,_} -> + {skipped,"Socket type not supported"} + end. use_ipv6_v6only_udp(_Config, S6) -> - ?line {ok,Port} = inet:port(S6), - ?line {ok,S4} = gen_udp:open(Port, [inet]), - ?line E6 = " IPv6-echo.", - ?line E4 = " IPv4-echo.", - ?line Sender = + {ok,Port} = inet:port(S6), + {ok,S4} = gen_udp:open(Port, [inet]), + E6 = " IPv6-echo.", + E4 = " IPv4-echo.", + Sender = spawn_link(fun () -> use_ipv6_v6only_udp_sender(Port, E6, E4) end), - ?line use_ipv6_v6only_udp_listener( - S6, S4, E6, E4, monitor(process, Sender)). + use_ipv6_v6only_udp_listener( + S6, S4, E6, E4, monitor(process, Sender)). use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref) -> - ?line receive - {udp,S6,IP,P,Data} -> - ?line ok = gen_udp:send(S6, IP, P, [Data|E6]), - ?line use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref); - {udp,S4,IP,P,Data} -> - ?line ok = gen_udp:send(S4, IP, P, [Data|E4]), - ?line use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref); - {'DOWN',Mref,_,_,normal} -> - ok; - {'DOWN',Mref,_,_,Result} -> - %% Since we are linked we will never arrive here - Result; - Other -> - ?line exit({failed,{listener_unexpected,Other}}) - end. + receive + {udp,S6,IP,P,Data} -> + ok = gen_udp:send(S6, IP, P, [Data|E6]), + use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref); + {udp,S4,IP,P,Data} -> + ok = gen_udp:send(S4, IP, P, [Data|E4]), + use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref); + {'DOWN',Mref,_,_,normal} -> + ok; + {'DOWN',Mref,_,_,Result} -> + %% Since we are linked we will never arrive here + Result; + Other -> + exit({failed,{listener_unexpected,Other}}) + end. use_ipv6_v6only_udp_sender(Port, E6, E4) -> D6 = "IPv6-send.", @@ -613,12 +682,9 @@ sndrcv(Ip, Port, Opts, Data) -> -type_errors(suite) -> - []; -type_errors(doc) -> - "Test that raw data requests are not executed for bad types"; +%% Test that raw data requests are not executed for bad types. type_errors(Config) when is_list(Config) -> - ?line BadSetOptions = + BadSetOptions = [ {raw,x,3,<<1:32>>}, {raw,1,tre,<<1:32>>}, @@ -636,7 +702,7 @@ type_errors(Config) when is_list(Config) -> rav, {linger,banan} ], - ?line BadGetOptions = + BadGetOptions = [ {raw,x,3,<<1:32>>}, {raw,1,tre,<<1:32>>}, @@ -655,46 +721,46 @@ type_errors(Config) when is_list(Config) -> rav, {linger,banan} ], - ?line lists:foreach(fun(Option) -> - ?line case - catch create_socketpair([Option],[]) of - {'EXIT',badarg} -> - ?line ok; - Unexpected1 -> - ?line exit({unexpected, - Unexpected1}) - end, - ?line case - catch create_socketpair([],[Option]) of - {'EXIT',badarg} -> - ?line ok; - Unexpected2 -> - ?line exit({unexpected, - Unexpected2}) - end, - ?line {Sock1,Sock2} = create_socketpair([],[]), - ?line case inet:setopts(Sock1, [Option]) of - {error,einval} -> - ?line ok; - Unexpected3 -> - ?line exit({unexpected, - Unexpected3}) - end, - ?line gen_tcp:close(Sock1), - ?line gen_tcp:close(Sock2) - end,BadSetOptions), - ?line {Sock1,Sock2} = create_socketpair([],[]), - ?line lists:foreach(fun(Option) -> - ?line case inet:getopts(Sock1, [Option]) of - {error,einval} -> - ?line ok; - Unexpected -> - ?line exit({unexpected, - Unexpected}) - end - end,BadGetOptions), - ?line gen_tcp:close(Sock1), - ?line gen_tcp:close(Sock2), + lists:foreach(fun(Option) -> + case + catch create_socketpair([Option],[]) of + {'EXIT',badarg} -> + ok; + Unexpected1 -> + exit({unexpected, + Unexpected1}) + end, + case + catch create_socketpair([],[Option]) of + {'EXIT',badarg} -> + ok; + Unexpected2 -> + exit({unexpected, + Unexpected2}) + end, + {Sock1,Sock2} = create_socketpair([],[]), + case inet:setopts(Sock1, [Option]) of + {error,einval} -> + ok; + Unexpected3 -> + exit({unexpected, + Unexpected3}) + end, + gen_tcp:close(Sock1), + gen_tcp:close(Sock2) + end,BadSetOptions), + {Sock1,Sock2} = create_socketpair([],[]), + lists:foreach(fun(Option) -> + case inet:getopts(Sock1, [Option]) of + {error,einval} -> + ok; + Unexpected -> + exit({unexpected, + Unexpected}) + end + end,BadGetOptions), + gen_tcp:close(Sock1), + gen_tcp:close(Sock2), ok. all_ok([]) -> @@ -704,59 +770,59 @@ all_ok([H|T]) when H >= 0 -> all_ok(_) -> false. - + make_check_fun(Type,Element) -> fun({Name,V1,V2,Mand,Chang},Acc) -> - ?line {LO1,CO1} = setelement(Element,{[],[]}, [{Name,V1}]), - ?line {LO2,CO2} = setelement(Element,{[],[]}, [{Name,V2}]), - ?line {X1,Y1} = create_socketpair(LO1,CO1), - ?line {X2,Y2} = create_socketpair(LO2,CO2), - ?line S1 = element(Element,{X1,Y1}), - ?line S2 = element(Element,{X2,Y2}), - ?line {ok,[{Name,R1}]} = inet:getopts(S1,[Name]), - ?line {ok,[{Name,R2}]} = inet:getopts(S2,[Name]), + {LO1,CO1} = setelement(Element,{[],[]}, [{Name,V1}]), + {LO2,CO2} = setelement(Element,{[],[]}, [{Name,V2}]), + {X1,Y1} = create_socketpair(LO1,CO1), + {X2,Y2} = create_socketpair(LO2,CO2), + S1 = element(Element,{X1,Y1}), + S2 = element(Element,{X2,Y2}), + {ok,[{Name,R1}]} = inet:getopts(S1,[Name]), + {ok,[{Name,R2}]} = inet:getopts(S2,[Name]), NewAcc = case R1 =/= R2 of true -> case Chang of true -> - ?line inet:setopts(S1,[{Name,V2}]), - ?line {ok,[{Name,R3}]} = + inet:setopts(S1,[{Name,V2}]), + {ok,[{Name,R3}]} = inet:getopts(S1,[Name]), case {R3 =/= R1, R3 =:= R2} of {true,true} -> - ?line Acc; + Acc; _ -> case Mand of true -> - ?line exit - ({failed_sockopt, - {change, - Name}}); + exit + ({failed_sockopt, + {change, + Name}}); false -> - ?line [{change,Name}|Acc] + [{change,Name}|Acc] end end; false -> - ?line Acc + Acc end; false -> case Mand of true -> - ?line exit({failed_sockopt, - {Type,Name}}); + exit({failed_sockopt, + {Type,Name}}); false -> - ?line [{Type,Name}|Acc] + [{Type,Name}|Acc] end end, - ?line gen_tcp:close(X1), - ?line gen_tcp:close(Y1), - ?line gen_tcp:close(X2), - ?line gen_tcp:close(Y2), + gen_tcp:close(X1), + gen_tcp:close(Y1), + gen_tcp:close(X2), + gen_tcp:close(Y2), NewAcc - end. + end. -% {OptionName,Value1,Value2,Mandatory,Changeable} +%% {OptionName,Value1,Value2,Mandatory,Changeable} all_listen_options() -> [{tos,0,1,false,true}, {priority,0,1,false,true}, @@ -807,19 +873,19 @@ all_connect_options() -> {delay_send,false,true,true,true}, {packet_size,0,4,true,true} ]. - + create_socketpair(ListenOptions,ConnectOptions) -> - ?line {ok,LS}=gen_tcp:listen(0,ListenOptions), - ?line {ok,Port}=inet:port(LS), - ?line {ok,CS}=gen_tcp:connect(localhost,Port,ConnectOptions), - ?line {ok,AS}=gen_tcp:accept(LS), - ?line gen_tcp:close(LS), + {ok,LS}=gen_tcp:listen(0,ListenOptions), + {ok,Port}=inet:port(LS), + {ok,CS}=gen_tcp:connect(localhost,Port,ConnectOptions), + {ok,AS}=gen_tcp:accept(LS), + gen_tcp:close(LS), {AS,CS}. start_helper(Config) -> - Progname = filename:join(?config(data_dir, Config), "sockopt_helper"), + Progname = filename:join(proplists:get_value(data_dir, Config), "sockopt_helper"), Port = open_port({spawn,Progname},[eof,line]), Port. diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index 54ab5aa566..2b59eb2bfe 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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. @@ -19,15 +19,16 @@ %% -module(init_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([get_arguments/1, get_argument/1, boot_var/1, restart/1, - many_restarts/1, + many_restarts/0, many_restarts/1, get_plain_arguments/1, - reboot/1, stop/1, get_status/1, script_id/1]). + reboot/1, stop_status/1, stop/1, get_status/1, script_id/1, + find_system_processes/0]). -export([boot1/1, boot2/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -41,12 +42,14 @@ %% Should be started in a CC view with: %% erl -sname master -rsh ctrsh %%----------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [get_arguments, get_argument, boot_var, many_restarts, - get_plain_arguments, restart, get_status, script_id, + get_plain_arguments, restart, stop_status, get_status, script_id, {group, boot}]. groups() -> @@ -65,46 +68,35 @@ end_per_group(_GroupName, Config) -> Config. -init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog=?t:timetrap(?t:seconds(?DEFAULT_TIMEOUT_SEC)), - [{watchdog, Dog}|Config]. +init_per_testcase(Func, Config) -> + Config. -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. -init(doc) -> []; -init(suite) -> []; init(Config) when is_list(Config) -> Config. -fini(doc) -> []; -fini(suite) -> []; fini(Config) when is_list(Config) -> Host = list_to_atom(from($@, atom_to_list(node()))), Node = list_to_atom(lists:concat([init_test, "@", Host])), stop_node(Node), Config. -get_arguments(doc) ->[]; -get_arguments(suite) -> {req, [distribution, {local_slave_nodes, 1}]}; get_arguments(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(10)), - Args = args(), - ?line {ok, Node} = start_node(init_test, Args), - ?line case rpc:call(Node, init, get_arguments, []) of - Arguments when is_list(Arguments) -> - stop_node(Node), - check_a(Arguments), - check_b(Arguments), - check_c(Arguments), - check_d(Arguments); - _ -> - stop_node(Node), - ?t:fail(get_arguments) - end, - ?line ?t:timetrap_cancel(Dog), + {ok, Node} = start_node(init_test, Args), + case rpc:call(Node, init, get_arguments, []) of + Arguments when is_list(Arguments) -> + stop_node(Node), + check_a(Arguments), + check_b(Arguments), + check_c(Arguments), + check_d(Arguments); + _ -> + stop_node(Node), + ct:fail(get_arguments) + end, ok. check_a(Args) -> @@ -115,10 +107,10 @@ check_a(Args) -> false -> ok; _ -> - ?t:fail(check_a1) + ct:fail(check_a1) end; _ -> - ?t:fail(check_a2) + ct:fail(check_a2) end. check_b(Args) -> @@ -132,13 +124,13 @@ check_b(Args) -> false -> ok; _ -> - ?t:fail(check_b1) + ct:fail(check_b1) end; _ -> - ?t:fail(check_b2) + ct:fail(check_b2) end; _ -> - ?t:fail(check_b3) + ct:fail(check_b3) end. check_c(Args) -> @@ -152,13 +144,13 @@ check_c(Args) -> false -> ok; _ -> - ?t:fail(check_c1) + ct:fail(check_c1) end; _ -> - ?t:fail(check_c2) + ct:fail(check_c2) end; _ -> - ?t:fail(check_c3) + ct:fail(check_c3) end. check_d(Args) -> @@ -169,62 +161,54 @@ check_d(Args) -> false -> ok; _ -> - ?t:fail(check_d1) + ct:fail(check_d1) end; _ -> - ?t:fail(check_d2) + ct:fail(check_d2) end. -get_argument(doc) ->[]; -get_argument(suite) -> {req, [distribution, {local_slave_nodes, 1}]}; get_argument(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(10)), - Args = args(), - ?line {ok, Node} = start_node(init_test, Args), - ?line case rpc:call(Node, init, get_argument, [b]) of - {ok, [["hej", "hopp"],["san", "sa"]]} -> - ok; - _ -> - stop_node(Node), - ?t:fail({get_argument, b}) - end, - ?line case rpc:call(Node, init, get_argument, [a]) of - {ok, [["kalle"]]} -> - ok; - _ -> - stop_node(Node), - ?t:fail({get_argument, a}) - end, - ?line case rpc:call(Node, init, get_argument, [c]) of - {ok, [["4", "5", "6"], ["7", "8", "9"]]} -> - ok; - _ -> - stop_node(Node), - ?t:fail({get_argument, c}) - end, - ?line case rpc:call(Node, init, get_argument, [d]) of - {ok, [[]]} -> - ok; - _ -> - stop_node(Node), - ?t:fail({get_argument, d}) - end, - ?line case rpc:call(Node, init, get_argument, [e]) of - error -> - ok; - _ -> - stop_node(Node), - ?t:fail({get_argument, e}) - end, + {ok, Node} = start_node(init_test, Args), + case rpc:call(Node, init, get_argument, [b]) of + {ok, [["hej", "hopp"],["san", "sa"]]} -> + ok; + _ -> + stop_node(Node), + ct:fail({get_argument, b}) + end, + case rpc:call(Node, init, get_argument, [a]) of + {ok, [["kalle"]]} -> + ok; + _ -> + stop_node(Node), + ct:fail({get_argument, a}) + end, + case rpc:call(Node, init, get_argument, [c]) of + {ok, [["4", "5", "6"], ["7", "8", "9"]]} -> + ok; + _ -> + stop_node(Node), + ct:fail({get_argument, c}) + end, + case rpc:call(Node, init, get_argument, [d]) of + {ok, [[]]} -> + ok; + _ -> + stop_node(Node), + ct:fail({get_argument, d}) + end, + case rpc:call(Node, init, get_argument, [e]) of + error -> + ok; + _ -> + stop_node(Node), + ct:fail({get_argument, e}) + end, stop_node(Node), - ?line ?t:timetrap_cancel(Dog), ok. -get_plain_arguments(doc) ->[]; -get_plain_arguments(suite) -> {req, [distribution, {local_slave_nodes, 1}]}; get_plain_arguments(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(10)), Longstring = "fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2" "fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2" @@ -235,18 +219,17 @@ get_plain_arguments(Config) when is_list(Config) -> "fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2" "fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2" "fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2", - ?line true = (length(Longstring) > 255), + true = (length(Longstring) > 255), Args = long_args(Longstring), - ?line {ok, Node} = start_node(init_test, Args), - ?line case rpc:call(Node, init, get_plain_arguments, []) of - ["a", "b", "c", Longstring] -> - ok; - As -> - stop_node(Node), - ?t:fail({get_argument, As}) - end, + {ok, Node} = start_node(init_test, Args), + case rpc:call(Node, init, get_plain_arguments, []) of + ["a", "b", "c", Longstring] -> + ok; + As -> + stop_node(Node), + ct:fail({get_argument, As}) + end, stop_node(Node), - ?line ?t:timetrap_cancel(Dog), ok. @@ -254,199 +237,237 @@ get_plain_arguments(Config) when is_list(Config) -> %% ------------------------------------------------ %% Use -boot_var flag to set $TEST_VAR in boot script. %% ------------------------------------------------ -boot_var(doc) -> []; -boot_var(suite) -> {req, [distribution, {local_slave_nodes, 1}]}; boot_var(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(100)), - {BootScript, TEST_VAR, KernelVsn, StdlibVsn} = create_boot(Config), %% Should fail as we have not given -boot_var TEST_VAR - ?line {error, timeout} = - start_node(init_test, "-boot " ++ BootScript), + {error, timeout} = + start_node(init_test, "-boot " ++ BootScript), case is_real_system(KernelVsn, StdlibVsn) of true -> %% Now it should work !! - ?line {ok, Node} = - start_node(init_test, - "-boot " ++ BootScript ++ - " -boot_var TEST_VAR " ++ TEST_VAR), + {ok, Node} = + start_node(init_test, + "-boot " ++ BootScript ++ + " -boot_var TEST_VAR \"" ++ + TEST_VAR ++ "\""), stop_node(Node), Res = ok; _ -> %% What we need is not so much version numbers on the directories, but %% for the boot var TEST_VAR to appear in the boot script, and it doesn't %% if we give the 'local' option to systools:make_script. - ?t:format( - "Test case not complete as we are not~n" - "running in a real system!~n" - "Probably this test is performed in a " - "clearcase view or source tree.~n" - "Need version numbers on the kernel and " - "stdlib directories!~n", - []), + io:format( + "Test case not complete as we are not~n" + "running in a real system!~n" + "Probably this test is performed in a " + "clearcase view or source tree.~n" + "Need version numbers on the kernel and " + "stdlib directories!~n", + []), Res = {skip, - "Test case only partially run since it is run " - "in a clearcase view or in a source tree. " - "Need an installed system to complete this test."} + "Test case only partially run since it is run " + "in a clearcase view or in a source tree. " + "Need an installed system to complete this test."} end, - ?line ?t:timetrap_cancel(Dog), Res. create_boot(Config) -> - ?line {ok, OldDir} = file:get_cwd(), - ?line {LatestDir, LatestName, KernelVsn, StdlibVsn} = + {ok, OldDir} = file:get_cwd(), + {LatestDir, LatestName, KernelVsn, StdlibVsn} = create_script(Config), LibDir = code:lib_dir(), - ?line ok = file:set_cwd(LatestDir), - ?line ok = systools:make_script(LatestName, - [{variables, [{"TEST_VAR", LibDir}]}]), - ?line ok = file:set_cwd(OldDir), + ok = file:set_cwd(LatestDir), + ok = systools:make_script(LatestName, + [{variables, [{"TEST_VAR", LibDir}]}]), + ok = file:set_cwd(OldDir), {LatestDir ++ "/" ++ LatestName, LibDir, KernelVsn, StdlibVsn}. is_real_system(KernelVsn, StdlibVsn) -> LibDir = code:lib_dir(), - filelib:is_dir(filename:join(LibDir, "kernel"++KernelVsn)) andalso - filelib:is_dir(filename:join(LibDir, "stdlib"++StdlibVsn)). - + filelib:is_dir(filename:join(LibDir, "kernel-"++KernelVsn)) andalso + filelib:is_dir(filename:join(LibDir, "stdlib-"++StdlibVsn)). + %% ------------------------------------------------ %% Slave executes erlang:halt() on master nodedown. %% Therefore the slave process must be killed %% before restart. %% ------------------------------------------------ -many_restarts(doc) -> []; -many_restarts(suite) -> - case ?t:os_type() of - {Fam, _} when Fam == unix; Fam == win32 -> - {req, [distribution, {local_slave_nodes, 1}, {time, 5}]}; - _ -> - {skip, "Only run on unix and win32"} - end; +many_restarts() -> + [{timetrap,{minutes,8}}]. many_restarts(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(480)), - ?line {ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC), - ?line loop_restart(30,Node,rpc:call(Node,erlang,whereis,[error_logger])), - ?line loose_node:stop(Node), - ?line ?t:timetrap_cancel(Dog), + {ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC), + loop_restart(50,Node,rpc:call(Node,erlang,whereis,[error_logger])), + loose_node:stop(Node), ok. loop_restart(0,_,_) -> ok; loop_restart(N,Node,EHPid) -> - ?line erlang:monitor_node(Node, true), - ?line ok = rpc:call(Node, init, restart, []), - ?line receive - {nodedown, Node} -> - ok - after 10000 -> - loose_node:stop(Node), - ?t:fail(not_stopping) - end, - ?line ok = wait_for(30, Node, EHPid), - ?line loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[error_logger])). + erlang:monitor_node(Node, true), + ok = rpc:call(Node, init, restart, []), + receive + {nodedown, Node} -> + ok + after 10000 -> + loose_node:stop(Node), + ct:fail(not_stopping) + end, + ok = wait_for(30, Node, EHPid), + loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[error_logger])). wait_for(0,Node,_) -> loose_node:stop(Node), error; wait_for(N,Node,EHPid) -> - ?line case rpc:call(Node, erlang, whereis, [error_logger]) of + case rpc:call(Node, erlang, whereis, [error_logger]) of Pid when is_pid(Pid), Pid =/= EHPid -> - %% ?line erlang:display(ok), - ?line ok; + %% erlang:display(ok), + ok; _X -> - %% ?line erlang:display(_X), - %% ?line Procs = rpc:call(Node, erlang, processes, []), - %% ?line erlang:display(Procs), - %% case is_list(Procs) of - %% true -> - %% ?line [(catch erlang:display( - %% rpc:call(Node, - %% erlang, - %% process_info, - %% [Y,registered_name]))) - %% || Y <- Procs]; - %% _ -> - %% ok - %% end, - receive - after 100 -> - ok - end, - ?line wait_for(N-1,Node,EHPid) - end. + %% erlang:display(_X), + %% Procs = rpc:call(Node, erlang, processes, []), + %% erlang:display(Procs), + %% case is_list(Procs) of + %% true -> + %% [(catch erlang:display( + %% rpc:call(Node, + %% erlang, + %% process_info, + %% [Y,registered_name]))) + %% || Y <- Procs]; + %% _ -> + %% ok + %% end, + receive + after 100 -> + ok + end, + wait_for(N-1,Node,EHPid) + end. %% ------------------------------------------------ %% Slave executes erlang:halt() on master nodedown. %% Therefore the slave process must be killed %% before restart. %% ------------------------------------------------ -restart(doc) -> []; -restart(suite) -> - case ?t:os_type() of - {Fam, _} when Fam == unix; Fam == win32 -> - {req, [distribution, {local_slave_nodes, 1}, {time, 5}]}; - _ -> - {skip, "Only run on unix and win32"} - end; restart(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(40)), - ?line Args = args(), + Args = args(), + + Pa = " -pa " ++ filename:dirname(code:which(?MODULE)), %% Currently test_server:start_node cannot be used. The restarted %% node immediately halts due to the implementation of %% test_server:start_node. - ?line {ok, Node} = loose_node:start(init_test, Args, ?DEFAULT_TIMEOUT_SEC), + {ok, Node} = loose_node:start(init_test, Args ++ Pa, ?DEFAULT_TIMEOUT_SEC), %% Ok, the node is up, now the real test test begins. - ?line erlang:monitor_node(Node, true), - ?line InitPid = rpc:call(Node, erlang, whereis, [init]), - ?line Procs = rpc:call(Node, erlang, processes, []), - ?line MaxPid = lists:last(Procs), - ?line ok = rpc:call(Node, init, restart, []), - ?line receive - {nodedown, Node} -> - ok - after 10000 -> - loose_node:stop(Node), - ?t:fail(not_stopping) - end, - ?line ok = wait_restart(30, Node), + erlang:monitor_node(Node, true), + SysProcs0 = rpc:call(Node, ?MODULE, find_system_processes, []), + [InitPid, PurgerPid, LitCollectorPid, DirtyCodePid] = SysProcs0, + InitPid = rpc:call(Node, erlang, whereis, [init]), + PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]), + Procs = rpc:call(Node, erlang, processes, []), + MaxPid = lists:last(Procs), + ok = rpc:call(Node, init, restart, []), + receive + {nodedown, Node} -> + ok + after 10000 -> + loose_node:stop(Node), + ct:fail(not_stopping) + end, + ok = wait_restart(30, Node), + + SysProcs1 = rpc:call(Node, ?MODULE, find_system_processes, []), + [InitPid1, PurgerPid1, LitCollectorPid1, DirtyCodePid1] = SysProcs1, %% Still the same init process! - ?line InitPid1 = rpc:call(Node, erlang, whereis, [init]), + InitPid1 = rpc:call(Node, erlang, whereis, [init]), InitP = pid_to_list(InitPid), - ?line InitP = pid_to_list(InitPid1), - - ?line NewProcs0 = rpc:call(Node, erlang, processes, []), - NewProcs = lists:delete(InitPid1, NewProcs0), - ?line case check_processes(NewProcs, MaxPid) of - true -> - ok; - _ -> - loose_node:stop(Node), - ?t:fail(processes_not_greater) - end, + InitP = pid_to_list(InitPid1), + + %% and same purger process! + PurgerPid1 = rpc:call(Node, erlang, whereis, [erts_code_purger]), + PurgerP = pid_to_list(PurgerPid), + PurgerP = pid_to_list(PurgerPid1), + + %% and same literal area collector process! + case LitCollectorPid of + undefined -> undefined = LitCollectorPid1; + _ -> + LitCollectorP = pid_to_list(LitCollectorPid), + LitCollectorP = pid_to_list(LitCollectorPid1) + end, + + %% and same dirty process code checker process! + case DirtyCodePid of + undefined -> undefined = DirtyCodePid1; + _ -> + DirtyCodeP = pid_to_list(DirtyCodePid), + DirtyCodeP = pid_to_list(DirtyCodePid1) + end, + + NewProcs0 = rpc:call(Node, erlang, processes, []), + NewProcs = NewProcs0 -- SysProcs1, + case check_processes(NewProcs, MaxPid) of + true -> + ok; + _ -> + loose_node:stop(Node), + ct:fail(processes_not_greater) + end, %% Test that, for instance, the same argument still exists. - ?line case rpc:call(Node, init, get_argument, [c]) of - {ok, [["4", "5", "6"], ["7", "8", "9"]]} -> - ok; - _ -> - loose_node:stop(Node), - ?t:fail({get_argument, restart_fail}) - end, + case rpc:call(Node, init, get_argument, [c]) of + {ok, [["4", "5", "6"], ["7", "8", "9"]]} -> + ok; + _ -> + loose_node:stop(Node), + ct:fail({get_argument, restart_fail}) + end, loose_node:stop(Node), - ?line ?t:timetrap_cancel(Dog), ok. +-record(sys_procs, {init, + code_purger, + literal_collector, + dirty_proc_checker}). + +find_system_processes() -> + find_system_procs(processes(), #sys_procs{}). + +find_system_procs([], SysProcs) -> + [SysProcs#sys_procs.init, + SysProcs#sys_procs.code_purger, + SysProcs#sys_procs.literal_collector, + SysProcs#sys_procs.dirty_proc_checker]; +find_system_procs([P|Ps], SysProcs) -> + case process_info(P, initial_call) of + {initial_call,{otp_ring0,start,2}} -> + undefined = SysProcs#sys_procs.init, + find_system_procs(Ps, SysProcs#sys_procs{init = P}); + {initial_call,{erts_code_purger,start,0}} -> + undefined = SysProcs#sys_procs.code_purger, + find_system_procs(Ps, SysProcs#sys_procs{code_purger = P}); + {initial_call,{erts_literal_area_collector,start,0}} -> + undefined = SysProcs#sys_procs.literal_collector, + find_system_procs(Ps, SysProcs#sys_procs{literal_collector = P}); + {initial_call,{erts_dirty_process_code_checker,start,0}} -> + undefined = SysProcs#sys_procs.dirty_proc_checker, + find_system_procs(Ps, SysProcs#sys_procs{dirty_proc_checker = P}); + _ -> + find_system_procs(Ps, SysProcs) + end. + wait_restart(0, _Node) -> - ?t:fail(not_restarted); + ct:fail(not_restarted); wait_restart(N, Node) -> case net_adm:ping(Node) of pong -> ok; _ -> - ?t:sleep(1000), + ct:sleep(1000), wait_restart(N - 1, Node) end. @@ -474,124 +495,112 @@ apid(Pid) -> %% The reboot facility using heart is tested %% in the heart_SUITE. %% ------------------------------------------------ -reboot(doc) -> []; -reboot(suite) -> {req, [distribution, {local_slave_nodes, 1}]}; reboot(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(40)), - Args = args(), - ?line {ok, Node} = start_node(init_test, Args), + {ok, Node} = start_node(init_test, Args), erlang:monitor_node(Node, true), - ?line ok = rpc:call(Node, init, reboot, []), - ?line receive - {nodedown, Node} -> - ok - after 10000 -> - stop_node(Node), - ?t:fail(not_stopping) - end, - ?t:sleep(5000), - ?line case net_adm:ping(Node) of - pang -> - ok; - _ -> - stop_node(Node), - ?t:fail(system_rebooted) - end, - ?line ?t:timetrap_cancel(Dog), + ok = rpc:call(Node, init, reboot, []), + receive + {nodedown, Node} -> + ok + after 10000 -> + stop_node(Node), + ct:fail(not_stopping) + end, + ct:sleep(5000), + case net_adm:ping(Node) of + pang -> + ok; + _ -> + stop_node(Node), + ct:fail(system_rebooted) + end, ok. %% ------------------------------------------------ %% %% ------------------------------------------------ -stop(doc) -> []; -stop(suite) -> []; +stop_status(Config) when is_list(Config) -> + badarg = catch_stop([65,[66],67]), % flat strings only + badarg = catch_stop([65, 666, 67]), % only bytes in string + badarg = catch_stop(abort), % 'abort' not allowed + badarg = catch_stop(true), % other atoms not allowed + badarg = catch_stop(-1), % no negative statuses + ok. + +catch_stop(Status) -> + try init:stop(Status) catch error:badarg -> badarg end. + +%% ------------------------------------------------ +%% +%% ------------------------------------------------ stop(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(20)), Args = args(), - ?line {ok, Node} = start_node(init_test, Args), + {ok, Node} = start_node(init_test, Args), erlang:monitor_node(Node, true), - ?line ok = rpc:call(Node, init, reboot, []), - ?line receive - {nodedown, Node} -> - ok - after 10000 -> - stop_node(Node), - ?t:fail(not_stopping) - end, - ?t:sleep(5000), - ?line case net_adm:ping(Node) of - pang -> - ok; - _ -> - stop_node(Node), - ?t:fail(system_rebooted) - end, - ?line ?t:timetrap_cancel(Dog), + ok = rpc:call(Node, init, reboot, []), + receive + {nodedown, Node} -> + ok + after 10000 -> + stop_node(Node), + ct:fail(not_stopping) + end, + ct:sleep(5000), + case net_adm:ping(Node) of + pang -> + ok; + _ -> + stop_node(Node), + ct:fail(system_rebooted) + end, ok. %% ------------------------------------------------ %% %% ------------------------------------------------ -get_status(doc) -> []; -get_status(suite) -> []; get_status(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(10)), - ?line ?t:timetrap_cancel(Dog), + {Start, _} = init:get_status(), - ?line {Start, _} = init:get_status(), %% Depending on how the test_server is started Start has %% different values. staring if test_server started with %% -s flag. - ?line case lists:member(Start, [started, starting]) of - true -> - ok; - _ -> - ?t:fail(get_status) - end. + case lists:member(Start, [started, starting]) of + true -> + ok; + _ -> + ct:fail(get_status) + end. %% ------------------------------------------------ %% %% ------------------------------------------------ -script_id(doc) -> []; -script_id(suite) -> []; script_id(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(10)), - - ?line {Name, Vsn} = init:script_id(), - ?line if - is_list(Name), is_list(Vsn) -> - ok; - true -> - ?t:fail(not_standard_script) - end, - ?line ?t:timetrap_cancel(Dog), + {Name, Vsn} = init:script_id(), + if + is_list(Name), is_list(Vsn) -> + ok; + true -> + ct:fail(not_standard_script) + end, ok. %% ------------------------------------------------ %% Start the slave system with -boot flag. %% ------------------------------------------------ -boot1(doc) -> []; -boot1(suite) -> {req, [distribution, {local_slave_nodes, 1}, {time, 35}]}; boot1(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:seconds(80)), Args = args() ++ " -boot start_sasl", - ?line {ok, Node} = start_node(init_test, Args), - ?line stop_node(Node), + {ok, Node} = start_node(init_test, Args), + stop_node(Node), %% Try to start with non existing boot file. Args1 = args() ++ " -boot dummy_script", - ?line {error, timeout} = start_node(init_test, Args1), + {error, timeout} = start_node(init_test, Args1), - ?line ?t:timetrap_cancel(Dog), ok. -boot2(doc) -> []; -boot2(suite) -> {req, [distribution, {local_slave_nodes, 1}, {time, 35}]}; boot2(Config) when is_list(Config) -> - Dog = ?t:timetrap(?t:seconds(80)), - %% Absolute boot file name Boot = filename:join([code:root_dir(), "bin", "start_sasl"]), @@ -604,9 +613,9 @@ boot2(Config) when is_list(Config) -> %% Absolute boot file name for Windows -- all slashes are %% converted to backslashes. Win_boot = lists:map(fun - ($/) -> $\\; - (C) -> C - end, Boot), + ($/) -> $\\; + (C) -> C + end, Boot), Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"", {ok, Node2} = start_node(init_test, Args2), stop_node(Node2); @@ -614,16 +623,15 @@ boot2(Config) when is_list(Config) -> ok end, - ?t:timetrap_cancel(Dog), ok. %% Misc. functions start_node(Name, Param) -> - ?t:start_node(Name, slave, [{args, Param}]). + test_server:start_node(Name, slave, [{args, Param}]). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). from(H, [H | T]) -> T; from(H, [_ | T]) -> from(H, T); @@ -639,18 +647,18 @@ long_args(A) -> [A])). create_script(Config) -> - ?line PrivDir = ?config(priv_dir,Config), - ?line Name = PrivDir ++ "boot_var_test", - ?line Apps = application_controller:which_applications(), - ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), - ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), - ?line {ok,Fd} = file:open(Name ++ ".rel", [write]), - ?line io:format(Fd, - "{release, {\"Test release 3\", \"P2A\"}, \n" - " {erts, \"4.4\"}, \n" - " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n", - [KernelVer,StdlibVer]), - ?line file:close(Fd), + PrivDir = proplists:get_value(priv_dir,Config), + Name = PrivDir ++ "boot_var_test", + Apps = application_controller:which_applications(), + {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), + {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), + {ok,Fd} = file:open(Name ++ ".rel", [write]), + io:format(Fd, + "{release, {\"Test release 3\", \"P2A\"}, \n" + " {erts, \"4.4\"}, \n" + " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n", + [KernelVer,StdlibVer]), + file:close(Fd), {filename:dirname(Name), filename:basename(Name), - KernelVer, StdlibVer}. + KernelVer, StdlibVer}. diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl index 8adae1f606..298a364a91 100644 --- a/lib/kernel/test/interactive_shell_SUITE.erl +++ b/lib/kernel/test/interactive_shell_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2016. 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,7 +18,7 @@ %% %CopyrightEnd% %% -module(interactive_shell_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, get_columns_and_rows/1, exit_initial/1, job_control_local/1, @@ -30,15 +30,14 @@ -export([toerl_server/3]). init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:minutes(3)), - [{watchdog,Dog}|Config]. - -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). + Config. +end_per_testcase(_Func, _Config) -> + ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,3}}]. all() -> [get_columns_and_rows, exit_initial, job_control_local, @@ -55,7 +54,7 @@ init_per_suite(Config) -> [{default_shell,DefShell},{term,Term}|Config]. end_per_suite(Config) -> - Term = ?config(term,Config), + Term = proplists:get_value(term,Config), os:putenv("TERM",Term), ok. @@ -66,68 +65,66 @@ end_per_group(_GroupName, Config) -> Config. -%-define(DEBUG,1). +%%-define(DEBUG,1). -ifdef(DEBUG). -define(dbg(Data),erlang:display(Data)). -else. -define(dbg(Data),noop). -endif. -get_columns_and_rows(suite) -> []; -get_columns_and_rows(doc) -> ["Test that the shell can access columns and rows"]; +%% Test that the shell can access columns and rows. get_columns_and_rows(Config) when is_list(Config) -> case proplists:get_value(default_shell,Config) of old -> %% Old shell tests ?dbg(old_shell), - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline,"io:columns()."}, - {getline_re,".*{error,enotsup}"}, - {putline,"io:rows()."}, - {getline_re,".*{error,enotsup}"} - - ],[]), - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline,"io:columns()."}, - {getline_re,".*{ok,90}"}, - {putline,"io:rows()."}, - {getline_re,".*{ok,40}"}], - [], - "stty rows 40; stty columns 90; "); + rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline,"io:columns()."}, + {getline_re,".*{error,enotsup}"}, + {putline,"io:rows()."}, + {getline_re,".*{error,enotsup}"} + + ],[]), + rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline,"io:columns()."}, + {getline_re,".*{ok,90}"}, + {putline,"io:rows()."}, + {getline_re,".*{ok,40}"}], + [], + "stty rows 40; stty columns 90; "); new -> - % New shell tests + %% New shell tests ?dbg(new_shell), - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline,"io:columns()."}, - %% Behaviour change in R12B-5, returns 80 - %% {getline,"{error,enotsup}"}, - {getline,"{ok,80}"}, - {putline,"io:rows()."}, - %% Behaviour change in R12B-5, returns 24 - %% {getline,"{error,enotsup}"} - {getline,"{ok,24}"} - ],[]), - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline,"io:columns()."}, - {getline,"{ok,90}"}, - {putline,"io:rows()."}, - {getline,"{ok,40}"}], - [], - "stty rows 40; stty columns 90; ") + rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline,"io:columns()."}, + %% Behaviour change in R12B-5, returns 80 + %% {getline,"{error,enotsup}"}, + {getline,"{ok,80}"}, + {putline,"io:rows()."}, + %% Behaviour change in R12B-5, returns 24 + %% {getline,"{error,enotsup}"} + {getline,"{ok,24}"} + ],[]), + rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline,"io:columns()."}, + {getline,"{ok,90}"}, + {putline,"io:rows()."}, + {getline,"{ok,40}"}], + [], + "stty rows 40; stty columns 90; ") end. - - -exit_initial(suite) -> []; -exit_initial(doc) -> ["Tests that exit of initial shell restarts shell"]; + + +%% Tests that exit of initial shell restarts shell. exit_initial(Config) when is_list(Config) -> case proplists:get_value(default_shell,Config) of old -> @@ -152,9 +149,7 @@ exit_initial(Config) when is_list(Config) -> {getline_re,"35"}],[]) end. -job_control_local(suite) -> []; -job_control_local(doc) -> [ "Tests that local shell can be " - "started by means of job control" ]; +%% Tests that local shell can be started by means of job control. job_control_local(Config) when is_list(Config) -> case proplists:get_value(default_shell,Config) of old -> @@ -162,133 +157,130 @@ job_control_local(Config) when is_list(Config) -> {skip,"No new shell found"}; new -> %% New shell tests - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline,[7]}, - {sleep,timeout(short)}, - {putline,""}, - {getline," -->"}, - {putline,"s"}, - {putline,"c"}, - {putline_raw,""}, - {getline,"Eshell"}, - {putline_raw,""}, - {getline,"1>"}, - {putline,"35."}, - {getline,"35"}],[]) + rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline,[7]}, + {sleep,timeout(short)}, + {putline,""}, + {getline," -->"}, + {putline,"s"}, + {putline,"c"}, + {putline_raw,""}, + {getline,"Eshell"}, + {putline_raw,""}, + {getline,"1>"}, + {putline,"35."}, + {getline,"35"}],[]) end. -job_control_remote(suite) -> []; job_control_remote(doc) -> [ "Tests that remote shell can be " "started by means of job control" ]; job_control_remote(Config) when is_list(Config) -> case {node(),proplists:get_value(default_shell,Config)} of {nonode@nohost,_} -> - ?line exit(not_distributed); + exit(not_distributed); {_,old} -> {skip,"No new shell found"}; _ -> - ?line RNode = create_nodename(), - ?line MyNode = atom2list(node()), - ?line Pid = spawn_link(fun() -> - receive die -> - ok - end - end), - ?line PidStr = pid_to_list(Pid), - ?line register(kalaskula,Pid), - ?line CookieString = lists:flatten( - io_lib:format("~w", - [erlang:get_cookie()])), - ?line Res = rtnode([{putline,""}, - {putline, "erlang:get_cookie()."}, - {getline, CookieString}, - {putline,[7]}, - {sleep,timeout(short)}, - {putline,""}, - {getline," -->"}, - {putline,"r '"++MyNode++"'"}, - {putline,"c"}, - {putline_raw,""}, - {getline,"Eshell"}, - {sleep,timeout(short)}, - {putline_raw,""}, - {getline,"("++MyNode++")1>"}, - {putline,"whereis(kalaskula)."}, - {getline,PidStr}, - {sleep,timeout(short)}, % Race, known bug. - {putline_raw,"exit()."}, - {getline,"***"}, - {putline,[7]}, - {putline,""}, - {getline," -->"}, - {putline,"c 1"}, - {putline,""}, - {sleep,timeout(short)}, - {putline_raw,""}, - {getline,"("++RNode++")"}],RNode), - ?line Pid ! die, - ?line Res + RNode = create_nodename(), + MyNode = atom2list(node()), + Pid = spawn_link(fun() -> + receive die -> + ok + end + end), + PidStr = pid_to_list(Pid), + register(kalaskula,Pid), + CookieString = lists:flatten( + io_lib:format("~w", + [erlang:get_cookie()])), + Res = rtnode([{putline,""}, + {putline, "erlang:get_cookie()."}, + {getline, CookieString}, + {putline,[7]}, + {sleep,timeout(short)}, + {putline,""}, + {getline," -->"}, + {putline,"r '"++MyNode++"'"}, + {putline,"c"}, + {putline_raw,""}, + {getline,"Eshell"}, + {sleep,timeout(short)}, + {putline_raw,""}, + {getline,"("++MyNode++")1>"}, + {putline,"whereis(kalaskula)."}, + {getline,PidStr}, + {sleep,timeout(short)}, % Race, known bug. + {putline_raw,"exit()."}, + {getline,"***"}, + {putline,[7]}, + {putline,""}, + {getline," -->"}, + {putline,"c 1"}, + {putline,""}, + {sleep,timeout(short)}, + {putline_raw,""}, + {getline,"("++RNode++")"}],RNode), + Pid ! die, + Res end. -job_control_remote_noshell(suite) -> []; -job_control_remote_noshell(doc) -> - [ "Tests that remote shell can be " - "started by means of job control to -noshell node" ]; + +%% Tests that remote shell can be +%% started by means of job control to -noshell node. job_control_remote_noshell(Config) when is_list(Config) -> case {node(),proplists:get_value(default_shell,Config)} of {nonode@nohost,_} -> - ?line exit(not_distributed); + exit(not_distributed); {_,old} -> {skip,"No new shell found"}; _ -> - ?line RNode = create_nodename(), - ?line NSNode = start_noshell_node(interactive_shell_noshell), - ?line Pid = spawn_link(NSNode, fun() -> - receive die -> - ok - end - end), - ?line PidStr = rpc:call(NSNode,erlang,pid_to_list,[Pid]), - ?line true = rpc:call(NSNode,erlang,register,[kalaskula,Pid]), - ?line NSNodeStr = atom2list(NSNode), - ?line CookieString = lists:flatten( - io_lib:format("~w", - [erlang:get_cookie()])), - ?line Res = rtnode([{putline,""}, - {putline, "erlang:get_cookie()."}, - {getline, CookieString}, - {putline,[7]}, - {sleep,timeout(short)}, - {putline,""}, - {getline," -->"}, - {putline,"r '"++NSNodeStr++"'"}, - {putline,"c"}, - {putline_raw,""}, - {getline,"Eshell"}, - {sleep,timeout(short)}, - {putline_raw,""}, - {getline,"("++NSNodeStr++")1>"}, - {putline,"whereis(kalaskula)."}, - {getline,PidStr}, - {sleep,timeout(short)}, % Race, known bug. - {putline_raw,"exit()."}, - {getline,"***"}, - {putline,[7]}, - {putline,""}, - {getline," -->"}, - {putline,"c 1"}, - {putline,""}, - {sleep,timeout(short)}, - {putline_raw,""}, - {getline,"("++RNode++")"}],RNode), - ?line Pid ! die, - ?line stop_noshell_node(NSNode), - ?line Res + RNode = create_nodename(), + NSNode = start_noshell_node(interactive_shell_noshell), + Pid = spawn_link(NSNode, fun() -> + receive die -> + ok + end + end), + PidStr = rpc:call(NSNode,erlang,pid_to_list,[Pid]), + true = rpc:call(NSNode,erlang,register,[kalaskula,Pid]), + NSNodeStr = atom2list(NSNode), + CookieString = lists:flatten( + io_lib:format("~w", + [erlang:get_cookie()])), + Res = rtnode([{putline,""}, + {putline, "erlang:get_cookie()."}, + {getline, CookieString}, + {putline,[7]}, + {sleep,timeout(short)}, + {putline,""}, + {getline," -->"}, + {putline,"r '"++NSNodeStr++"'"}, + {putline,"c"}, + {putline_raw,""}, + {getline,"Eshell"}, + {sleep,timeout(short)}, + {putline_raw,""}, + {getline,"("++NSNodeStr++")1>"}, + {putline,"whereis(kalaskula)."}, + {getline,PidStr}, + {sleep,timeout(short)}, % Race, known bug. + {putline_raw,"exit()."}, + {getline,"***"}, + {putline,[7]}, + {putline,""}, + {getline," -->"}, + {putline,"c 1"}, + {putline,""}, + {sleep,timeout(short)}, + {putline_raw,""}, + {getline,"("++RNode++")"}],RNode), + Pid ! die, + stop_noshell_node(NSNode), + Res end. -ctrl_keys(suite) -> []; -ctrl_keys(doc) -> ["Tests various control keys"]; +%% Tests various control keys. ctrl_keys(_Conf) when is_list(_Conf) -> Cu=[$\^u], Cw=[$\^w], @@ -308,7 +300,7 @@ ctrl_keys(_Conf) when is_list(_Conf) -> {getline,"\"hello world\""}, {putline,"\"hello world\""++Cu++Cy++"."}, {getline,"\"hello world\""}] - ++wordLeft()++wordRight(),[]). + ++wordLeft()++wordRight(),[]). wordLeft() -> @@ -337,46 +329,46 @@ wordRight(Chars) -> rtnode(C,N) -> rtnode(C,N,[]). rtnode(Commands,Nodename,ErlPrefix) -> - ?line case get_progs() of - {error,_Reason} -> - ?line {skip,"No runerl present"}; - {RunErl,ToErl,Erl} -> - ?line case create_tempdir() of - {error, Reason2} -> - ?line {skip, Reason2}; - Tempdir -> - ?line SPid = - start_runerl_node(RunErl,ErlPrefix++"\\\""++Erl++"\\\"", - Tempdir,Nodename), - ?line CPid = start_toerl_server(ToErl,Tempdir), - ?line erase(getline_skipped), - ?line Res = - (catch get_and_put(CPid, Commands,1)), - ?line case stop_runerl_node(CPid) of - {error,_} -> - ?line CPid2 = - start_toerl_server - (ToErl,Tempdir), - ?line erase(getline_skipped), - ?line ok = get_and_put - (CPid2, - [{putline,[7]}, - {sleep, - timeout(short)}, - {putline,""}, - {getline," -->"}, - {putline,"s"}, - {putline,"c"}, - {putline,""}],1), - ?line stop_runerl_node(CPid2); - _ -> - ?line ok - end, - ?line wait_for_runerl_server(SPid), - ?line ok = rm_rf(Tempdir), - ?line ok = Res - end - end. + case get_progs() of + {error,_Reason} -> + {skip,"No runerl present"}; + {RunErl,ToErl,Erl} -> + case create_tempdir() of + {error, Reason2} -> + {skip, Reason2}; + Tempdir -> + SPid = + start_runerl_node(RunErl,ErlPrefix++"\\\""++Erl++"\\\"", + Tempdir,Nodename), + CPid = start_toerl_server(ToErl,Tempdir), + erase(getline_skipped), + Res = + (catch get_and_put(CPid, Commands,1)), + case stop_runerl_node(CPid) of + {error,_} -> + CPid2 = + start_toerl_server + (ToErl,Tempdir), + erase(getline_skipped), + ok = get_and_put + (CPid2, + [{putline,[7]}, + {sleep, + timeout(short)}, + {putline,""}, + {getline," -->"}, + {putline,"s"}, + {putline,"c"}, + {putline,""}],1), + stop_runerl_node(CPid2); + _ -> + ok + end, + wait_for_runerl_server(SPid), + ok = rm_rf(Tempdir), + ok = Res + end + end. timeout(long) -> 2 * timeout(normal); @@ -389,7 +381,7 @@ timeout(normal) -> start_noshell_node(Name) -> PADir = filename:dirname(code:which(?MODULE)), {ok, Node} = test_server:start_node(Name,slave,[{args," -noshell -pa "++ - PADir++" "}]), + PADir++" "}]), Node. stop_noshell_node(Node) -> test_server:stop_node(Node). @@ -397,20 +389,20 @@ stop_noshell_node(Node) -> rm_rf(Dir) -> try - {ok,List} = file:list_dir(Dir), - Files = [filename:join([Dir,X]) || X <- List], - [case file:list_dir(Y) of - {error, enotdir} -> - ok = file:delete(Y); - _ -> - ok = rm_rf(Y) - end || Y <- Files], - ok = file:del_dir(Dir), - ok + {ok,List} = file:list_dir(Dir), + Files = [filename:join([Dir,X]) || X <- List], + [case file:list_dir(Y) of + {error, enotdir} -> + ok = file:delete(Y); + _ -> + ok = rm_rf(Y) + end || Y <- Files], + ok = file:del_dir(Dir), + ok catch _:Exception -> {error, {Exception,Dir}} end. - + get_and_put(_CPid,[],_) -> ok; @@ -479,7 +471,7 @@ get_and_put(CPid, [{putline_raw, Line}|T],N) -> Timeout = timeout(normal), receive {send_line, ok} -> - get_and_put(CPid, T,N+1) + get_and_put(CPid, T,N+1) after Timeout -> error_logger:error_msg("~p: putline_raw timeout (~p) sending " "\"~s\" (command number ~p)~n", @@ -493,7 +485,7 @@ get_and_put(CPid, [{putline, Line}|T],N) -> Timeout = timeout(normal), receive {send_line, ok} -> - get_and_put(CPid, [{getline, []}|T],N) + get_and_put(CPid, [{getline, []}|T],N) after Timeout -> error_logger:error_msg("~p: putline timeout (~p) sending " "\"~s\" (command number ~p)~n[~p]~n", @@ -510,8 +502,8 @@ wait_for_runerl_server(SPid) -> after Timeout -> {error, timeout} end. - - + + stop_runerl_node(CPid) -> Ref = erlang:monitor(process, CPid), @@ -562,11 +554,11 @@ create_tempdir(Dir,X) when X > $Z, X < $a -> create_tempdir(Dir,$a); create_tempdir(Dir,X) when X > $z -> Estr = lists:flatten( - io_lib:format("Unable to create ~s, reason eexist", - [Dir++[$z]])), + io_lib:format("Unable to create ~s, reason eexist", + [Dir++[$z]])), {error, Estr}; create_tempdir(Dir0, Ch) -> - % Expect fairly standard unix. + %% Expect fairly standard unix. Dir = Dir0++[Ch], case file:make_dir(Dir) of {error, eexist} -> @@ -604,13 +596,13 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename) -> []; _ -> " -sname "++(if is_atom(Nodename) -> atom_to_list(Nodename); - true -> Nodename - end)++ + true -> Nodename + end)++ " -setcookie "++atom_to_list(erlang:get_cookie()) end, spawn(fun() -> os:cmd("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++" \""++ - Erl++XArg++"\"") + Erl++XArg++"\"") end). start_toerl_server(ToErl,Tempdir) -> @@ -668,7 +660,7 @@ toerl_loop(Port,Acc) -> _ -> toerl_loop(Port,[{Tag0,Data}|Acc]) end; - {Pid,{get_line,Timeout}} -> + {Pid,{get_line,Timeout}} -> case Acc of [] -> case get_data_within(Port,Timeout,[]) of @@ -717,10 +709,10 @@ toerl_loop(Port,Acc) -> Other -> {error, {unexpected, Other}} end. - + millistamp() -> - erlang:monotonic_time(milli_seconds). - + erlang:monotonic_time(millisecond). + get_data_within(Port, X, Acc) when X =< 0 -> ?dbg({get_data_within, X, Acc, ?LINE}), receive @@ -751,7 +743,7 @@ get_data_within(Port, Timeout, Acc) -> after Timeout -> timeout end. - + get_default_shell() -> try rtnode([{putline,""}, diff --git a/lib/kernel/test/kernel_SUITE.erl b/lib/kernel/test/kernel_SUITE.erl index 8ae2e4b23b..da56359294 100644 --- a/lib/kernel/test/kernel_SUITE.erl +++ b/lib/kernel/test/kernel_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2014. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. 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,21 +21,20 @@ %%% Kernel application test suite. %%%----------------------------------------------------------------- -module(kernel_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -% Test server specific exports +%% Test server specific exports -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([init_per_testcase/2, end_per_testcase/2]). -% Test cases must be exported. +%% Test cases must be exported. -export([app_test/1, appup_test/1]). -%% -%% all/1 -%% -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [app_test, appup_test]. @@ -61,15 +60,12 @@ init_per_testcase(_Case, Config) -> end_per_testcase(_Case, _Config) -> ok. -% -% Test cases starts here. -% -app_test(doc) -> - ["Tests the applications consistency."]; -app_test(suite) -> - []; +%% +%% Test cases starts here. +%% +%% Tests the applications consistency. app_test(Config) when is_list(Config) -> - ?line ok=?t:app_test(kernel), + ok=test_server:app_test(kernel), ok. diff --git a/lib/kernel/test/kernel_bench.spec b/lib/kernel/test/kernel_bench.spec new file mode 100644 index 0000000000..8de60dae31 --- /dev/null +++ b/lib/kernel/test/kernel_bench.spec @@ -0,0 +1 @@ +{groups,"../kernel_test",zlib_SUITE,[bench]}. diff --git a/lib/kernel/test/kernel_config_SUITE.erl b/lib/kernel/test/kernel_config_SUITE.erl index 4be44015c9..9a4578917d 100644 --- a/lib/kernel/test/kernel_config_SUITE.erl +++ b/lib/kernel/test/kernel_config_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. 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. @@ -19,13 +19,15 @@ %% -module(kernel_config_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, sync/1]). -export([init_per_suite/1, end_per_suite/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [sync]. @@ -40,13 +42,9 @@ end_per_group(_GroupName, Config) -> Config. -init_per_suite(doc) -> []; -init_per_suite(suite) -> []; init_per_suite(Config) when is_list(Config) -> Config. -end_per_suite(doc) -> []; -end_per_suite(suite) -> []; end_per_suite(Config) when is_list(Config) -> stop_node(init_test), Config. @@ -54,7 +52,7 @@ end_per_suite(Config) when is_list(Config) -> config(Fd) -> M = from($@, atom_to_list(node())), io:format(Fd, "[{kernel, [{sync_nodes_optional, ['cp1@~s','cp2@~s']}," - "{sync_nodes_timeout, 15000}]}].~n", + "{sync_nodes_timeout, 15000}]}].~n", [M, M]). from(H, [H | T]) -> T; @@ -67,12 +65,9 @@ from(_, []) -> []. %% Should be started in a CC view with: %% erl -sname XXX where XX not in [cp1, cp2] %%----------------------------------------------------------------- -sync(doc) -> []; -sync(suite) -> []; sync(Conf) when is_list(Conf) -> - ?line Dog = ?t:timetrap(?t:seconds(120)), - % Write a config file - Dir = ?config(priv_dir,Conf), + %% Write a config file + Dir = proplists:get_value(priv_dir,Conf), {ok, Fd} = file:open(Dir ++ "sys.config", [write]), config(Fd), file:close(Fd), @@ -81,34 +76,33 @@ sync(Conf) when is_list(Conf) -> %% Reset wall_clock {T1,_} = erlang:statistics(wall_clock), io:format("~p~n", [{t1, T1}]), - ?line Command = lists:concat([lib:progname(), - " -detached -sname cp1 ", - "-config ", Config, - " -env ERL_CRASH_DUMP erl_crash_dump.cp1"]), + Command = lists:concat([lib:progname(), + " -detached -sname cp1 ", + "-config ", Config, + " -env ERL_CRASH_DUMP erl_crash_dump.cp1"]), io:format("Command: ~s", [Command]), - ?line open_port({spawn, Command}, [stream]), + open_port({spawn, Command}, [stream]), io:format("started~n"), - ?line ?t:sleep(12000), + ct:sleep(12000), io:format("waited12~n"), - ?line Host = from($@, atom_to_list(node())), - ?line Cp1 = list_to_atom("cp1@"++Host), - ?line wait_for_node(Cp1), + Host = from($@, atom_to_list(node())), + Cp1 = list_to_atom("cp1@"++Host), + wait_for_node(Cp1), io:format("waitednode~n"), %% Check time since last call - ?line {TT, T} = erlang:statistics(wall_clock), + {TT, T} = erlang:statistics(wall_clock), io:format("~p~n", [{t2, {TT, T}}]), - ?line stop_node(cp1), + stop_node(cp1), if - TT-T1 < 15000 -> ?line ?t:fail({too_short_time, TT-T1}); + TT-T1 < 15000 -> ct:fail({too_short_time, TT-T1}); true -> ok end, - ?line ?t:timetrap_cancel(Dog), ok. wait_for_node(Node) -> case rpc:call(Node, init, get_status, []) of {started,_} -> ok; - {badrpc, R} -> ?line ?t:fail({rpc_failed, R}); + {badrpc, R} -> ct:fail({rpc_failed, R}); _Other -> wait_for_node(Node) end. diff --git a/lib/kernel/test/loose_node.erl b/lib/kernel/test/loose_node.erl index ba293a821a..cc3f9bbea0 100644 --- a/lib/kernel/test/loose_node.erl +++ b/lib/kernel/test/loose_node.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2016. 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. @@ -57,9 +57,16 @@ %% stop(Node) when is_atom(Node) -> + erlang:monitor_node(Node, true), rpc:cast(Node, erlang, halt, []), - io:format("Stopped loose node ~p~n", [Node]), - ok. + receive + {nodedown, Node} -> + io:format("Stopped loose node ~p~n", [Node]), + ok + after 10000 -> + io:format("Failed to stop loose node: ~p~n", [Node]), + {error, node_not_stopped} + end. start(Name, Args) -> start(Name, Args, -1). diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl new file mode 100644 index 0000000000..f3258ea520 --- /dev/null +++ b/lib/kernel/test/multi_load_SUITE.erl @@ -0,0 +1,419 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2017. 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(multi_load_SUITE). +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + basic_atomic_load/1,basic_errors/1,sticky_dir/1, + on_load_failing/1,ensure_modules_loaded/1, + native_code/1]). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("syntax_tools/include/merl.hrl"). + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. + +all() -> + [basic_atomic_load,basic_errors,sticky_dir,on_load_failing, + ensure_modules_loaded,native_code]. + +groups() -> + []. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +basic_atomic_load(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + Dir = filename:join(PrivDir, multi_load_sticky_dir), + _ = file:make_dir(Dir), + + OldPath = code:get_path(), + try + code:add_patha(Dir), + do_basic(Dir) + after + code:set_path(OldPath) + end, + + ok. + +do_basic(Dir) -> + MsVer1_0 = make_modules(5, versioned_module(1)), + MsVer1 = [{M,filename:absname(F, Dir),Bin} || {M,F,Bin} <- MsVer1_0], + _ = [ok = file:write_file(F, Bin) || {_,F,Bin} <- MsVer1], + + Ms = [M || {M,_,_} <- MsVer1], + [] = [loaded || M <- Ms, is_loaded(M)], + + ok = code:atomic_load(Ms), + _ = [1 = M:M() || M <- Ms], + _ = [F = code:which(M) || {M,F,_} <- MsVer1], + [] = [not_loaded || M <- Ms, not is_loaded(M)], + + MsVer2 = update_modules(Ms, versioned_module(2)), + {ok,Prepared} = code:prepare_loading(MsVer2), + ok = code:finish_loading(Prepared), + _ = [2 = M:M() || M <- Ms], + _ = [F = code:which(M) || {M,F,_} <- MsVer2], + [] = [not_loaded || M <- Ms, not is_loaded(M)], + + MsVer3 = update_modules(Ms, versioned_module(2)), + NotPurged = lists:sort([{M,not_purged} || M <- Ms]), + NotPurged = atomic_load_error(MsVer3, true), + + ok. + +versioned_module(Ver) -> + fun(Mod) -> + ?Q(["-module('@Mod@').\n", + "-export(['@Mod@'/0]).\n", + "'@Mod@'() -> _@Ver@.\n"]) + end. + +basic_errors(_Config) -> + atomic_load_fc([42]), + atomic_load_fc([{"mod","file","bin"}]), + + finish_loading_fc(atom), + {ok,{PrepTag,_}} = code:prepare_loading([code]), + finish_loading_fc({PrepTag,[x]}), + finish_loading_fc({PrepTag,[{m,{<<>>,"",<<>>}}]}), + Prep = prepared_with_wrong_magic_bin(), + finish_loading_fc(Prep), + + [{x,badfile}] = atomic_load_error([{x,"x",<<"bad">>}], false), + [{a,badfile},{some_nonexistent_file,nofile}] = + atomic_load_error([some_nonexistent_file,{a,"a",<<>>}], + false), + + %% Modules mentioned more than once. + Mods = make_modules(2, fun basic_module/1), + Ms = [M || {M,_,_} <- Mods], + DupMods = Mods ++ [mnesia] ++ Mods ++ [mnesia], + DupErrors0 = lists:sort([mnesia|Ms]), + DupErrors = [{M,duplicated} || M <- DupErrors0], + DupErrors = atomic_load_error(DupMods, false), + + ok. + +atomic_load_fc(L) -> + {'EXIT',{function_clause,[{code,atomic_load,[L],_}|_]}} = + (catch code:atomic_load(L)), + {'EXIT',{function_clause,[{code,prepare_loading,[L],_}|_]}} = + (catch code:prepare_loading(L)). + +finish_loading_fc(Term) -> + {'EXIT',{function_clause,[{code,finish_loading,[Term],_}|_]}} = + (catch code:finish_loading(Term)). + +prepared_with_wrong_magic_bin() -> + {ok,Prep} = code:prepare_loading([?MODULE]), + prep_magic(Prep). + +prep_magic([H|T]) -> + [prep_magic(H)|prep_magic(T)]; +prep_magic(Tuple) when is_tuple(Tuple) -> + L = prep_magic(tuple_to_list(Tuple)), + list_to_tuple(L); +prep_magic(Ref) when is_reference(Ref) -> + try erlang:has_prepared_code_on_load(Ref) of + false -> + %% Create a different kind of magic ref. + ets:match_spec_compile([{'_',[true],['$_']}]) + catch + _:_ -> + Ref + end; +prep_magic(Other) -> + Other. + +sticky_dir(_Config) -> + Mod0 = make_module(lists, fun basic_module/1), + Mod1 = make_module(gen_server, fun basic_module/1), + Ms = [Mod0,Mod1], + SD = sticky_directory, + StickyErrors = [{gen_server,SD},{lists,SD}], + StickyErrors = atomic_load_error(Ms, true), + + ok. + +on_load_failing(_Config) -> + OnLoad = make_modules(1, fun on_load_module/1), + [{OnLoadMod,_,_}] = OnLoad, + Ms = make_modules(10, fun basic_module/1) ++ OnLoad, + + %% Fail because there is a module with on_load in the list. + on_load_failure(OnLoadMod, Ms), + on_load_failure(OnLoadMod, [lists:last(Ms)]), + + %% Fail because there already is a pending on_load. + [{HangingOnLoad,_,_}|_] = Ms, + spawn_hanging_on_load(HangingOnLoad), + NoOnLoadMs = lists:droplast(Ms), + {error,[{HangingOnLoad,pending_on_load}]} = + code:atomic_load(NoOnLoadMs), + hanging_on_load ! stop_hanging_and_unload, + + ok. + +on_load_failure(OnLoadMod, Ms) -> + [{OnLoadMod,on_load_not_allowed}] = atomic_load_error(Ms, false). + +spawn_hanging_on_load(Mod) -> + {Mod,Name,Bin} = make_module(Mod, "unknown", + fun(_) -> + hanging_on_load_module(Mod) + end), + spawn_link(fun() -> + {error,on_load_failure} = + code:load_binary(Mod, Name, Bin) + end). + +hanging_on_load_module(Mod) -> + ?Q(["-module('@Mod@').\n", + "-on_load(hang/0).\n", + "hang() ->\n" + " register(hanging_on_load, self()),\n" + " receive _ -> unload end.\n"]). + +ensure_modules_loaded(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + Dir = filename:join(PrivDir, multi_load_ensure_modules_loaded), + _ = file:make_dir(Dir), + + OldPath = code:get_path(), + try + code:add_patha(Dir), + do_ensure_modules_loaded(Dir) + after + code:set_path(OldPath) + end, + + ok. + +do_ensure_modules_loaded(Dir) -> + %% Create a dummy "lists" module and place it in our code path. + {lists,ListsFile,ListsCode} = make_module(lists, fun basic_module/1), + ok = file:write_file(filename:absname(ListsFile, Dir), ListsCode), + {error,sticky_directory} = code:load_file(lists), + + %% Make a new module that we can load. + Mod = make_module_file(Dir, fun basic_module/1), + false = is_loaded(Mod), + + %% Make a new module with an on_load function. + OLMod = make_module_file(Dir, fun on_load_module/1), + false = is_loaded(OLMod), + + %% lists should not be loaded again; Mod and OLMod should be + %% loaded. ?MODULE should not be reloaded, but there is no easy + %% way to test that. Repeating modules is OK. + ok = code:ensure_modules_loaded([?MODULE,lists,Mod,OLMod, + Mod,OLMod,Mod,lists]), + last = lists:last([last]), + true = is_loaded(Mod), + ok = Mod:Mod(), + true = is_loaded(OLMod), + _ = OLMod:module_info(), + + %% Unload the modules that were loaded. + [begin + code:purge(M), + code:delete(M), + code:purge(M), + false = is_loaded(M) + end || M <- [Mod,OLMod]], + + %% If there are some errors, all other modules should be loaded + %% anyway. + [{BadMod,BadFile,_}] = make_modules(1, fun basic_module/1), + ok = file:write_file(filename:absname(BadFile, Dir), <<"bad_code">>), + BadOLMod = make_module_file(Dir, fun failing_on_load_module/1), + BadEgg = bad__egg, + NativeMod = a_native_module, + NativeModFile = atom_to_list(NativeMod) ++ ".beam", + {NativeMod,_,NativeCode} = make_module(NativeMod, NativeModFile, + fun basic_module/1, [native]), + ok = file:write_file(filename:absname(NativeModFile, Dir), NativeCode), + ModulesToLoad = [OLMod,?MODULE,Mod,BadOLMod,NativeMod, + BadEgg,BadMod,lists], + {error,Error0} = code:ensure_modules_loaded(ModulesToLoad), + Error = lists:sort([{BadEgg,nofile}, + {BadMod,badfile}, + {BadOLMod,on_load_failure}]), + Error = lists:sort(Error0), + true = is_loaded(Mod), + true = is_loaded(OLMod), + true = is_loaded(NativeMod), + + ModuleNative = case erlang:system_info(hipe_architecture) of + undefined -> false; + _ -> true + end, + ModuleNative = NativeMod:module_info(native), + + ok. + +failing_on_load_module(Mod) -> + ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> fail.\n"]). + +native_code(_Config) -> + case erlang:system_info(hipe_architecture) of + undefined -> + {skip,"No native support"}; + _ -> + do_native_code() + end. + +do_native_code() -> + CalledMod = native_called_module, + CallingMod = native_calling_module, + + %% Create a module in native code that calls another module. + CallingMod = make_and_load(CallingMod, + calling_module_fun(CalledMod), + [native]), + + %% Create a threaded-code module. + _ = make_and_load(CalledMod, called_module_fun(42), []), + 42 = CallingMod:call(), + + %% Now replace it with a changed module in native code. + code:purge(CalledMod), + make_and_load(CalledMod, called_module_fun(43), [native]), + true = test_server:is_native(CalledMod), + 43 = CallingMod:call(), + + %% Reload the called module and call it. + code:purge(CalledMod), + ModVer3 = make_module(CalledMod, "", called_module_fun(changed)), + ok = code:atomic_load([ModVer3]), + false = test_server:is_native(CalledMod), + changed = CallingMod:call(), + code:purge(CalledMod), + + ok. + +make_and_load(Mod, Fun, Opts) -> + {Mod,_,Code} = make_module(Mod, "", Fun, Opts), + {module,Mod} = code:load_binary(Mod, "", Code), + Mod. + +calling_module_fun(Called) -> + fun(Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([call/0]).\n", + "call() -> _@Called@:f().\n"]) + end. + +called_module_fun(Ret) -> + fun(Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([f/0]).\n", + "f() -> _@Ret@.\n"]) + end. + +%%% +%%% Common utilities +%%% + +atomic_load_error(Modules, ErrorInFinishLoading) -> + {error,Errors0} = code:atomic_load(Modules), + {Errors1,Bool} = + case code:prepare_loading(Modules) of + {ok,Prepared} -> + {error,Es0} = code:finish_loading(Prepared), + {Es0,true}; + {error,Es0} -> + {Es0,false} + end, + Errors = lists:sort(Errors0), + Errors = lists:sort(Errors1), + case {ErrorInFinishLoading,Bool} of + {B,B} -> + Errors; + {false,true} -> + ct:fail("code:prepare_loading/1 should have failed"); + {true,false} -> + ct:fail("code:prepare_loading/1 should have succeeded") + end. + +is_loaded(Mod) -> + case erlang:module_loaded(Mod) of + false -> + false = code:is_loaded(Mod); + true -> + {file,_} = code:is_loaded(Mod), + true + end. + +basic_module(Mod) -> + ?Q(["-module('@Mod@').\n" + "-export(['@Mod@'/0]).\n", + "'@Mod@'() -> ok."]). + +on_load_module(Mod) -> + ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> ok.\n"]). + +make_module_file(Dir, Fun) -> + [{Mod,File,Code}] = make_modules(1, Fun), + ok = file:write_file(filename:absname(File, Dir), Code), + Mod. + +make_modules(0, _) -> + []; +make_modules(N, Fun) -> + U = erlang:unique_integer([positive]), + ModName = "m__" ++ integer_to_list(N) ++ "_" ++ integer_to_list(U), + Mod = list_to_atom(ModName), + ModItem = make_module(Mod, Fun), + [ModItem|make_modules(N-1, Fun)]. + +update_modules(Ms, Fun) -> + [make_module(M, Fun) || M <- Ms]. + +make_module(Mod, Fun) -> + Filename = atom_to_list(Mod) ++ ".beam", + make_module(Mod, Filename, Fun). + +make_module(Mod, Filename, Fun) -> + make_module(Mod, Filename, Fun, []). + +make_module(Mod, Filename, Fun, Opts) -> + Tree = Fun(Mod), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree, Opts), + {Mod,Filename,Code}. diff --git a/lib/kernel/test/myApp.erl b/lib/kernel/test/myApp.erl index add1d5d500..0318e55c52 100644 --- a/lib/kernel/test/myApp.erl +++ b/lib/kernel/test/myApp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 29d8d10262..a0bcde68db 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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,17 +20,25 @@ -module(os_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). + init_per_group/2,end_per_group/2, + init_per_testcase/2,end_per_testcase/2]). -export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1, - find_executable/1, unix_comment_in_command/1, deep_list_command/1, evil/1]). + find_executable/1, unix_comment_in_command/1, deep_list_command/1, + large_output_command/1, background_command/0, background_command/1, + message_leak/1, close_stdin/0, close_stdin/1, max_size_command/1, + perf_counter_api/1]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command, - find_executable, unix_comment_in_command, deep_list_command, evil]. + find_executable, unix_comment_in_command, deep_list_command, + large_output_command, background_command, message_leak, + close_stdin, max_size_command, perf_counter_api]. groups() -> []. @@ -47,16 +55,27 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +init_per_testcase(TC, Config) + when TC =:= background_command; TC =:= close_stdin -> + case os:type() of + {win32, _} -> + {skip,"Should not work on windows"}; + _ -> + Config + end; +init_per_testcase(_TC,Config) -> + Config. + +end_per_testcase(_,_Config) -> + ok. -space_in_cwd(doc) -> - "Test that executing a command in a current working directory " - "with space in its name works."; -space_in_cwd(suite) -> []; +%% Test that executing a command in a current working directory +%% with space in its name works. space_in_cwd(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line Dirname = filename:join(PrivDir, "cwd with space"), - ?line ok = file:make_dir(Dirname), - ?line ok = file:set_cwd(Dirname), + PrivDir = proplists:get_value(priv_dir, Config), + Dirname = filename:join(PrivDir, "cwd with space"), + ok = file:make_dir(Dirname), + ok = file:set_cwd(Dirname), %% Using `more' gives the almost the same result on both Unix and Windows. @@ -67,70 +86,66 @@ space_in_cwd(Config) when is_list(Config) -> "more </dev/null" end, - ?line case os:cmd(Cmd) of - [] -> ok; % Unix. - "\r\n" -> ok; % Windows. - Other -> - ?line test_server:fail({unexpected, Other}) - end, + case os:cmd(Cmd) of + [] -> ok; % Unix. + "\r\n" -> ok; % Windows. + Other -> + ct:fail({unexpected, Other}) + end, - ?t:sleep(5), - ?line [] = receive_all(), + ct:sleep(5), + [] = receive_all(), ok. -quoting(doc) -> "Test that various ways of quoting arguments work."; -quoting(suite) -> []; +%% Test that various ways of quoting arguments work. quoting(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line Echo = filename:join(DataDir, "my_echo"), - - ?line comp("one", os:cmd(Echo ++ " one")), - ?line comp("one::two", os:cmd(Echo ++ " one two")), - ?line comp("one two", os:cmd(Echo ++ " \"one two\"")), - ?line comp("x::one two::y", os:cmd(Echo ++ " x \"one two\" y")), - ?line comp("x::one two", os:cmd(Echo ++ " x \"one two\"")), - ?line comp("one two::y", os:cmd(Echo ++ " \"one two\" y")), - ?line comp("x::::y", os:cmd(Echo ++ " x \"\" y")), - ?t:sleep(5), - ?line [] = receive_all(), + DataDir = proplists:get_value(data_dir, Config), + Echo = filename:join(DataDir, "my_echo"), + + comp("one", os:cmd(Echo ++ " one")), + comp("one::two", os:cmd(Echo ++ " one two")), + comp("one two", os:cmd(Echo ++ " \"one two\"")), + comp("x::one two::y", os:cmd(Echo ++ " x \"one two\" y")), + comp("x::one two", os:cmd(Echo ++ " x \"one two\"")), + comp("one two::y", os:cmd(Echo ++ " \"one two\" y")), + comp("x::::y", os:cmd(Echo ++ " x \"\" y")), + ct:sleep(5), + [] = receive_all(), ok. -cmd_unicode(doc) -> "Test that unicode arguments work."; -cmd_unicode(suite) -> []; +%% Test that unicode arguments work. cmd_unicode(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line Echo = filename:join(DataDir, "my_echo"), - - ?line comp("one", os:cmd(Echo ++ " one")), - ?line comp("one::two", os:cmd(Echo ++ " one two")), - ?line comp("åäö::ϼΩ", os:cmd(Echo ++ " åäö " ++ [1020, 937])), - ?t:sleep(5), - ?line [] = receive_all(), + DataDir = proplists:get_value(data_dir, Config), + Echo = filename:join(DataDir, "my_echo"), + + comp("one", os:cmd(Echo ++ " one")), + comp("one::two", os:cmd(Echo ++ " one two")), + comp("åäö::ϼΩ", os:cmd(Echo ++ " åäö " ++ [1020, 937])), + ct:sleep(5), + [] = receive_all(), ok. -space_in_name(doc) -> - "Test that program with a space in its name can be executed."; -space_in_name(suite) -> []; +%% Test that program with a space in its name can be executed. space_in_name(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line DataDir = ?config(data_dir, Config), - ?line Spacedir = filename:join(PrivDir, "program files"), + PrivDir = proplists:get_value(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + Spacedir = filename:join(PrivDir, "program files"), Ext = case os:type() of {win32,_} -> ".exe"; _ -> "" end, - ?line OrigEcho = filename:join(DataDir, "my_echo" ++ Ext), - ?line Echo0 = filename:join(Spacedir, "my_echo" ++ Ext), + OrigEcho = filename:join(DataDir, "my_echo" ++ Ext), + Echo0 = filename:join(Spacedir, "my_echo" ++ Ext), %% Copy the `my_echo' program to a directory whose name contains a space. - ?line ok = file:make_dir(Spacedir), - ?line {ok, Bin} = file:read_file(OrigEcho), - ?line ok = file:write_file(Echo0, Bin), - ?line Echo = filename:nativename(Echo0), - ?line ok = file:change_mode(Echo, 8#777), % Make it executable on Unix. + ok = file:make_dir(Spacedir), + {ok, Bin} = file:read_file(OrigEcho), + ok = file:write_file(Echo0, Bin), + Echo = filename:nativename(Echo0), + ok = file:change_mode(Echo, 8#777), % Make it executable on Unix. %% Run the echo program. %% Quoting on windows depends on if the full path of the executable @@ -146,78 +161,74 @@ space_in_name(Config) when is_list(Config) -> _ -> "\"" end, - ?line comp("", os:cmd(Quote ++ Echo ++ Quote)), - ?line comp("a::b::c", os:cmd(Quote ++ Echo ++ Quote ++ " a b c")), - ?t:sleep(5), - ?line [] = receive_all(), + comp("", os:cmd(Quote ++ Echo ++ Quote)), + comp("a::b::c", os:cmd(Quote ++ Echo ++ Quote ++ " a b c")), + ct:sleep(5), + [] = receive_all(), ok. -bad_command(doc) -> - "Check that a bad command doesn't crasch the server or the emulator (it used to)."; -bad_command(suite) -> []; +%% Check that a bad command doesn't crasch the server or the emulator (it used to). bad_command(Config) when is_list(Config) -> - ?line catch os:cmd([a|b]), - ?line catch os:cmd({bad, thing}), + catch os:cmd([a|b]), + catch os:cmd({bad, thing}), %% This should at least not crash (on Unix it typically returns %% a message from the shell). - ?line os:cmd("xxxxx"), + os:cmd("xxxxx"), ok. -find_executable(suite) -> []; -find_executable(doc) -> []; find_executable(Config) when is_list(Config) -> case os:type() of {win32, _} -> - ?line DataDir = filename:join(?config(data_dir, Config), "win32"), - ?line ok = file:set_cwd(filename:join([DataDir, "current"])), - ?line Bin = filename:join(DataDir, "bin"), - ?line Abin = filename:join(DataDir, "abin"), - ?line UsrBin = filename:join([DataDir, "usr", "bin"]), - ?line {ok, Current} = file:get_cwd(), + DataDir = filename:join(proplists:get_value(data_dir, Config), "win32"), + ok = file:set_cwd(filename:join([DataDir, "current"])), + Bin = filename:join(DataDir, "bin"), + Abin = filename:join(DataDir, "abin"), + UsrBin = filename:join([DataDir, "usr", "bin"]), + {ok, Current} = file:get_cwd(), - ?line Path = lists:concat([Bin, ";", Abin, ";", UsrBin]), - ?line io:format("Path = ~s", [Path]), + Path = lists:concat([Bin, ";", Abin, ";", UsrBin]), + io:format("Path = ~s", [Path]), %% Search for programs in Bin (second element in PATH). - ?line find_exe(Abin, "my_ar", ".exe", Path), - ?line find_exe(Abin, "my_ascii", ".com", Path), - ?line find_exe(Abin, "my_adb", ".bat", Path), + find_exe(Abin, "my_ar", ".exe", Path), + find_exe(Abin, "my_ascii", ".com", Path), + find_exe(Abin, "my_adb", ".bat", Path), %% OTP-3626 find names of executables given with extension - ?line find_exe(Abin, "my_ar.exe", "", Path), - ?line find_exe(Abin, "my_ascii.com", "", Path), - ?line find_exe(Abin, "my_adb.bat", "", Path), - ?line find_exe(Abin, "my_ar.EXE", "", Path), - ?line find_exe(Abin, "my_ascii.COM", "", Path), - ?line find_exe(Abin, "MY_ADB.BAT", "", Path), + find_exe(Abin, "my_ar.exe", "", Path), + find_exe(Abin, "my_ascii.com", "", Path), + find_exe(Abin, "my_adb.bat", "", Path), + find_exe(Abin, "my_ar.EXE", "", Path), + find_exe(Abin, "my_ascii.COM", "", Path), + find_exe(Abin, "MY_ADB.BAT", "", Path), %% Search for programs in Abin (second element in PATH). - ?line find_exe(Abin, "my_ar", ".exe", Path), - ?line find_exe(Abin, "my_ascii", ".com", Path), - ?line find_exe(Abin, "my_adb", ".bat", Path), + find_exe(Abin, "my_ar", ".exe", Path), + find_exe(Abin, "my_ascii", ".com", Path), + find_exe(Abin, "my_adb", ".bat", Path), %% Search for programs in the current working directory. - ?line find_exe(Current, "my_program", ".exe", Path), - ?line find_exe(Current, "my_command", ".com", Path), - ?line find_exe(Current, "my_batch", ".bat", Path), + find_exe(Current, "my_program", ".exe", Path), + find_exe(Current, "my_command", ".com", Path), + find_exe(Current, "my_batch", ".bat", Path), ok; {unix, _} -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), %% Smoke test. case lib:progname() of erl -> - ?line ErlPath = os:find_executable("erl"), - ?line true = is_list(ErlPath), - ?line true = filelib:is_regular(ErlPath); + ErlPath = os:find_executable("erl"), + true = is_list(ErlPath), + true = filelib:is_regular(ErlPath); _ -> %% Don't bother -- the progname could include options. ok end, %% Never return a directory name. - ?line false = os:find_executable("unix", [DataDir]), + false = os:find_executable("unix", [DataDir]), ok end. @@ -233,29 +244,23 @@ find_exe(Where, Name, Ext, Path) -> Other -> io:format("Expected ~p; got (converted to absolute) ~p", [Expected, Other]), - test_server:fail() + ct:fail(failed) end; Other -> io:format("Expected ~p; got ~p", [Expected, Other]), - test_server:fail() + ct:fail(failed) end. -unix_comment_in_command(doc) -> - "OTP-1805: Test that os:cmd(\"ls #\") works correctly (used to hang)."; -unix_comment_in_command(suite) -> []; +%% OTP-1805: Test that os:cmd(\ls #\) works correctly (used to hang). unix_comment_in_command(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(20)), - ?line Priv = ?config(priv_dir, Config), - ?line ok = file:set_cwd(Priv), - ?line _ = os:cmd("ls #"), % Any result is ok. - ?t:sleep(5), - ?line [] = receive_all(), - ?line test_server:timetrap_cancel(Dog), + Priv = proplists:get_value(priv_dir, Config), + ok = file:set_cwd(Priv), + _ = os:cmd("ls #"), % Any result is ok. + ct:sleep(5), + [] = receive_all(), ok. -deep_list_command(doc) -> - "Check that a deep list in command works equally on unix and on windows."; -deep_list_command(suite) -> []; +%% Check that a deep list in command works equally on unix and on windows. deep_list_command(Config) when is_list(Config) -> %% As a 'io_lib' module description says: "There is no guarantee that the %% character lists returned from some of the functions are flat, they can @@ -267,50 +272,101 @@ deep_list_command(Config) when is_list(Config) -> %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"]) ok. +%% Test to make sure that the correct data is +%% received when doing large commands. +large_output_command(Config) when is_list(Config) -> + %% Maximum allowed on windows is 8192, so we test well below that + AAA = lists:duplicate(7000, $a), + comp(AAA,os:cmd("echo " ++ AAA)). --define(EVIL_PROCS, 100). --define(EVIL_LOOPS, 100). --define(PORT_CREATOR, os_cmd_port_creator). -evil(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:minutes(5)), - Parent = self(), - Ps = lists:map(fun (N) -> - spawn_link(fun () -> - evil_loop(Parent, ?EVIL_LOOPS,N) - end) - end, lists:seq(1, ?EVIL_PROCS)), - Devil = spawn_link(fun () -> devil(hd(Ps), hd(lists:reverse(Ps))) end), - lists:foreach(fun (P) -> receive {P, done} -> ok end end, Ps), - unlink(Devil), - exit(Devil, kill), - test_server:timetrap_cancel(Dog), - ok. +%% Test that it is possible on unix to start a background task using os:cmd. +background_command() -> + [{timetrap, {seconds, 5}}]. +background_command(_Config) -> + %% This testcase fails when the os:cmd takes + %% longer then the 5 second timeout + os:cmd("sleep 10&"). + +%% Test that message does not leak to the calling process +message_leak(_Config) -> + process_flag(trap_exit, true), + + os:cmd("echo hello"), + [] = receive_all(), + + case os:type() of + {unix, _} -> + os:cmd("for i in $(seq 1 100); do echo hello; done&"), + [] = receive_all(); + _ -> + ok % Cannot background on non-unix + end, + + process_flag(trap_exit, false). + +%% Test that os:cmd closes stdin of the program that is executed +close_stdin() -> + [{timetrap, {seconds, 5}}]. +close_stdin(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Fds = filename:join(DataDir, "my_fds"), + + "-1" = os:cmd(Fds). + +max_size_command(_Config) -> + + Res20 = os:cmd("cat /dev/zero", #{ max_size => 20 }), + 20 = length(Res20), + + Res0 = os:cmd("cat /dev/zero", #{ max_size => 0 }), + 0 = length(Res0), + + Res32768 = os:cmd("cat /dev/zero", #{ max_size => 32768 }), + 32768 = length(Res32768), + + ResHello = string:trim(os:cmd("echo hello", #{ max_size => 20 })), + 5 = length(ResHello). + +%% Test that the os:perf_counter api works as expected +perf_counter_api(_Config) -> + + true = is_integer(os:perf_counter()), + true = os:perf_counter() > 0, + + Conv = fun(T1, T2) -> + erlang:convert_time_unit(T2 - T1, perf_counter, nanosecond) + end, + + do_perf_counter_test([], Conv, 120000000, 80000000), + do_perf_counter_test([1000], fun(T1, T2) -> T2 - T1 end, 120, 80). + +do_perf_counter_test(CntArgs, Conv, Upper, Lower) -> + %% We run the test multiple times to try to get a somewhat + %% stable value... what does this test? That the + %% calculate_perf_counter_unit in sys_time.c works somewhat ok. + do_perf_counter_test(CntArgs, Conv, Upper, Lower, 10). + +do_perf_counter_test(CntArgs, _Conv, Upper, Lower, 0) -> + ct:fail("perf_counter_test ~p ~p ~p",[CntArgs, Upper, Lower]); +do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters) -> + + T1 = apply(os, perf_counter, CntArgs), + timer:sleep(100), + T2 = apply(os, perf_counter, CntArgs), + TsDiff = Conv(T1, T2), + ct:log("T1: ~p~n" + "T2: ~p~n" + "TsDiff: ~p~n", + [T1,T2,TsDiff]), + + if + TsDiff < Upper, TsDiff > Lower -> + ok; + true -> + do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters-1) + end. -devil(P1, P2) -> - erlang:display({?PORT_CREATOR, whereis(?PORT_CREATOR)}), - (catch ?PORT_CREATOR ! lists:seq(1,1000000)), - (catch ?PORT_CREATOR ! lists:seq(1,666)), - (catch ?PORT_CREATOR ! grrrrrrrrrrrrrrrr), - (catch ?PORT_CREATOR ! {'EXIT', P1, buhuuu}), - (catch ?PORT_CREATOR ! {'EXIT', hd(erlang:ports()), buhuuu}), - (catch ?PORT_CREATOR ! {'EXIT', P2, arggggggg}), - receive after 500 -> ok end, - (catch exit(whereis(?PORT_CREATOR), kill)), - (catch ?PORT_CREATOR ! ">8|"), - receive after 500 -> ok end, - (catch exit(whereis(?PORT_CREATOR), diiiiiiiiiiiiiiiiiiiie)), - receive after 100 -> ok end, - devil(P1, P2). - -evil_loop(Parent, Loops, N) -> - Res = integer_to_list(N), - evil_loop(Parent, Loops, Res, "echo " ++ Res). - -evil_loop(Parent, 0, _Res, _Cmd) -> - Parent ! {self(), done}; -evil_loop(Parent, Loops, Res, Cmd) -> - comp(Res, os:cmd(Cmd)), - evil_loop(Parent, Loops-1, Res, Cmd). +%% Util functions comp(Expected, Got) -> case strip_nl(Got) of @@ -319,7 +375,7 @@ comp(Expected, Got) -> Other -> ok = io:format("Expected: ~ts\n", [Expected]), ok = io:format("Got: ~ts\n", [Other]), - test_server:fail() + ct:fail(failed) end. %% Like lib:nonl/1, but strips \r as well as \n. diff --git a/lib/kernel/test/os_SUITE_data/Makefile.src b/lib/kernel/test/os_SUITE_data/Makefile.src index 912d0cbcb1..f83f781411 100644 --- a/lib/kernel/test/os_SUITE_data/Makefile.src +++ b/lib/kernel/test/os_SUITE_data/Makefile.src @@ -3,7 +3,7 @@ LD = @LD@ CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@ CROSSLDFLAGS = @CROSSLDFLAGS@ -PROGS = my_echo@exe@ +PROGS = my_echo@exe@ my_fds@exe@ all: $(PROGS) @@ -12,3 +12,9 @@ my_echo@exe@: my_echo@obj@ my_echo@obj@: my_echo.c $(CC) -c -o my_echo@obj@ $(CFLAGS) my_echo.c + +my_fds@exe@: my_fds@obj@ + $(LD) $(CROSSLDFLAGS) -o my_fds my_fds@obj@ @LIBS@ + +my_fds@obj@: my_fds.c + $(CC) -c -o my_fds@obj@ $(CFLAGS) my_fds.c diff --git a/lib/kernel/test/os_SUITE_data/my_fds.c b/lib/kernel/test/os_SUITE_data/my_fds.c new file mode 100644 index 0000000000..704a4d1e1d --- /dev/null +++ b/lib/kernel/test/os_SUITE_data/my_fds.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int +main(int argc, char** argv) +{ + char buff[1]; + int res = read(stdin, buff, 1); + printf("%d", res); +} diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl index 6de4ff9f77..d105952df9 100644 --- a/lib/kernel/test/pdict_SUITE.erl +++ b/lib/kernel/test/pdict_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. 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,9 @@ %% %CopyrightEnd% %% -module(pdict_SUITE). -%% NB: The ?line macro cannot be used when testing the dictionary. --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(M(A,B),m(A,B,?MODULE,?LINE)). -ifdef(DEBUG). @@ -32,22 +31,28 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, + mixed/1, + literals/1, simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]). -export([init_per_testcase/2, end_per_testcase/2]). -export([other_process/2]). +-export([put_do/2, get_do/1, erase_do/1]). + init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(test_server:minutes(10)), - [{watchdog, Dog} | Config]. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), + Config. + +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> - [simple, complicated, heavy, simple_all_keys, info]. + [simple, complicated, heavy, simple_all_keys, info, + literals, + mixed]. groups() -> []. @@ -65,10 +70,7 @@ end_per_group(_GroupName, Config) -> Config. -simple(doc) -> - ["Tests simple functionality in process dictionary."]; -simple(suite) -> - []; +%% Tests simple functionality in process dictionary. simple(Config) when is_list(Config) -> XX = get(), ok = match_keys(XX), @@ -109,7 +111,7 @@ complicated(Config) when is_list(Config) -> Previous = get(), ok = match_keys(Previous), Previous = erase(), - N = case ?t:is_debug() of + N = case test_server:is_debug() of false -> 500000; true -> 5000 end, @@ -143,10 +145,7 @@ comp_4([{{key,_}=K,{value,_}=Val}|T]) -> comp_4(T); comp_4([]) -> ok. -heavy(doc) -> - ["Tests heavy usage of the process dictionary"]; -heavy(suite) -> - []; +%% Tests heavy usage of the process dictionary. heavy(Config) when is_list(Config) -> XX = get(), erase(), @@ -156,7 +155,7 @@ heavy(Config) when is_list(Config) -> ?M([],get()), time(5000), ?M([],get()), - case {os:type(),?t:is_debug()} of + case {os:type(),test_server:is_debug()} of {_,true} -> ok; _ -> time(50000), @@ -185,10 +184,7 @@ simple_all_keys_del_loop([K|Ks]) -> ok = match_keys(get()), simple_all_keys_del_loop(Ks). -info(doc) -> - ["Tests process_info(Pid, dictionary)"]; -info(suite) -> - []; +%% Tests process_info(Pid, dictionary). info(Config) when is_list(Config) -> L = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, q,r,s,t,u,v,x,y,z,'A','B','C','D'], @@ -369,3 +365,116 @@ match_keys(All) -> Ks = lists:sort([K||{K,_}<-All]), Ks = lists:sort(erlang:get_keys()), ok. + + +%% Do random mixed put/erase to test grow/shrink +%% Written for a temporary bug in gc during shrink +mixed(_Config) -> + Rand0 = rand:seed_s(exsplus), + io:format("Random seed = ~p\n\n", [rand:export_seed_s(Rand0)]), + + erts_debug:set_internal_state(available_internal_state, true), + try + C = do_mixed([10,0,100,50,1000,500,600,100,150,1,11,2,30,0], + 0, + array:new(), + 1, + Rand0), + io:format("\nDid total of ~p operations\n", [C]) + after + erts_debug:set_internal_state(available_internal_state, false) + end. + +do_mixed([], _, _, C, _) -> + C; +do_mixed([GoalN | Tail], GoalN, Array, C, Rand0) -> + io:format("Reached goal of ~p keys in dict after ~p mixed ops\n",[GoalN, C]), + GoalN = array:size(Array), + do_mixed(Tail, GoalN, Array, C, Rand0); +do_mixed([GoalN | _]=Goals, CurrN, Array0, C, Rand0) -> + CurrN = array:size(Array0), + GrowPercent = case GoalN > CurrN of + true when CurrN == 0 -> 100; + true -> 75; + false -> 25 + end, + {R, Rand1} = rand:uniform_s(100, Rand0), + case R of + _ when R =< GrowPercent -> %%%%%%%%%%%%% GROW + {Key, Rand2} = rand:uniform_s(10000, Rand1), + case put(Key, {Key,C}) of + undefined -> + Array1 = array:set(CurrN, Key, Array0), + do_mixed(Goals, CurrN+1, Array1, C+1, Rand2); + _ -> + do_mixed(Goals, CurrN, Array0, C+1, Rand2) + end; + + _ -> %%%%%%%%%% SHRINK + {Kix, Rand2} = rand:uniform_s(CurrN, Rand1), + Key = array:get(Kix-1, Array0), + + %% provoke GC during shrink + erts_debug:set_internal_state(fill_heap, true), + + {Key, _} = erase(Key), + Array1 = array:set(Kix-1, array:get(CurrN-1, Array0), Array0), + Array2 = array:resize(CurrN-1, Array1), + do_mixed(Goals, CurrN-1, Array2, C+1, Rand2) + end. + +%% Test hash precalculation of literal keys +literals(_Config) -> + %% Put literal -> get variable + put(1742, "1742"), + "1742" = ?MODULE:get_do(1742), + "1742" = ?MODULE:erase_do(1742), + + put(-1742, "-1742"), + "-1742" = ?MODULE:get_do(-1742), + "-1742" = ?MODULE:erase_do(-1742), + + put([], "NIL"), + "NIL" = ?MODULE:get_do([]), + "NIL" = ?MODULE:erase_do([]), + + put(<<"binary">>, "binary"), + "binary" = ?MODULE:get_do(<<"binary">>), + "binary" = ?MODULE:erase_do(<<"binary">>), + + BigBin = <<"A large binary with a lot of bytes to make it go off heap as shared and reference counted">>, + put(BigBin, "bigbin"), + "bigbin" = ?MODULE:get_do(BigBin), + "bigbin" = ?MODULE:erase_do(BigBin), + + %% Put variable -> get literal + ?MODULE:put_do(4217, "4217"), + "4217" = get(4217), + "4217" = erase(4217), + + ?MODULE:put_do(-4217, "-4217"), + "-4217" = get(-4217), + "-4217" = erase(-4217), + + ?MODULE:put_do([], "NIL"), + "NIL" = get([]), + "NIL" = erase([]), + + ?MODULE:put_do(<<"bytes">>, "bytes"), + "bytes" = get(<<"bytes">>), + "bytes" = erase(<<"bytes">>), + + ?MODULE:put_do(BigBin, "BigBin"), + "BigBin" = get(BigBin), + "BigBin" = erase(BigBin), + + ok. + +put_do(K, V) -> + put(K, V). + +get_do(K) -> + get(K). + +erase_do(K) -> + erase(K). diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl index 832d2d1c27..acecd34ead 100644 --- a/lib/kernel/test/pg2_SUITE.erl +++ b/lib/kernel/test/pg2_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. 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,9 +21,9 @@ %%----------------------------------------------------------------- -module(pg2_SUITE). --include_lib("test_server/include/test_server.hrl"). --define(datadir, ?config(data_dir, Config)). --define(privdir, ?config(priv_dir, Config)). +-include_lib("common_test/include/ct.hrl"). +-define(datadir, proplists:get_value(data_dir, Config)). +-define(privdir, proplists:get_value(priv_dir, Config)). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, @@ -31,36 +31,32 @@ -export([ otp_7277/1, otp_8259/1, otp_8653/1, - compat/1, basic/1]). - -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(1)). + basic/1]). -define(TESTCASE, testcase_name). --define(testcase, ?config(?TESTCASE, Config)). +-define(testcase, proplists:get_value(?TESTCASE, Config)). %% Internal export. -export([mk_part_node_and_group/3, part2/4, mk_part_node/3, part1/5, p_init/3, start_proc/1, sane/0]). init_per_testcase(Case, Config) -> - ?line Dog = ?t:timetrap(?default_timeout), - [{?TESTCASE, Case}, {watchdog, Dog} | Config]. + [{?TESTCASE, Case}| Config]. end_per_testcase(_Case, _Config) -> test_server_ctrl:kill_slavenodes(), - Dog = ?config(watchdog, _Config), - test_server:timetrap_cancel(Dog), ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [{group, tickets}]. groups() -> [{tickets, [], - [otp_7277, otp_8259, otp_8653, compat, basic]}]. + [otp_7277, otp_8259, otp_8653, basic]}]. init_per_suite(Config) -> Config. @@ -76,67 +72,59 @@ end_per_group(_GroupName, Config) -> -otp_7277(doc) -> - "OTP-7277. Bugfix leave()."; -otp_7277(suite) -> []; +%% OTP-7277. Bugfix leave(). otp_7277(Config) when is_list(Config) -> - ?line ok = pg2:create(a), - ?line ok = pg2:create(b), + ok = pg2:create(a), + ok = pg2:create(b), P = spawn(forever()), - ?line ok = pg2:join(a, P), - ?line ok = pg2:leave(b, P), - ?line true = exit(P, kill), + ok = pg2:join(a, P), + ok = pg2:leave(b, P), + true = exit(P, kill), case {pg2:get_members(a), pg2:get_local_members(a)} of {[], []} -> ok; _ -> timer:sleep(100), - ?line [] = pg2:get_members(a), - ?line [] = pg2:get_local_members(a) + [] = pg2:get_members(a), + [] = pg2:get_local_members(a) end, - ?line _ = pg2:delete(a), - ?line _ = pg2:delete(b), + _ = pg2:delete(a), + _ = pg2:delete(b), ok. -define(UNTIL(Seq), loop_until_true(fun() -> Seq end, Config)). -define(UNTIL_LOOP, 300). -otp_8653(suite) -> []; -otp_8653(doc) -> - ["OTP-8259. Member was not removed after being killed."]; +%% OTP-8259. Member was not removed after being killed. otp_8653(Config) when is_list(Config) -> - Timeout = 15, - ?line Dog = test_server:timetrap({seconds,Timeout}), - - ?line [A, B, C] = start_nodes([a, b, c], peer, Config), + [A, B, C] = start_nodes([a, b, c], peer, Config), - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), - % make b and c connected, partitioned from node() and a - ?line rpc_cast(B, ?MODULE, part2, [Config, node(), A, C]), - ?line ?UNTIL(is_ready_partition(Config)), + %% make b and c connected, partitioned from node() and a + rpc_cast(B, ?MODULE, part2, [Config, node(), A, C]), + ?UNTIL(is_ready_partition(Config)), - % Connect to the other partition. - ?line pong = net_adm:ping(B), + %% Connect to the other partition. + pong = net_adm:ping(B), timer:sleep(100), - ?line pong = net_adm:ping(C), - ?line _ = global:sync(), - ?line [A, B, C] = lists:sort(nodes()), + pong = net_adm:ping(C), + _ = global:sync(), + [A, B, C] = lists:sort(nodes()), G = pg2_otp_8653, - ?line ?UNTIL(begin - GA = lists:sort(rpc:call(A, pg2, get_members, [G])), - GB = lists:sort(rpc:call(B, pg2, get_members, [G])), - GC = lists:sort(rpc:call(C, pg2, get_members, [G])), - GT = lists:sort(pg2:get_members(G)), - GA =:= GB andalso - GB =:= GC andalso - GC =:= GT andalso - 8 =:= length(GA) - end), - ?line ok = pg2:delete(G), - ?line stop_nodes([A,B,C]), - ?line test_server:timetrap_cancel(Dog), + ?UNTIL(begin + GA = lists:sort(rpc:call(A, pg2, get_members, [G])), + GB = lists:sort(rpc:call(B, pg2, get_members, [G])), + GC = lists:sort(rpc:call(C, pg2, get_members, [G])), + GT = lists:sort(pg2:get_members(G)), + GA =:= GB andalso + GB =:= GC andalso + GC =:= GT andalso + 8 =:= length(GA) + end), + ok = pg2:delete(G), + stop_nodes([A,B,C]), ok. part2(Config, Main, A, C) -> @@ -158,54 +146,48 @@ mk_part_node_and_group(File, MyPart0, Config) -> _ = [ok = pg2:join(G, Pid) || _ <- [1,1]], touch(File, "done"). -otp_8259(suite) -> []; -otp_8259(doc) -> - ["OTP-8259. Member was not removed after being killed."]; +%% OTP-8259. Member was not removed after being killed. otp_8259(Config) when is_list(Config) -> - Timeout = 15, - ?line Dog = test_server:timetrap({seconds,Timeout}), + [A, B, C] = start_nodes([a, b, c], peer, Config), - ?line [A, B, C] = start_nodes([a, b, c], peer, Config), - - ?line wait_for_ready_net(Config), + wait_for_ready_net(Config), G = pg2_otp_8259, Name = otp_8259_a_global_name, - % start different processes in both partitions - ?line {Pid, yes} = rpc:call(A, ?MODULE, start_proc, [Name]), + %% start different processes in both partitions + {Pid, yes} = rpc:call(A, ?MODULE, start_proc, [Name]), - ?line ok = pg2:create(G), - ?line ok = pg2:join(G, Pid), + ok = pg2:create(G), + ok = pg2:join(G, Pid), - % make b and c connected, partitioned from node() and a - ?line rpc_cast(B, ?MODULE, part1, [Config, node(), A, C, Name]), - ?line ?UNTIL(is_ready_partition(Config)), + %% make b and c connected, partitioned from node() and a + rpc_cast(B, ?MODULE, part1, [Config, node(), A, C, Name]), + ?UNTIL(is_ready_partition(Config)), - % Connect to the other partition. - % The resolver on node b will be called. - ?line pong = net_adm:ping(B), + %% Connect to the other partition. + %% The resolver on node b will be called. + pong = net_adm:ping(B), timer:sleep(100), - ?line pong = net_adm:ping(C), - ?line _ = global:sync(), - ?line [A, B, C] = lists:sort(nodes()), + pong = net_adm:ping(C), + _ = global:sync(), + [A, B, C] = lists:sort(nodes()), %% Pid has been killed by the resolver. %% Pid has been removed from pg2 on all nodes, in particular node B. - ?line ?UNTIL([] =:= rpc:call(B, pg2, get_members, [G])), - ?line ?UNTIL([] =:= pg2:get_members(G)), - ?line ?UNTIL([] =:= rpc:call(A, pg2, get_members, [G])), - ?line ?UNTIL([] =:= rpc:call(C, pg2, get_members, [G])), - - ?line ok = pg2:delete(G), - ?line stop_nodes([A,B,C]), - ?line test_server:timetrap_cancel(Dog), + ?UNTIL([] =:= rpc:call(B, pg2, get_members, [G])), + ?UNTIL([] =:= pg2:get_members(G)), + ?UNTIL([] =:= rpc:call(A, pg2, get_members, [G])), + ?UNTIL([] =:= rpc:call(C, pg2, get_members, [G])), + + ok = pg2:delete(G), + stop_nodes([A,B,C]), ok. part1(Config, Main, A, C, Name) -> case catch begin make_partition(Config, [Main, A], [node(), C]), - ?line {_Pid, yes} = start_proc(Name) + {_Pid, yes} = start_proc(Name) end of {_, yes} -> ok end. @@ -236,39 +218,10 @@ loop() -> exit(normal) end. -compat(suite) -> []; -compat(doc) -> - ["OTP-8259. Check that 'exchange' and 'del_member' work."]; -compat(Config) when is_list(Config) -> - case ?t:is_release_available("r13b") of - true -> - Timeout = 15, - ?line Dog = test_server:timetrap({seconds,Timeout}), - Pid = spawn(forever()), - G = a, - ?line ok = pg2:create(G), - ?line ok = pg2:join(G, Pid), - ?line ok = pg2:join(G, Pid), - ?line {ok, A} = start_node_rel(r13, r13b, slave), - ?line pong = net_adm:ping(A), - ?line wait_for_ready_net(Config), - ?line {ok, _} = rpc:call(A, pg2, start, []), - ?line ?UNTIL([Pid,Pid] =:= rpc:call(A, pg2, get_members, [a])), - ?line true = exit(Pid, kill), - ?line ?UNTIL([] =:= pg2:get_members(a)), - ?line ?UNTIL([] =:= rpc:call(A, pg2, get_members, [a])), - ?t:stop_node(A), - ?line test_server:timetrap_cancel(Dog); - false -> - {skipped, "No support for old node"} - end. - -basic(suite) -> []; -basic(doc) -> - ["OTP-8259. Some basic tests."]; +%% OTP-8259. Some basic tests. basic(Config) when is_list(Config) -> _ = [pg2:delete(G) || G <- pg2:which_groups()], - ?line _ = [do(Cs, T, Config) || {T,Cs} <- ts()], + _ = [do(Cs, T, Config) || {T,Cs} <- ts()], ok. ts() -> @@ -373,7 +326,7 @@ ts() -> ]. do(Cs, T, Config) -> - ?t:format("*** Test ~p ***~n", [T]), + io:format("*** Test ~p ***~n", [T]), {ok,T} = (catch {do(Cs, [], [], Config),T}). do([{nodeup,N} | Cs], Ps, Ns, Config) -> @@ -425,7 +378,7 @@ doit(N, C, Ps, Ns) -> Result when Result =:= R orelse R =:= ignore -> sane(Ns); Else -> - ?t:format("~p and ~p: expected ~p, but got ~p~n", + io:format("~p and ~p: expected ~p, but got ~p~n", [F, As, R, Else]), throw({error,{F, As, R, Else}}) end. @@ -446,8 +399,8 @@ killit(N, P, Ps, Ns) -> lists:keydelete(P, 1, Ps). pr(Node, C) -> - _ = [?t:format("~p: ", [Node]) || Node =/= node()], - ?t:format("do ~p~n", [C]). + _ = [io:format("~p: ", [Node]) || Node =/= node()], + io:format("do ~p~n", [C]). get_node(N, Ns) -> if @@ -475,7 +428,7 @@ replace_pids(A, Ps) -> sane(Ns) -> Nodes = [node()] ++ [NN || {_,NN} <- Ns], - _ = [?t:format("~p, pg2_table:~n ~p~n", % debug + _ = [io:format("~p, pg2_table:~n ~p~n", % debug [N, rpc:call(N, ets, tab2list, [pg2_table])]) || N <- Nodes], R = [case rpc:call(Node, ?MODULE, sane, []) of @@ -509,7 +462,7 @@ wsane(Ns) -> Pid when is_pid(Pid), node(Pid) =:= N -> true = lists:member(Pid, rpc:call(N, pg2, get_local_members, [G])); -%% FIXME. Om annan nod: member, local = []. + %% FIXME. Om annan nod: member, local = []. _ -> [] = rpc:call(N, pg2, get_local_members, [G]) end || N <- Ns] || G <- pg2:which_groups()]. @@ -558,21 +511,21 @@ start_node_rel(Name, Rel, How) -> Rel when is_atom(Rel) -> {[{release, atom_to_list(Rel)}], ""}; RelList -> - {RelList, ""} - end, - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line Res = test_server:start_node(Name, How, - [{args, - Compat ++ - " -kernel net_setuptime 100 " - " -pa " ++ Pa}, - {erl, Release}]), + {RelList, ""} + end, + Pa = filename:dirname(code:which(?MODULE)), + Res = test_server:start_node(Name, How, + [{args, + Compat ++ + " -kernel net_setuptime 100 " + " -pa " ++ Pa}, + {erl, Release}]), Res. start_nodes(L, How, Config) -> start_nodes2(L, How, 0, Config), Nodes = collect_nodes(0, length(L)), - ?line ?UNTIL([] =:= Nodes -- nodes()), + ?UNTIL([] =:= Nodes -- nodes()), %% Pinging doesn't help, we have to wait too, for nodes() to become %% correct on the other node. lists:foreach(fun(E) -> @@ -588,7 +541,7 @@ verify_nodes(Nodes, Config) -> verify_nodes([], _N, _Config) -> []; verify_nodes([Node | Rest], N, Config) -> - ?line ?UNTIL( + ?UNTIL( case rpc:call(Node, erlang, nodes, []) of Nodes when is_list(Nodes) -> case N =:= lists:sort([Node | Nodes]) of @@ -620,7 +573,7 @@ start_nodes2([Name | Rest], How, N, Config) -> Self ! {N, R}, %% sleeping is necessary, or with peer nodes, they will %% go down again, despite {linked, false}. - test_server:sleep(100000) + ct:sleep(100000) end), start_nodes2(Rest, How, N+1, Config). @@ -640,7 +593,7 @@ start_node(Name0, How, Args, Config) -> Pa = filename:dirname(code:which(?MODULE)), test_server:start_node(Name, How, [{args, Args ++ " " ++ - "-kernel net_setuptime 100 " + "-kernel net_setuptime 100 " "-noshell " "-pa " ++ Pa}, {linked, false}]). @@ -648,7 +601,7 @@ stop_nodes(Nodes) -> lists:foreach(fun(Node) -> stop_node(Node) end, Nodes). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). get_known(Node) -> case catch gen_server:call({global_name_server,Node},get_known,infinity) of @@ -672,7 +625,7 @@ make_partition(Config, Part1, Part2) -> make_partition(Config, Part1, Part2, mk_part_node). make_partition(Config, Part1, Part2, Function) -> - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), Ns = [begin Name = lists:concat([atom_to_list(N),"_",msec(),".part"]), File = filename:join([Dir, Name]), @@ -726,13 +679,13 @@ wait_for_ready_net(Config) -> wait_for_ready_net(Nodes0, Config) -> Nodes = lists:sort(Nodes0), - ?t:format("wait_for_ready_net ~p~n", [Nodes]), + io:format("wait_for_ready_net ~p~n", [Nodes]), ?UNTIL(begin lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and - lists:all(fun(N) -> - LNs = rpc:call(N, erlang, nodes, []), - Nodes =:= lists:sort([N | LNs]) - end, Nodes) + lists:all(fun(N) -> + LNs = rpc:call(N, erlang, nodes, []), + Nodes =:= lists:sort([N | LNs]) + end, Nodes) end). %% To make it less probable that some low-level problem causes @@ -788,11 +741,11 @@ file_contents(File, ContentsList, Config, LogFile) -> end). make_partition_file(Config) -> - Dir = ?config(priv_dir, Config), + Dir = proplists:get_value(priv_dir, Config), filename:join([Dir, atom_to_list(make_partition_done)]). msec() -> msec(now()). msec(T) -> - element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000. + element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000. diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 3e6d8492f7..e88d42788f 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2014. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. 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. @@ -19,8 +19,8 @@ %% -module(prim_file_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - read_write_file/1]). + init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2, + read_write_file/1, free_memory/0]). -export([cur_dir_0a/1, cur_dir_0b/1, cur_dir_1a/1, cur_dir_1b/1, make_del_dir_a/1, make_del_dir_b/1, @@ -36,7 +36,7 @@ file_write_file_info_a/1, file_write_file_info_b/1, file_read_file_info_opts/1, file_write_file_info_opts/1, file_write_read_file_info_opts/1 - ]). + ]). -export([rename_a/1, rename_b/1, access/1, truncate/1, datasync/1, sync/1, read_write/1, pread_write/1, append/1, exclusive/1]). @@ -62,7 +62,7 @@ -export([allocate/1]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/file.hrl"). -define(PRIM_FILE, prim_file). @@ -105,7 +105,7 @@ groups() -> file_write_file_info_a, file_write_file_info_b, file_read_file_info_opts, file_write_file_info_opts, file_write_read_file_info_opts - ]}, + ]}, {errors, [], [e_delete, e_rename, e_make_dir, e_del_dir]}, {compression, [], @@ -115,6 +115,18 @@ groups() -> [make_link_a, make_link_b, read_link_info_for_non_link, symlinks_a, symlinks_b, list_dir_error]}]. +init_per_testcase(large_write, Config) -> + {ok, Started} = application:ensure_all_started(os_mon), + [{started, Started}|Config]; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(large_write, Config) -> + [application:stop(App) || App <- lists:reverse(proplists:get_value(started, Config))], + ok; +end_per_testcase(_, _Config) -> + ok. + init_per_group(_GroupName, Config) -> Config. @@ -125,7 +137,7 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config) when is_list(Config) -> case os:type() of {win32, _} -> - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), HasAccessTime = case file:read_file_info(Priv) of {ok, #file_info{atime={_, {0, 0, 0}}}} -> @@ -181,92 +193,86 @@ time_dist({_D1, _T1} = DT1, {_D2, _T2} = DT2) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -read_write_file(suite) -> []; -read_write_file(doc) -> []; read_write_file(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_read_write_file"), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_read_write_file"), %% Try writing and reading back some term - ?line SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]}, - ?line ok = ?PRIM_FILE:write_file(Name,term_to_binary(SomeTerm)), - ?line {ok,Bin1} = ?PRIM_FILE:read_file(Name), - ?line SomeTerm = binary_to_term(Bin1), - + SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]}, + ok = ?PRIM_FILE:write_file(Name,term_to_binary(SomeTerm)), + {ok,Bin1} = ?PRIM_FILE:read_file(Name), + SomeTerm = binary_to_term(Bin1), + %% Try a "null" term - ?line NullTerm = [], - ?line ok = ?PRIM_FILE:write_file(Name,term_to_binary(NullTerm)), - ?line {ok,Bin2} = ?PRIM_FILE:read_file(Name), - ?line NullTerm = binary_to_term(Bin2), + NullTerm = [], + ok = ?PRIM_FILE:write_file(Name,term_to_binary(NullTerm)), + {ok,Bin2} = ?PRIM_FILE:read_file(Name), + NullTerm = binary_to_term(Bin2), %% Try some "complicated" types - ?line BigNum = 123456789012345678901234567890, - ?line ComplTerm = {self(),make_ref(),BigNum,3.14159}, - ?line ok = ?PRIM_FILE:write_file(Name,term_to_binary(ComplTerm)), - ?line {ok,Bin3} = ?PRIM_FILE:read_file(Name), - ?line ComplTerm = binary_to_term(Bin3), + BigNum = 123456789012345678901234567890, + ComplTerm = {self(),make_ref(),BigNum,3.14159}, + ok = ?PRIM_FILE:write_file(Name,term_to_binary(ComplTerm)), + {ok,Bin3} = ?PRIM_FILE:read_file(Name), + ComplTerm = binary_to_term(Bin3), %% Try reading a nonexistent file - ?line Name2 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_nonexistent_file"), - ?line {error, enoent} = ?PRIM_FILE:read_file(Name2), - ?line {error, enoent} = ?PRIM_FILE:read_file(""), - - % Try writing to a bad filename - ?line {error, enoent} = + Name2 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_nonexistent_file"), + {error, enoent} = ?PRIM_FILE:read_file(Name2), + {error, enoent} = ?PRIM_FILE:read_file(""), + + %% Try writing to a bad filename + {error, enoent} = ?PRIM_FILE:write_file("",term_to_binary(NullTerm)), - % Try writing something else than a binary - ?line {error, badarg} = ?PRIM_FILE:write_file(Name,{1,2,3}), - ?line {error, badarg} = ?PRIM_FILE:write_file(Name,self()), + %% Try writing something else than a binary + {error, badarg} = ?PRIM_FILE:write_file(Name,{1,2,3}), + {error, badarg} = ?PRIM_FILE:write_file(Name,self()), %% Some non-term binaries - ?line ok = ?PRIM_FILE:write_file(Name,[]), - ?line {ok,Bin4} = ?PRIM_FILE:read_file(Name), - ?line 0 = byte_size(Bin4), + ok = ?PRIM_FILE:write_file(Name,[]), + {ok,Bin4} = ?PRIM_FILE:read_file(Name), + 0 = byte_size(Bin4), - ?line ok = ?PRIM_FILE:write_file(Name,[Bin1,[],[[Bin2]]]), - ?line {ok,Bin5} = ?PRIM_FILE:read_file(Name), - ?line {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)), + ok = ?PRIM_FILE:write_file(Name,[Bin1,[],[[Bin2]]]), + {ok,Bin5} = ?PRIM_FILE:read_file(Name), + {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -make_del_dir_a(suite) -> []; -make_del_dir_a(doc) -> []; make_del_dir_a(Config) when is_list(Config) -> make_del_dir(Config, [], "_a"). -make_del_dir_b(suite) -> []; -make_del_dir_b(doc) -> []; make_del_dir_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = make_del_dir(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), %% Just to make sure the state of the server makes a difference - ?line {error, einval} = ?PRIM_FILE_call(get_cwd, Handle, []), + {error, einval} = ?PRIM_FILE_call(get_cwd, Handle, []), Result. make_del_dir(Config, Handle, Suffix) -> - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_mk-dir"++Suffix), - ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), - ?line {error, eexist} = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), - ?line ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]), - ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [NewDir]), - - % Make sure we are not in a directory directly under test_server - % as that would result in eacces errors when trying to delete '..', - % because there are processes having that directory as current. - ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), - ?line {ok, CurrentDir} = ?PRIM_FILE_call(get_cwd, Handle, []), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_mk-dir"++Suffix), + ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), + {error, eexist} = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), + ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]), + {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [NewDir]), + + %% Make sure we are not in a directory directly under test_server + %% as that would result in eacces errors when trying to delete '..', + %% because there are processes having that directory as current. + ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), + {ok, CurrentDir} = ?PRIM_FILE_call(get_cwd, Handle, []), case {os:type(), length(NewDir) >= 260 } of {{win32,_}, true} -> io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH)\n", []), @@ -277,18 +283,18 @@ make_del_dir(Config, Handle, Suffix) -> try %% Check that we get an error when trying to create... %% a deep directory - ?line NewDir2 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_mk-dir-noexist/foo"), - ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]), + NewDir2 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_mk-dir-noexist/foo"), + {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]), %% a nameless directory - ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]), + {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]), %% a directory with illegal name - ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']), - + {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']), + %% a directory with illegal name, even if it's a (bad) list - ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]), - + {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]), + %% Maybe this isn't an error, exactly, but worth mentioning anyway: %% ok = ?PRIM_FILE:make_dir([$f,$o,$o,0,$b,$a,$r])), %% The above line works, and created a directory "./foo" @@ -296,41 +302,37 @@ make_del_dir(Config, Handle, Suffix) -> %% a directory, but with a name that incorporates the "bar" part of %% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same %% dir. But this would slow it down. - + %% Try deleting some bad directories %% Deleting the parent directory to the current, sounds dangerous, huh? %% Don't worry ;-) the parent directory should never be empty, right? - ?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of - {error, eexist} -> ok; - {error, eacces} -> ok; %OpenBSD - {error, einval} -> ok %FreeBSD - end, - ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]), - ?line {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]]) + case ?PRIM_FILE_call(del_dir, Handle, [".."]) of + {error, eexist} -> ok; + {error, eacces} -> ok; %OpenBSD + {error, einval} -> ok %FreeBSD + end, + {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]), + {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]]) after - ?line ok = ?PRIM_FILE_call(set_cwd, Handle, [CurrentDir]) + ok = ?PRIM_FILE_call(set_cwd, Handle, [CurrentDir]) end, ok. -cur_dir_0a(suite) -> []; -cur_dir_0a(doc) -> []; cur_dir_0a(Config) when is_list(Config) -> cur_dir_0(Config, []). -cur_dir_0b(suite) -> []; -cur_dir_0b(doc) -> []; cur_dir_0b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = cur_dir_0(Config, Handle), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. cur_dir_0(Config, Handle) -> %% Find out the current dir, and cd to it ;-) - ?line {ok,BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), - ?line Dir1 = BaseDir ++ "", %% Check that it's a string - ?line ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]), - ?line DirName = atom_to_list(?MODULE) ++ + {ok,BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), + Dir1 = BaseDir ++ "", %% Check that it's a string + ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]), + DirName = atom_to_list(?MODULE) ++ case Handle of [] -> "_curdir"; @@ -339,9 +341,9 @@ cur_dir_0(Config, Handle) -> end, %% Make a new dir, and cd to that - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, DirName), - ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, DirName), + ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), case {os:type(), length(NewDir) >= 260} of {{win32,_}, true} -> io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH):\n"), @@ -361,7 +363,7 @@ cur_dir_0(Config, Handle) -> %% Delete the directory and return to the old current directory %% and check that the created file isn't there (too!) expect({error, einval}, {error, eacces}, {error, eexist}, - ?PRIM_FILE_call(del_dir, Handle, [NewDir])), + ?PRIM_FILE_call(del_dir, Handle, [NewDir])), ?PRIM_FILE_call(delete, Handle, [UncommonName]), {ok,[]} = ?PRIM_FILE_call(list_dir, Handle, ["."]), ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]), @@ -375,13 +377,13 @@ cur_dir_0(Config, Handle) -> end, %% Try doing some bad things - ?line {error, badarg} = + {error, badarg} = ?PRIM_FILE_call(set_cwd, Handle, [{foo,bar}]), - ?line {error, enoent} = + {error, enoent} = ?PRIM_FILE_call(set_cwd, Handle, [""]), - ?line {error, enoent} = + {error, enoent} = ?PRIM_FILE_call(set_cwd, Handle, [".......a......"]), - ?line {ok,BaseDir} = + {ok,BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), %% Still there? %% On Windows, there should only be slashes, no backslashes, @@ -389,44 +391,40 @@ cur_dir_0(Config, Handle) -> %% (The test is harmless on Unix, because filenames usually %% don't contain backslashes.) - ?line {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), - ?line false = lists:member($\\, BaseDir), + {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), + false = lists:member($\\, BaseDir), ok. %% Tests ?PRIM_FILE:get_cwd/1. -cur_dir_1a(suite) -> []; -cur_dir_1a(doc) -> []; cur_dir_1a(Config) when is_list(Config) -> cur_dir_1(Config, []). -cur_dir_1b(suite) -> []; -cur_dir_1b(doc) -> []; cur_dir_1b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = cur_dir_1(Config, Handle), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. cur_dir_1(Config, Handle) -> - ?line case os:type() of - {win32, _} -> - win_cur_dir_1(Config, Handle); - _ -> - ?line {error, enotsup} = - ?PRIM_FILE_call(get_cwd, Handle, ["d:"]) - end, + case os:type() of + {win32, _} -> + win_cur_dir_1(Config, Handle); + _ -> + {error, enotsup} = + ?PRIM_FILE_call(get_cwd, Handle, ["d:"]) + end, ok. - + win_cur_dir_1(_Config, Handle) -> - ?line {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), + {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []), %% Get the drive letter from the current directory, %% and try to get current directory for that drive. - ?line [Drive, $:|_] = BaseDir, - ?line {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, [[Drive, $:]]), + [Drive, $:|_] = BaseDir, + {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, [[Drive, $:]]), io:format("BaseDir = ~s\n", [BaseDir]), %% Unfortunately, there is no way to move away from the @@ -439,440 +437,405 @@ win_cur_dir_1(_Config, Handle) -> -open1(suite) -> []; -open1(doc) -> []; open1(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_files"), - ?line ok = ?PRIM_FILE:make_dir(NewDir), - ?line Name = filename:join(NewDir, "foo1.fil"), - ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]), - ?line {ok,Fd2} = ?PRIM_FILE:open(Name, [read]), - ?line Str = "{a,tuple}.\n", - ?line Length = length(Str), - ?line ?PRIM_FILE:write(Fd1,Str), - ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), - ?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length), - ?line case ?PRIM_FILE:read(Fd2,Length) of - {ok,Str} -> Str; - eof -> Str - end, - ?line ok = ?PRIM_FILE:close(Fd2), - ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), - ?line ok = ?PRIM_FILE:truncate(Fd1), - ?line eof = ?PRIM_FILE:read(Fd1,Length), - ?line ok = ?PRIM_FILE:close(Fd1), - ?line {ok,Fd3} = ?PRIM_FILE:open(Name, [read]), - ?line eof = ?PRIM_FILE:read(Fd3,Length), - ?line ok = ?PRIM_FILE:close(Fd3), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_files"), + ok = ?PRIM_FILE:make_dir(NewDir), + Name = filename:join(NewDir, "foo1.fil"), + {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]), + {ok,Fd2} = ?PRIM_FILE:open(Name, [read]), + Str = "{a,tuple}.\n", + Length = length(Str), + ?PRIM_FILE:write(Fd1,Str), + {ok,0} = ?PRIM_FILE:position(Fd1,bof), + {ok, Str} = ?PRIM_FILE:read(Fd1,Length), + {ok, Str} = ?PRIM_FILE:read(Fd2,Length), + ok = ?PRIM_FILE:close(Fd2), + {ok,0} = ?PRIM_FILE:position(Fd1,bof), + ok = ?PRIM_FILE:truncate(Fd1), + eof = ?PRIM_FILE:read(Fd1,Length), + ok = ?PRIM_FILE:close(Fd1), + {ok,Fd3} = ?PRIM_FILE:open(Name, [read]), + eof = ?PRIM_FILE:read(Fd3,Length), + ok = ?PRIM_FILE:close(Fd3), ok. %% Tests all open modes. -modes(suite) -> []; -modes(doc) -> []; modes(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_open_modes"), - ?line ok = ?PRIM_FILE:make_dir(NewDir), - ?line Name1 = filename:join(NewDir, "foo1.fil"), - ?line Marker = "hello, world", - ?line Length = length(Marker), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_open_modes"), + ok = ?PRIM_FILE:make_dir(NewDir), + Name1 = filename:join(NewDir, "foo1.fil"), + Marker = "hello, world", + Length = length(Marker), %% write - ?line {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]), - ?line ok = ?PRIM_FILE:write(Fd1, Marker), - ?line ok = ?PRIM_FILE:write(Fd1, ".\n"), - ?line ok = ?PRIM_FILE:close(Fd1), + {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]), + ok = ?PRIM_FILE:write(Fd1, Marker), + ok = ?PRIM_FILE:write(Fd1, ".\n"), + ok = ?PRIM_FILE:close(Fd1), %% read - ?line {ok, Fd2} = ?PRIM_FILE:open(Name1, [read]), - ?line {ok, Marker} = ?PRIM_FILE:read(Fd2, Length), - ?line ok = ?PRIM_FILE:close(Fd2), + {ok, Fd2} = ?PRIM_FILE:open(Name1, [read]), + {ok, Marker} = ?PRIM_FILE:read(Fd2, Length), + ok = ?PRIM_FILE:close(Fd2), %% read and write - ?line {ok, Fd3} = ?PRIM_FILE:open(Name1, [read, write]), - ?line {ok, Marker} = ?PRIM_FILE:read(Fd3, Length), - ?line ok = ?PRIM_FILE:write(Fd3, Marker), - ?line ok = ?PRIM_FILE:close(Fd3), + {ok, Fd3} = ?PRIM_FILE:open(Name1, [read, write]), + {ok, Marker} = ?PRIM_FILE:read(Fd3, Length), + ok = ?PRIM_FILE:write(Fd3, Marker), + ok = ?PRIM_FILE:close(Fd3), %% read by default - ?line {ok, Fd4} = ?PRIM_FILE:open(Name1, []), - ?line {ok, Marker} = ?PRIM_FILE:read(Fd4, Length), - ?line ok = ?PRIM_FILE:close(Fd4), + {ok, Fd4} = ?PRIM_FILE:open(Name1, []), + {ok, Marker} = ?PRIM_FILE:read(Fd4, Length), + ok = ?PRIM_FILE:close(Fd4), %% read and binary - ?line BinaryMarker = list_to_binary(Marker), - ?line {ok, Fd5} = ?PRIM_FILE:open(Name1, [read, binary]), - ?line {ok, BinaryMarker} = ?PRIM_FILE:read(Fd5, Length), - ?line ok = ?PRIM_FILE:close(Fd5), + BinaryMarker = list_to_binary(Marker), + {ok, Fd5} = ?PRIM_FILE:open(Name1, [read, binary]), + {ok, BinaryMarker} = ?PRIM_FILE:read(Fd5, Length), + ok = ?PRIM_FILE:close(Fd5), - ?line test_server:timetrap_cancel(Dog), ok. -close(suite) -> []; -close(doc) -> []; close(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_close.fil"), - ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_close.fil"), + {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]), %% Just closing it is no fun, we did that a million times already %% This is a common error, for code written before Erlang 4.3 %% bacause then ?PRIM_FILE:open just returned a Pid, and not everyone %% really checked what they got. - ?line {'EXIT',_Msg} = (catch ok = ?PRIM_FILE:close({ok,Fd1})), - ?line ok = ?PRIM_FILE:close(Fd1), + {'EXIT',_Msg} = (catch ok = ?PRIM_FILE:close({ok,Fd1})), + ok = ?PRIM_FILE:close(Fd1), %% Try closing one more time - ?line Val = ?PRIM_FILE:close(Fd1), - ?line io:format("Second close gave: ~p", [Val]), + Val = ?PRIM_FILE:close(Fd1), + io:format("Second close gave: ~p", [Val]), ok. -access(suite) -> []; -access(doc) -> []; access(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_access.fil"), - ?line Str = "ABCDEFGH", - ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), - ?line ?PRIM_FILE:write(Fd1,Str), - ?line ok = ?PRIM_FILE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_access.fil"), + Str = "ABCDEFGH", + {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), + ?PRIM_FILE:write(Fd1,Str), + ok = ?PRIM_FILE:close(Fd1), %% Check that we can't write when in read only mode - ?line {ok,Fd2} = ?PRIM_FILE:open(Name, [read]), - ?line case catch ?PRIM_FILE:write(Fd2,"XXXX") of - ok -> - test_server:fail({access,write}); - _ -> - ok - end, - ?line ok = ?PRIM_FILE:close(Fd2), - ?line {ok, Fd3} = ?PRIM_FILE:open(Name, [read]), - ?line {ok, Str} = ?PRIM_FILE:read(Fd3,length(Str)), - ?line ok = ?PRIM_FILE:close(Fd3), + {ok,Fd2} = ?PRIM_FILE:open(Name, [read]), + case catch ?PRIM_FILE:write(Fd2,"XXXX") of + ok -> + ct:fail({access,write}); + _ -> + ok + end, + ok = ?PRIM_FILE:close(Fd2), + {ok, Fd3} = ?PRIM_FILE:open(Name, [read]), + {ok, Str} = ?PRIM_FILE:read(Fd3,length(Str)), + ok = ?PRIM_FILE:close(Fd3), ok. %% Tests ?PRIM_FILE:read/2 and ?PRIM_FILE:write/2. -read_write(suite) -> []; -read_write(doc) -> []; read_write(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_read_write"), - ?line ok = ?PRIM_FILE:make_dir(NewDir), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_read_write"), + ok = ?PRIM_FILE:make_dir(NewDir), %% Raw file. - ?line Name = filename:join(NewDir, "raw.fil"), - ?line {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]), - ?line read_write_test(Fd), + Name = filename:join(NewDir, "raw.fil"), + {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]), + read_write_test(Fd), ok. read_write_test(File) -> - ?line Marker = "hello, world", - ?line ok = ?PRIM_FILE:write(File, Marker), - ?line {ok, 0} = ?PRIM_FILE:position(File, 0), - ?line {ok, Marker} = ?PRIM_FILE:read(File, 100), - ?line eof = ?PRIM_FILE:read(File, 100), - ?line ok = ?PRIM_FILE:close(File), + Marker = "hello, world", + ok = ?PRIM_FILE:write(File, Marker), + {ok, 0} = ?PRIM_FILE:position(File, 0), + {ok, Marker} = ?PRIM_FILE:read(File, 100), + eof = ?PRIM_FILE:read(File, 100), + ok = ?PRIM_FILE:close(File), ok. %% Tests ?PRIM_FILE:pread/2 and ?PRIM_FILE:pwrite/2. -pread_write(suite) -> []; -pread_write(doc) -> []; pread_write(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_pread_write"), - ?line ok = ?PRIM_FILE:make_dir(NewDir), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_pread_write"), + ok = ?PRIM_FILE:make_dir(NewDir), %% Raw file. - ?line Name = filename:join(NewDir, "raw.fil"), - ?line {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]), - ?line pread_write_test(Fd), + Name = filename:join(NewDir, "raw.fil"), + {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]), + pread_write_test(Fd), ok. pread_write_test(File) -> - ?line Marker = "hello, world", - ?line Len = length(Marker), - ?line ok = ?PRIM_FILE:write(File, Marker), - ?line {ok, Marker} = ?PRIM_FILE:pread(File, 0, 100), - ?line eof = ?PRIM_FILE:pread(File, 100, 1), - ?line ok = ?PRIM_FILE:pwrite(File, Len, Marker), - ?line {ok, Marker} = ?PRIM_FILE:pread(File, Len, 100), - ?line eof = ?PRIM_FILE:pread(File, 100, 1), - ?line MM = Marker ++ Marker, - ?line {ok, MM} = ?PRIM_FILE:pread(File, 0, 100), - ?line ok = ?PRIM_FILE:close(File), + Marker = "hello, world", + Len = length(Marker), + ok = ?PRIM_FILE:write(File, Marker), + {ok, Marker} = ?PRIM_FILE:pread(File, 0, 100), + eof = ?PRIM_FILE:pread(File, 100, 1), + ok = ?PRIM_FILE:pwrite(File, Len, Marker), + {ok, Marker} = ?PRIM_FILE:pread(File, Len, 100), + eof = ?PRIM_FILE:pread(File, 100, 1), + MM = Marker ++ Marker, + {ok, MM} = ?PRIM_FILE:pread(File, 0, 100), + ok = ?PRIM_FILE:close(File), ok. -append(doc) -> "Test appending to a file."; -append(suite) -> []; +%% Test appending to a file. append(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_append"), - ?line ok = ?PRIM_FILE:make_dir(NewDir), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_append"), + ok = ?PRIM_FILE:make_dir(NewDir), - ?line First = "First line\n", - ?line Second = "Seond lines comes here\n", - ?line Third = "And here is the third line\n", + First = "First line\n", + Second = "Seond lines comes here\n", + Third = "And here is the third line\n", %% Write a small text file. - ?line Name1 = filename:join(NewDir, "a_file.txt"), - ?line {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]), - ?line ok = ?PRIM_FILE:write(Fd1, First), - ?line ok = ?PRIM_FILE:write(Fd1, Second), - ?line ok = ?PRIM_FILE:close(Fd1), + Name1 = filename:join(NewDir, "a_file.txt"), + {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]), + ok = ?PRIM_FILE:write(Fd1, First), + ok = ?PRIM_FILE:write(Fd1, Second), + ok = ?PRIM_FILE:close(Fd1), %% Open it a again and a append a line to it. - ?line {ok, Fd2} = ?PRIM_FILE:open(Name1, [append]), - ?line ok = ?PRIM_FILE:write(Fd2, Third), - ?line ok = ?PRIM_FILE:close(Fd2), + {ok, Fd2} = ?PRIM_FILE:open(Name1, [append]), + ok = ?PRIM_FILE:write(Fd2, Third), + ok = ?PRIM_FILE:close(Fd2), %% Read it back and verify. - ?line Expected = list_to_binary([First, Second, Third]), - ?line {ok, Expected} = ?PRIM_FILE:read_file(Name1), + Expected = list_to_binary([First, Second, Third]), + {ok, Expected} = ?PRIM_FILE:read_file(Name1), ok. -exclusive(suite) -> []; -exclusive(doc) -> "Test exclusive access to a file."; +%% Test exclusive access to a file. exclusive(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_exclusive"), - ?line ok = ?PRIM_FILE:make_dir(NewDir), - ?line Name = filename:join(NewDir, "ex_file.txt"), - ?line {ok,Fd} = ?PRIM_FILE:open(Name, [write, exclusive]), - ?line {error, eexist} = ?PRIM_FILE:open(Name, [write, exclusive]), - ?line ok = ?PRIM_FILE:close(Fd), + RootDir = proplists:get_value(priv_dir,Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_exclusive"), + ok = ?PRIM_FILE:make_dir(NewDir), + Name = filename:join(NewDir, "ex_file.txt"), + {ok,Fd} = ?PRIM_FILE:open(Name, [write, exclusive]), + {error, eexist} = ?PRIM_FILE:open(Name, [write, exclusive]), + ok = ?PRIM_FILE:close(Fd), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -pos1(suite) -> []; -pos1(doc) -> []; pos1(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_pos1.fil"), - ?line {ok, Fd1} = ?PRIM_FILE:open(Name, [write]), - ?line ?PRIM_FILE:write(Fd1,"ABCDEFGH"), - ?line ok = ?PRIM_FILE:close(Fd1), - ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_pos1.fil"), + {ok, Fd1} = ?PRIM_FILE:open(Name, [write]), + ?PRIM_FILE:write(Fd1,"ABCDEFGH"), + ok = ?PRIM_FILE:close(Fd1), + {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), %% Start pos is first char - ?line io:format("Relative positions"), - ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,1}), - ?line {ok, "C"} = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 0} = ?PRIM_FILE:position(Fd2,{cur,-3}), - ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1), + io:format("Relative positions"), + {ok, "A"} = ?PRIM_FILE:read(Fd2,1), + {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,1}), + {ok, "C"} = ?PRIM_FILE:read(Fd2,1), + {ok, 0} = ?PRIM_FILE:position(Fd2,{cur,-3}), + {ok, "A"} = ?PRIM_FILE:read(Fd2,1), %% Backwards from first char should be an error - ?line {ok,0} = ?PRIM_FILE:position(Fd2,{cur,-1}), - ?line {error, einval} = ?PRIM_FILE:position(Fd2,{cur,-1}), + {ok,0} = ?PRIM_FILE:position(Fd2,{cur,-1}), + {error, einval} = ?PRIM_FILE:position(Fd2,{cur,-1}), %% Reset position and move again - ?line {ok, 0} = ?PRIM_FILE:position(Fd2,0), - ?line {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,2}), - ?line {ok, "C"} = ?PRIM_FILE:read(Fd2,1), + {ok, 0} = ?PRIM_FILE:position(Fd2,0), + {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,2}), + {ok, "C"} = ?PRIM_FILE:read(Fd2,1), %% Go a lot forwards - ?line {ok, 13} = ?PRIM_FILE:position(Fd2,{cur,10}), - ?line eof = ?PRIM_FILE:read(Fd2,1), + {ok, 13} = ?PRIM_FILE:position(Fd2,{cur,10}), + eof = ?PRIM_FILE:read(Fd2,1), %% Try some fixed positions - ?line io:format("Fixed positions"), - ?line {ok, 8} = ?PRIM_FILE:position(Fd2,8), - ?line eof = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 8} = ?PRIM_FILE:position(Fd2,cur), - ?line eof = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 7} = ?PRIM_FILE:position(Fd2,7), - ?line {ok, "H"} = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 0} = ?PRIM_FILE:position(Fd2,0), - ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 3} = ?PRIM_FILE:position(Fd2,3), - ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 12} = ?PRIM_FILE:position(Fd2,12), - ?line eof = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 3} = ?PRIM_FILE:position(Fd2,3), - ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1), + io:format("Fixed positions"), + {ok, 8} = ?PRIM_FILE:position(Fd2,8), + eof = ?PRIM_FILE:read(Fd2,1), + {ok, 8} = ?PRIM_FILE:position(Fd2,cur), + eof = ?PRIM_FILE:read(Fd2,1), + {ok, 7} = ?PRIM_FILE:position(Fd2,7), + {ok, "H"} = ?PRIM_FILE:read(Fd2,1), + {ok, 0} = ?PRIM_FILE:position(Fd2,0), + {ok, "A"} = ?PRIM_FILE:read(Fd2,1), + {ok, 3} = ?PRIM_FILE:position(Fd2,3), + {ok, "D"} = ?PRIM_FILE:read(Fd2,1), + {ok, 12} = ?PRIM_FILE:position(Fd2,12), + eof = ?PRIM_FILE:read(Fd2,1), + {ok, 3} = ?PRIM_FILE:position(Fd2,3), + {ok, "D"} = ?PRIM_FILE:read(Fd2,1), %% Try the {bof,X} notation - ?line {ok, 3} = ?PRIM_FILE:position(Fd2,{bof,3}), - ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1), + {ok, 3} = ?PRIM_FILE:position(Fd2,{bof,3}), + {ok, "D"} = ?PRIM_FILE:read(Fd2,1), %% Try eof positions - ?line io:format("EOF positions"), - ?line {ok, 8} = ?PRIM_FILE:position(Fd2,{eof,0}), - ?line eof = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 7} = ?PRIM_FILE:position(Fd2,{eof,-1}), - ?line {ok, "H"} = ?PRIM_FILE:read(Fd2,1), - ?line {ok, 0} = ?PRIM_FILE:position(Fd2,{eof,-8}), - ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1), - ?line {error, einval} = ?PRIM_FILE:position(Fd2,{eof,-9}), + io:format("EOF positions"), + {ok, 8} = ?PRIM_FILE:position(Fd2,{eof,0}), + eof = ?PRIM_FILE:read(Fd2,1), + {ok, 7} = ?PRIM_FILE:position(Fd2,{eof,-1}), + {ok, "H"} = ?PRIM_FILE:read(Fd2,1), + {ok, 0} = ?PRIM_FILE:position(Fd2,{eof,-8}), + {ok, "A"} = ?PRIM_FILE:read(Fd2,1), + {error, einval} = ?PRIM_FILE:position(Fd2,{eof,-9}), ok. -pos2(suite) -> []; -pos2(doc) -> []; pos2(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_pos2.fil"), - ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), - ?line ?PRIM_FILE:write(Fd1,"ABCDEFGH"), - ?line ok = ?PRIM_FILE:close(Fd1), - ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), - ?line {error, einval} = ?PRIM_FILE:position(Fd2,-1), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_pos2.fil"), + {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), + ?PRIM_FILE:write(Fd1,"ABCDEFGH"), + ok = ?PRIM_FILE:close(Fd1), + {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), + {error, einval} = ?PRIM_FILE:position(Fd2,-1), %% Make sure that we still can search after an error. - ?line {ok, 0} = ?PRIM_FILE:position(Fd2, 0), - ?line {ok, 3} = ?PRIM_FILE:position(Fd2, {bof,3}), - ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1), + {ok, 0} = ?PRIM_FILE:position(Fd2, 0), + {ok, 3} = ?PRIM_FILE:position(Fd2, {bof,3}), + {ok, "D"} = ?PRIM_FILE:read(Fd2,1), - ?line io:format("DONE"), + io:format("DONE"), ok. -file_info_basic_file_a(suite) -> []; -file_info_basic_file_a(doc) -> []; file_info_basic_file_a(Config) when is_list(Config) -> file_info_basic_file(Config, [], "_a"). -file_info_basic_file_b(suite) -> []; -file_info_basic_file_b(doc) -> []; file_info_basic_file_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = file_info_basic_file(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. file_info_basic_file(Config, Handle, Suffix) -> - ?line RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), %% Create a short file. - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_basic_test"++Suffix++".fil"), - ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), - ?line ?PRIM_FILE:write(Fd1, "foo bar"), - ?line ok = ?PRIM_FILE:close(Fd1), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_basic_test"++Suffix++".fil"), + {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), + ?PRIM_FILE:write(Fd1, "foo bar"), + ok = ?PRIM_FILE:close(Fd1), %% Test that the file has the expected attributes. %% The times are tricky, so we will save them to a separate test case. - ?line {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line #file_info{size = Size, type = Type, access = Access, - atime = AccessTime, mtime = ModifyTime} = + {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), + #file_info{size = Size, type = Type, access = Access, + atime = AccessTime, mtime = ModifyTime} = FileInfo, - ?line io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]), - ?line Size = 7, - ?line Type = regular, - ?line Access = read_write, - ?line true = abs(time_dist(filter_atime(AccessTime, Config), - filter_atime(ModifyTime, - Config))) < 2, - ?line {AD, AT} = AccessTime, - ?line all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)), - ?line {MD, MT} = ModifyTime, - ?line all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)), + io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]), + Size = 7, + Type = regular, + Access = read_write, + true = abs(time_dist(filter_atime(AccessTime, Config), + filter_atime(ModifyTime, + Config))) < 2, + {AD, AT} = AccessTime, + all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)), + {MD, MT} = ModifyTime, + all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)), ok. -file_info_basic_directory_a(suite) -> []; -file_info_basic_directory_a(doc) -> []; file_info_basic_directory_a(Config) when is_list(Config) -> file_info_basic_directory(Config, []). -file_info_basic_directory_b(suite) -> []; -file_info_basic_directory_b(doc) -> []; file_info_basic_directory_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = file_info_basic_directory(Config, Handle), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. file_info_basic_directory(Config, Handle) -> %% Note: filename:join/1 removes any trailing slash, %% which is essential for ?PRIM_FILE:read_file_info/1 to work on %% platforms such as Windows95. - ?line RootDir = filename:join([?config(priv_dir, Config)]), + RootDir = filename:join([proplists:get_value(priv_dir, Config)]), %% Test that the RootDir directory has the expected attributes. - ?line test_directory(RootDir, read_write, Handle), + test_directory(RootDir, read_write, Handle), %% Note that on Windows file systems, "/" or "c:/" are *NOT* directories. %% Therefore, test that ?PRIM_FILE:read_file_info/1 behaves %% as if they were directories. - ?line case os:type() of - {win32, _} -> - ?line test_directory("/", read_write, Handle), - ?line test_directory("c:/", read_write, Handle), - ?line test_directory("c:\\", read_write, Handle); - _ -> - ?line test_directory("/", read, Handle) - end, + case os:type() of + {win32, _} -> + test_directory("/", read_write, Handle), + test_directory("c:/", read_write, Handle), + test_directory("c:\\", read_write, Handle); + _ -> + test_directory("/", read, Handle) + end, ok. test_directory(Name, ExpectedAccess, Handle) -> - ?line {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line #file_info{size = Size, type = Type, access = Access, - atime = AccessTime, mtime = ModifyTime} = + {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), + #file_info{size = Size, type = Type, access = Access, + atime = AccessTime, mtime = ModifyTime} = FileInfo, - ?line io:format("Testing directory ~s", [Name]), - ?line io:format("Directory size is ~p", [Size]), - ?line io:format("Access ~p", [Access]), - ?line io:format("Access time ~p; Modify time~p", - [AccessTime, ModifyTime]), - ?line Type = directory, - ?line Access = ExpectedAccess, - ?line {AD, AT} = AccessTime, - ?line all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)), - ?line {MD, MT} = ModifyTime, - ?line all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)), + io:format("Testing directory ~s", [Name]), + io:format("Directory size is ~p", [Size]), + io:format("Access ~p", [Access]), + io:format("Access time ~p; Modify time~p", + [AccessTime, ModifyTime]), + Type = directory, + Access = ExpectedAccess, + {AD, AT} = AccessTime, + all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)), + {MD, MT} = ModifyTime, + all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)), ok. all_integers([Int|Rest]) when is_integer(Int) -> - ?line all_integers(Rest); + all_integers(Rest); all_integers([]) -> ok. %% Try something nonexistent. -file_info_bad_a(suite) -> []; -file_info_bad_a(doc) -> []; file_info_bad_a(Config) when is_list(Config) -> file_info_bad(Config, []). -file_info_bad_b(suite) -> []; -file_info_bad_b(doc) -> []; file_info_bad_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = file_info_bad(Config, Handle), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. file_info_bad(Config, Handle) -> - ?line RootDir = filename:join([?config(priv_dir, Config)]), - ?line {error, enoent} = + RootDir = filename:join([proplists:get_value(priv_dir, Config)]), + {error, enoent} = ?PRIM_FILE_call( read_file_info, Handle, [filename:join(RootDir, @@ -881,28 +844,22 @@ file_info_bad(Config, Handle) -> %% Test that the file times behave as they should. -file_info_times_a(suite) -> []; -file_info_times_a(doc) -> []; file_info_times_a(Config) when is_list(Config) -> file_info_times(Config, [], "_a"). -file_info_times_b(suite) -> []; -file_info_times_b(doc) -> []; file_info_times_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = file_info_times(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. file_info_times(Config, Handle, Suffix) -> - ?line Dog = test_server:timetrap(test_server:seconds(60)), %% We have to try this twice, since if the test runs across the change %% of a month the time diff calculations will fail. But it won't happen %% if you run it twice in succession. - ?line test_server:m_out_of_n( - 1,2, - fun() -> ?line file_info_int(Config, Handle, Suffix) end), - ?line test_server:timetrap_cancel(Dog), + test_server:m_out_of_n( + 1,2, + fun() -> file_info_int(Config, Handle, Suffix) end), ok. file_info_int(Config, Handle, Suffix) -> @@ -910,55 +867,55 @@ file_info_int(Config, Handle, Suffix) -> %% which is essential for ?PRIM_FILE:read_file_info/1 to work on %% platforms such as Windows95. - ?line RootDir = filename:join([?config(priv_dir, Config)]), - ?line test_server:format("RootDir = ~p", [RootDir]), + RootDir = filename:join([proplists:get_value(priv_dir, Config)]), + io:format("RootDir = ~p", [RootDir]), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_file_info"++Suffix++".fil"), - ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), - ?line ?PRIM_FILE:write(Fd1,"foo"), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_file_info"++Suffix++".fil"), + {ok,Fd1} = ?PRIM_FILE:open(Name, [write]), + ?PRIM_FILE:write(Fd1,"foo"), %% check that the file got a modify date max a few seconds away from now - ?line {ok, #file_info{type = regular, - atime = AccTime1, mtime = ModTime1}} = + {ok, #file_info{type = regular, + atime = AccTime1, mtime = ModTime1}} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line Now = erlang:localtime(), - ?line io:format("Now ~p",[Now]), - ?line io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]), - ?line true = abs(time_dist(filter_atime(Now, Config), - filter_atime(AccTime1, - Config))) < 8, - ?line true = abs(time_dist(Now, ModTime1)) < 8, - + Now = erlang:localtime(), + io:format("Now ~p",[Now]), + io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]), + true = abs(time_dist(filter_atime(Now, Config), + filter_atime(AccTime1, + Config))) < 8, + true = abs(time_dist(Now, ModTime1)) < 8, + %% Sleep until we can be sure the seconds value has changed. %% Note: FAT-based filesystem (like on Windows 95) have %% a resolution of 2 seconds. - ?line test_server:sleep(test_server:seconds(2.2)), + ct:sleep({seconds,2.2}), %% close the file, and watch the modify date change - ?line ok = ?PRIM_FILE:close(Fd1), - ?line {ok, #file_info{size = Size, type = regular, access = Access, - atime = AccTime2, mtime = ModTime2}} = + ok = ?PRIM_FILE:close(Fd1), + {ok, #file_info{size = Size, type = regular, access = Access, + atime = AccTime2, mtime = ModTime2}} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]), - ?line true = time_dist(ModTime1, ModTime2) >= 0, + io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]), + true = time_dist(ModTime1, ModTime2) >= 0, %% this file is supposed to be binary, so it'd better keep it's size - ?line Size = 3, - ?line Access = read_write, + Size = 3, + Access = read_write, %% Do some directory checking - ?line {ok, #file_info{size = DSize, type = directory, - access = DAccess, - atime = AccTime3, mtime = ModTime3}} = + {ok, #file_info{size = DSize, type = directory, + access = DAccess, + atime = AccTime3, mtime = ModTime3}} = ?PRIM_FILE_call(read_file_info, Handle, [RootDir]), %% this dir was modified only a few secs ago - ?line io:format("Dir Acc ~p; Mod ~p; Now ~p", - [AccTime3, ModTime3, Now]), - ?line true = abs(time_dist(Now, ModTime3)) < 5, - ?line DAccess = read_write, - ?line io:format("Dir size is ~p",[DSize]), + io:format("Dir Acc ~p; Mod ~p; Now ~p", + [AccTime3, ModTime3, Now]), + true = abs(time_dist(Now, ModTime3)) < 5, + DAccess = read_write, + io:format("Dir size is ~p",[DSize]), ok. %% Filter access times, to cope with a deficiency of FAT file systems @@ -969,9 +926,9 @@ filter_atime(Atime, Config) -> true -> case Atime of {Date, _} -> - {Date, {0, 0, 0}}; + {Date, {0, 0, 0}}; {Y, M, D, _, _, _} -> - {Y, M, D, 0, 0, 0} + {Y, M, D, 0, 0, 0} end; false -> Atime @@ -979,186 +936,170 @@ filter_atime(Atime, Config) -> %% Test the write_file_info/2 function. -file_write_file_info_a(suite) -> []; -file_write_file_info_a(doc) -> []; file_write_file_info_a(Config) when is_list(Config) -> file_write_file_info(Config, [], "_a"). -file_write_file_info_b(suite) -> []; -file_write_file_info_b(doc) -> []; file_write_file_info_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = file_write_file_info(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. file_write_file_info(Config, Handle, Suffix) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = get_good_directory(Config), - ?line test_server:format("RootDir = ~p", [RootDir]), + RootDir = get_good_directory(Config), + io:format("RootDir = ~p", [RootDir]), %% Set the file to read only AND update the file times at the same time. %% (This used to fail on Windows NT/95 for a local filesystem.) %% Note: Seconds must be even; see note in file_info_times/1. - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_write_file_info_ro"++Suffix), - ?line ok = ?PRIM_FILE:write_file(Name, "hello"), - ?line Time = {{1997, 01, 02}, {12, 35, 42}}, - ?line Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time}, - ?line ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, Info]), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_write_file_info_ro"++Suffix), + ok = ?PRIM_FILE:write_file(Name, "hello"), + Time = {{1997, 01, 02}, {12, 35, 42}}, + Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time}, + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, Info]), %% Read back the times. - ?line {ok, ActualInfo} = + {ok, ActualInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line #file_info{mode=_Mode, atime=ActAtime, mtime=Time, - ctime=ActCtime} = ActualInfo, - ?line FilteredAtime = filter_atime(Time, Config), - ?line FilteredAtime = filter_atime(ActAtime, Config), - ?line case os:type() of - {win32, _} -> - %% On Windows, "ctime" means creation time and it can - %% be set. - ActCtime = Time; - _ -> - ok - end, - ?line {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"), + #file_info{mode=_Mode, atime=ActAtime, mtime=Time, + ctime=ActCtime} = ActualInfo, + FilteredAtime = filter_atime(Time, Config), + FilteredAtime = filter_atime(ActAtime, Config), + case os:type() of + {win32, _} -> + %% On Windows, "ctime" means creation time and it can + %% be set. + ActCtime = Time; + _ -> + ok + end, + {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"), %% Make the file writable again. - ?line ?PRIM_FILE_call(write_file_info, Handle, - [Name, #file_info{mode=8#600}]), - ?line ok = ?PRIM_FILE:write_file(Name, "hello again"), + ?PRIM_FILE_call(write_file_info, Handle, + [Name, #file_info{mode=8#600}]), + ok = ?PRIM_FILE:write_file(Name, "hello again"), %% And unwritable. - ?line ?PRIM_FILE_call(write_file_info, Handle, - [Name, #file_info{mode=8#400}]), - ?line {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"), + ?PRIM_FILE_call(write_file_info, Handle, + [Name, #file_info{mode=8#400}]), + {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"), %% Write the times again. %% Note: Seconds must be even; see note in file_info_times/1. - ?line NewTime = {{1997, 02, 15}, {13, 18, 20}}, - ?line NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime}, - ?line ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, NewInfo]), - ?line {ok, ActualInfo2} = + NewTime = {{1997, 02, 15}, {13, 18, 20}}, + NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime}, + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, NewInfo]), + {ok, ActualInfo2} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line #file_info{atime=NewActAtime, mtime=NewTime, - ctime=NewActCtime} = ActualInfo2, - ?line NewFilteredAtime = filter_atime(NewTime, Config), - ?line NewFilteredAtime = filter_atime(NewActAtime, Config), - ?line case os:type() of - {win32, _} -> NewActCtime = NewTime; - _ -> ok - end, + #file_info{atime=NewActAtime, mtime=NewTime, + ctime=NewActCtime} = ActualInfo2, + NewFilteredAtime = filter_atime(NewTime, Config), + NewFilteredAtime = filter_atime(NewActAtime, Config), + case os:type() of + {win32, _} -> NewActCtime = NewTime; + _ -> ok + end, %% The file should still be unwritable. - ?line {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"), + {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"), %% Make the file writeable again, so that we can remove the %% test suites ... :-) - ?line ?PRIM_FILE_call(write_file_info, Handle, - [Name, #file_info{mode=8#600}]), - ?line test_server:timetrap_cancel(Dog), + ?PRIM_FILE_call(write_file_info, Handle, + [Name, #file_info{mode=8#600}]), ok. %% Test the write_file_info/3 function. -file_write_file_info_opts(suite) -> []; -file_write_file_info_opts(doc) -> []; file_write_file_info_opts(Config) when is_list(Config) -> {ok, Handle} = ?PRIM_FILE:start(), - Dog = test_server:timetrap(test_server:seconds(10)), RootDir = get_good_directory(Config), - test_server:format("RootDir = ~p", [RootDir]), + io:format("RootDir = ~p", [RootDir]), Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_write_file_info_opts"), ok = ?PRIM_FILE:write_file(Name, "hello_opts"), lists:foreach(fun - ({FI, Opts}) -> - ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) - end, [ - {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} || - Opts <- [[{time, posix}]], - Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ] - ]), - - % REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64 - % Determine time_t on os:type()? - lists:foreach(fun - ({FI, Opts}) -> - ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) - end, [ - {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || - Opts <- [[{time, universal}],[{time, local}]], - Time <- [ - {{1970,1,1},{0,0,0}}, - {{1970,1,1},{0,0,1}}, - {{1969,12,31},{23,59,59}}, - {{1908,2,3},{23,59,59}}, - {{2012,2,3},{23,59,59}}, - {{2037,2,3},{23,59,59}}, - erlang:localtime() - ]]), + ({FI, Opts}) -> + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) + end, [ + {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} || + Opts <- [[{time, posix}]], + Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ] + ]), + + %% REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64 | Uint64 + %% Determine time_t on os:type()? + lists:foreach(fun ({FI, Opts}) -> + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) + end, [ {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || + Opts <- [[{time, universal}],[{time, local}]], + Time <- [ + {{1970,1,1},{0,0,0}}, + {{1970,1,1},{0,0,1}}, + % {{1969,12,31},{23,59,59}}, + % {{1908,2,3},{23,59,59}}, + {{2012,2,3},{23,59,59}}, + {{2037,2,3},{23,59,59}}, + erlang:localtime() + ]]), ok = ?PRIM_FILE:stop(Handle), - test_server:timetrap_cancel(Dog), ok. -file_read_file_info_opts(suite) -> []; -file_read_file_info_opts(doc) -> []; file_read_file_info_opts(Config) when is_list(Config) -> {ok, Handle} = ?PRIM_FILE:start(), - Dog = test_server:timetrap(test_server:seconds(10)), RootDir = get_good_directory(Config), - test_server:format("RootDir = ~p", [RootDir]), + io:format("RootDir = ~p", [RootDir]), Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_file_info_opts"), ok = ?PRIM_FILE:write_file(Name, "hello_opts"), lists:foreach(fun - (Opts) -> - {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]) - end, [[{time, Type}] || Type <- [local, universal, posix]]), + (Opts) -> + {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]) + end, [[{time, Type}] || Type <- [local, universal, posix]]), ok = ?PRIM_FILE:stop(Handle), - test_server:timetrap_cancel(Dog), ok. %% Test the write and read back *_file_info/3 functions. -file_write_read_file_info_opts(suite) -> []; -file_write_read_file_info_opts(doc) -> []; file_write_read_file_info_opts(Config) when is_list(Config) -> {ok, Handle} = ?PRIM_FILE:start(), - Dog = test_server:timetrap(test_server:seconds(10)), RootDir = get_good_directory(Config), - test_server:format("RootDir = ~p", [RootDir]), + io:format("RootDir = ~p", [RootDir]), Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_write_file_info_opts"), ok = ?PRIM_FILE:write_file(Name, "hello_opts2"), ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]), ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]), - ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), - ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]), + %% will not work on platforms with unsigned time_t + %ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), + %ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]), ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, posix}]), - ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]), + %% will not work on platforms with unsigned time_t + %ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]), + %ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, posix}]), ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, posix}]), - ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, posix}]), ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, posix}]), ok = ?PRIM_FILE:stop(Handle), - test_server:timetrap_cancel(Dog), ok. file_write_read_file_info_opts(Handle, Name, Mtime, Opts) -> {ok, FI} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), FI2 = FI#file_info{ mtime = Mtime }, ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI2, Opts]), - {ok, FI2} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + {ok, FI3} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + io:format("Expecting mtime = ~p, got ~p~n", [FI2#file_info.mtime, FI3#file_info.mtime]), + FI2 = FI3, ok. @@ -1166,136 +1107,131 @@ file_write_read_file_info_opts(Handle, Name, Mtime, Opts) -> %% Returns a directory on a file system that has correct file times. get_good_directory(Config) -> - ?line ?config(priv_dir, Config). + proplists:get_value(priv_dir, Config). -truncate(suite) -> []; -truncate(doc) -> []; truncate(Config) when is_list(Config) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_truncate.fil"), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_truncate.fil"), %% Create a file with some data. - ?line MyData = "0123456789abcdefghijklmnopqrstuvxyz", - ?line ok = ?PRIM_FILE:write_file(Name, MyData), + MyData = "0123456789abcdefghijklmnopqrstuvxyz", + ok = ?PRIM_FILE:write_file(Name, MyData), %% Truncate the file to 10 characters. - ?line {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]), - ?line {ok, 10} = ?PRIM_FILE:position(Fd, 10), - ?line ok = ?PRIM_FILE:truncate(Fd), - ?line ok = ?PRIM_FILE:close(Fd), + {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]), + {ok, 10} = ?PRIM_FILE:position(Fd, 10), + ok = ?PRIM_FILE:truncate(Fd), + ok = ?PRIM_FILE:close(Fd), %% Read back the file and check that it has been truncated. - ?line Expected = list_to_binary("0123456789"), - ?line {ok, Expected} = ?PRIM_FILE:read_file(Name), + Expected = list_to_binary("0123456789"), + {ok, Expected} = ?PRIM_FILE:read_file(Name), %% Open the file read only and verify that it is not possible to %% truncate it, OTP-1960 - ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), - ?line {ok, 5} = ?PRIM_FILE:position(Fd2, 5), - ?line {error, _} = ?PRIM_FILE:truncate(Fd2), + {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), + {ok, 5} = ?PRIM_FILE:position(Fd2, 5), + {error, _} = ?PRIM_FILE:truncate(Fd2), ok. -datasync(suite) -> []; -datasync(doc) -> "Tests that ?PRIM_FILE:datasync/1 at least doesn't crash."; +%% Tests that ?PRIM_FILE:datasync/1 at least doesn't crash. datasync(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line Sync = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_sync.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Sync = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_sync.fil"), %% Raw open. - ?line {ok, Fd} = ?PRIM_FILE:open(Sync, [write]), - ?line ok = ?PRIM_FILE:datasync(Fd), - ?line ok = ?PRIM_FILE:close(Fd), + {ok, Fd} = ?PRIM_FILE:open(Sync, [write]), + ok = ?PRIM_FILE:datasync(Fd), + ok = ?PRIM_FILE:close(Fd), ok. -sync(suite) -> []; -sync(doc) -> "Tests that ?PRIM_FILE:sync/1 at least doesn't crash."; +%% Tests that ?PRIM_FILE:sync/1 at least doesn't crash. sync(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line Sync = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_sync.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Sync = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_sync.fil"), %% Raw open. - ?line {ok, Fd} = ?PRIM_FILE:open(Sync, [write]), - ?line ok = ?PRIM_FILE:sync(Fd), - ?line ok = ?PRIM_FILE:close(Fd), + {ok, Fd} = ?PRIM_FILE:open(Sync, [write]), + ok = ?PRIM_FILE:sync(Fd), + ok = ?PRIM_FILE:close(Fd), ok. -advise(suite) -> []; -advise(doc) -> "Tests that ?PRIM_FILE:advise/4 at least doesn't crash."; +%% Tests that ?PRIM_FILE:advise/4 at least doesn't crash. advise(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line Advise = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_advise.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Advise = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_advise.fil"), Line1 = "Hello\n", Line2 = "World!\n", - ?line {ok, Fd} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:advise(Fd, 0, 0, normal), - ?line ok = ?PRIM_FILE:write(Fd, Line1), - ?line ok = ?PRIM_FILE:write(Fd, Line2), - ?line ok = ?PRIM_FILE:close(Fd), - - ?line {ok, Fd2} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:advise(Fd2, 0, 0, random), - ?line ok = ?PRIM_FILE:write(Fd2, Line1), - ?line ok = ?PRIM_FILE:write(Fd2, Line2), - ?line ok = ?PRIM_FILE:close(Fd2), - - ?line {ok, Fd3} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:advise(Fd3, 0, 0, sequential), - ?line ok = ?PRIM_FILE:write(Fd3, Line1), - ?line ok = ?PRIM_FILE:write(Fd3, Line2), - ?line ok = ?PRIM_FILE:close(Fd3), - - ?line {ok, Fd4} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:advise(Fd4, 0, 0, will_need), - ?line ok = ?PRIM_FILE:write(Fd4, Line1), - ?line ok = ?PRIM_FILE:write(Fd4, Line2), - ?line ok = ?PRIM_FILE:close(Fd4), - - ?line {ok, Fd5} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:advise(Fd5, 0, 0, dont_need), - ?line ok = ?PRIM_FILE:write(Fd5, Line1), - ?line ok = ?PRIM_FILE:write(Fd5, Line2), - ?line ok = ?PRIM_FILE:close(Fd5), - - ?line {ok, Fd6} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:advise(Fd6, 0, 0, no_reuse), - ?line ok = ?PRIM_FILE:write(Fd6, Line1), - ?line ok = ?PRIM_FILE:write(Fd6, Line2), - ?line ok = ?PRIM_FILE:close(Fd6), - - ?line {ok, Fd7} = ?PRIM_FILE:open(Advise, [write]), - ?line {error, einval} = ?PRIM_FILE:advise(Fd7, 0, 0, bad_advise), - ?line ok = ?PRIM_FILE:close(Fd7), + {ok, Fd} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:advise(Fd, 0, 0, normal), + ok = ?PRIM_FILE:write(Fd, Line1), + ok = ?PRIM_FILE:write(Fd, Line2), + ok = ?PRIM_FILE:close(Fd), + + {ok, Fd2} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:advise(Fd2, 0, 0, random), + ok = ?PRIM_FILE:write(Fd2, Line1), + ok = ?PRIM_FILE:write(Fd2, Line2), + ok = ?PRIM_FILE:close(Fd2), + + {ok, Fd3} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:advise(Fd3, 0, 0, sequential), + ok = ?PRIM_FILE:write(Fd3, Line1), + ok = ?PRIM_FILE:write(Fd3, Line2), + ok = ?PRIM_FILE:close(Fd3), + + {ok, Fd4} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:advise(Fd4, 0, 0, will_need), + ok = ?PRIM_FILE:write(Fd4, Line1), + ok = ?PRIM_FILE:write(Fd4, Line2), + ok = ?PRIM_FILE:close(Fd4), + + {ok, Fd5} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:advise(Fd5, 0, 0, dont_need), + ok = ?PRIM_FILE:write(Fd5, Line1), + ok = ?PRIM_FILE:write(Fd5, Line2), + ok = ?PRIM_FILE:close(Fd5), + + {ok, Fd6} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:advise(Fd6, 0, 0, no_reuse), + ok = ?PRIM_FILE:write(Fd6, Line1), + ok = ?PRIM_FILE:write(Fd6, Line2), + ok = ?PRIM_FILE:close(Fd6), + + {ok, Fd7} = ?PRIM_FILE:open(Advise, [write]), + {error, einval} = ?PRIM_FILE:advise(Fd7, 0, 0, bad_advise), + ok = ?PRIM_FILE:close(Fd7), %% test write without advise, then a read after an advise - ?line {ok, Fd8} = ?PRIM_FILE:open(Advise, [write]), - ?line ok = ?PRIM_FILE:write(Fd8, Line1), - ?line ok = ?PRIM_FILE:write(Fd8, Line2), - ?line ok = ?PRIM_FILE:close(Fd8), - ?line {ok, Fd9} = ?PRIM_FILE:open(Advise, [read]), + {ok, Fd8} = ?PRIM_FILE:open(Advise, [write]), + ok = ?PRIM_FILE:write(Fd8, Line1), + ok = ?PRIM_FILE:write(Fd8, Line2), + ok = ?PRIM_FILE:close(Fd8), + {ok, Fd9} = ?PRIM_FILE:open(Advise, [read]), Offset = 0, %% same as a 0 length in some implementations Length = length(Line1) + length(Line2), - ?line ok = ?PRIM_FILE:advise(Fd9, Offset, Length, sequential), - ?line {ok, Line1} = ?PRIM_FILE:read_line(Fd9), - ?line {ok, Line2} = ?PRIM_FILE:read_line(Fd9), - ?line eof = ?PRIM_FILE:read_line(Fd9), - ?line ok = ?PRIM_FILE:close(Fd9), + ok = ?PRIM_FILE:advise(Fd9, Offset, Length, sequential), + {ok, Line1} = ?PRIM_FILE:read_line(Fd9), + {ok, Line2} = ?PRIM_FILE:read_line(Fd9), + eof = ?PRIM_FILE:read_line(Fd9), + ok = ?PRIM_FILE:close(Fd9), ok. @@ -1307,7 +1243,6 @@ large_write(Config) when is_list(Config) -> "_large_write"). do_large_write(Name) -> - Dog = test_server:timetrap(test_server:minutes(60)), ChunkSize = (256 bsl 20) + 1, % 256 M + 1 Chunks = 16, % times 16 -> 4 G + 16 Base = 100, @@ -1320,187 +1255,177 @@ do_large_write(Name) -> ok when Wordsize =:= 8 -> {ok,#file_info{size=Size}} = file:read_file_info(Name), {ok,Fd} = prim_file:open(Name, [read]), - check_large_write(Dog, Fd, ChunkSize, 0, Interleave); + check_large_write(Fd, ChunkSize, 0, Interleave); {error,einval} when Wordsize =:= 4 -> ok end. -check_large_write(Dog, Fd, ChunkSize, Pos, [X|Interleave]) -> +check_large_write(Fd, ChunkSize, Pos, [X|Interleave]) -> Pos1 = Pos + ChunkSize, {ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}), {ok,[X]} = prim_file:read(Fd, 1), - check_large_write(Dog, Fd, ChunkSize, Pos1+1, Interleave); -check_large_write(Dog, Fd, _, _, []) -> + check_large_write(Fd, ChunkSize, Pos1+1, Interleave); +check_large_write(Fd, _, _, []) -> eof = prim_file:read(Fd, 1), - test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -allocate(suite) -> []; -allocate(doc) -> "Tests that ?PRIM_FILE:allocate/3 at least doesn't crash."; +%% Tests that ?PRIM_FILE:allocate/3 at least doesn't crash. allocate(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line Allocate = filename:join(PrivDir, - atom_to_list(?MODULE) - ++"_allocate.fil"), + PrivDir = proplists:get_value(priv_dir, Config), + Allocate = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_allocate.fil"), Line1 = "Hello\n", Line2 = "World!\n", - ?line {ok, Fd} = ?PRIM_FILE:open(Allocate, [write, binary]), + {ok, Fd} = ?PRIM_FILE:open(Allocate, [write, binary]), allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])), - ?line ok = ?PRIM_FILE:write(Fd, Line1), - ?line ok = ?PRIM_FILE:write(Fd, Line2), - ?line ok = ?PRIM_FILE:close(Fd), + ok = ?PRIM_FILE:write(Fd, Line1), + ok = ?PRIM_FILE:write(Fd, Line2), + ok = ?PRIM_FILE:close(Fd), - ?line {ok, Fd2} = ?PRIM_FILE:open(Allocate, [write, binary]), + {ok, Fd2} = ?PRIM_FILE:open(Allocate, [write, binary]), allocate_and_assert(Fd2, 1, iolist_size(Line1)), - ?line ok = ?PRIM_FILE:write(Fd2, Line1), - ?line ok = ?PRIM_FILE:write(Fd2, Line2), - ?line ok = ?PRIM_FILE:close(Fd2), + ok = ?PRIM_FILE:write(Fd2, Line1), + ok = ?PRIM_FILE:write(Fd2, Line2), + ok = ?PRIM_FILE:close(Fd2), - ?line {ok, Fd3} = ?PRIM_FILE:open(Allocate, [write, binary]), + {ok, Fd3} = ?PRIM_FILE:open(Allocate, [write, binary]), allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1), - ?line ok = ?PRIM_FILE:write(Fd3, Line1), - ?line ok = ?PRIM_FILE:write(Fd3, Line2), - ?line ok = ?PRIM_FILE:close(Fd3), + ok = ?PRIM_FILE:write(Fd3, Line1), + ok = ?PRIM_FILE:write(Fd3, Line2), + ok = ?PRIM_FILE:close(Fd3), - ?line {ok, Fd4} = ?PRIM_FILE:open(Allocate, [write, binary]), + {ok, Fd4} = ?PRIM_FILE:open(Allocate, [write, binary]), allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])), - ?line ok = ?PRIM_FILE:write(Fd4, Line1), - ?line ok = ?PRIM_FILE:write(Fd4, Line2), - ?line ok = ?PRIM_FILE:close(Fd4), + ok = ?PRIM_FILE:write(Fd4, Line1), + ok = ?PRIM_FILE:write(Fd4, Line2), + ok = ?PRIM_FILE:close(Fd4), ok. allocate_and_assert(Fd, Offset, Length) -> - % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have - % any other negative side effect. We can't really asssert against a - % specific return value, because support for file space pre-allocation - % depends on the OS, OS version and underlying filesystem. - % - % The Linux kernel added support for fallocate() in version 2.6.23, - % which currently works only for the ext4, ocfs2, xfs and btrfs file - % systems. posix_fallocate() is available in glibc as of version - % 2.1.94, but it was buggy until glibc version 2.7. - % - % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE. - % - % Solaris supports posix_fallocate() but only for the UFS file system - % apparently (not supported for ZFS). - % - % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate(). - % - % For Windows there's apparently no way to pre-allocate file space, at - % least with similar API/semantics as posix_fallocate(), fallocate() or - % fcntl F_PREALLOCATE. + %% Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have + %% any other negative side effect. We can't really asssert against a + %% specific return value, because support for file space pre-allocation + %% depends on the OS, OS version and underlying filesystem. + %% + %% The Linux kernel added support for fallocate() in version 2.6.23, + %% which currently works only for the ext4, ocfs2, xfs and btrfs file + %% systems. posix_fallocate() is available in glibc as of version + %% 2.1.94, but it was buggy until glibc version 2.7. + %% + %% Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE. + %% + %% Solaris supports posix_fallocate() but only for the UFS file system + %% apparently (not supported for ZFS). + %% + %% FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate(). + %% + %% For Windows there's apparently no way to pre-allocate file space, at + %% least with similar API/semantics as posix_fallocate(), fallocate() or + %% fcntl F_PREALLOCATE. Result = ?PRIM_FILE:allocate(Fd, Offset, Length), case os:type() of {win32, _} -> - ?line {error, enotsup} = Result; + {error, enotsup} = Result; _ -> - ?line _ = Result + _ = Result end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -delete_a(suite) -> []; -delete_a(doc) -> []; delete_a(Config) when is_list(Config) -> delete(Config, [], "_a"). -delete_b(suite) -> []; -delete_b(doc) -> []; delete_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = delete(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. delete(Config, Handle, Suffix) -> - ?line RootDir = ?config(priv_dir,Config), - ?line Name = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_delete"++Suffix++".fil"), - ?line {ok, Fd1} = ?PRIM_FILE:open(Name, [write]), - ?line ?PRIM_FILE:write(Fd1,"ok.\n"), - ?line ok = ?PRIM_FILE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_delete"++Suffix++".fil"), + {ok, Fd1} = ?PRIM_FILE:open(Name, [write]), + ?PRIM_FILE:write(Fd1,"ok.\n"), + ok = ?PRIM_FILE:close(Fd1), %% Check that the file is readable - ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), - ?line ok = ?PRIM_FILE:close(Fd2), - ?line ok = ?PRIM_FILE_call(delete, Handle, [Name]), + {ok, Fd2} = ?PRIM_FILE:open(Name, [read]), + ok = ?PRIM_FILE:close(Fd2), + ok = ?PRIM_FILE_call(delete, Handle, [Name]), %% Check that the file is not readable anymore - ?line {error, _} = ?PRIM_FILE:open(Name, [read]), + {error, _} = ?PRIM_FILE:open(Name, [read]), %% Try deleting a nonexistent file - ?line {error, enoent} = ?PRIM_FILE_call(delete, Handle, [Name]), + {error, enoent} = ?PRIM_FILE_call(delete, Handle, [Name]), ok. -rename_a(suite) ->[]; -rename_a(doc) ->[]; rename_a(Config) when is_list(Config) -> rename(Config, [], "_a"). -rename_b(suite) ->[]; -rename_b(doc) ->[]; rename_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = rename(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. rename(Config, Handle, Suffix) -> - ?line RootDir = ?config(priv_dir,Config), - ?line FileName1 = atom_to_list(?MODULE)++"_rename"++Suffix++".fil", - ?line FileName2 = atom_to_list(?MODULE)++"_rename"++Suffix++".ful", - ?line Name1 = filename:join(RootDir, FileName1), - ?line Name2 = filename:join(RootDir, FileName2), - ?line {ok,Fd1} = ?PRIM_FILE:open(Name1, [write]), - ?line ok = ?PRIM_FILE:close(Fd1), + RootDir = proplists:get_value(priv_dir,Config), + FileName1 = atom_to_list(?MODULE)++"_rename"++Suffix++".fil", + FileName2 = atom_to_list(?MODULE)++"_rename"++Suffix++".ful", + Name1 = filename:join(RootDir, FileName1), + Name2 = filename:join(RootDir, FileName2), + {ok,Fd1} = ?PRIM_FILE:open(Name1, [write]), + ok = ?PRIM_FILE:close(Fd1), %% Rename, and check that it really changed name - ?line ok = ?PRIM_FILE_call(rename, Handle, [Name1, Name2]), - ?line {error, _} = ?PRIM_FILE:open(Name1, [read]), - ?line {ok, Fd2} = ?PRIM_FILE:open(Name2, [read]), - ?line ok = ?PRIM_FILE:close(Fd2), + ok = ?PRIM_FILE_call(rename, Handle, [Name1, Name2]), + {error, _} = ?PRIM_FILE:open(Name1, [read]), + {ok, Fd2} = ?PRIM_FILE:open(Name2, [read]), + ok = ?PRIM_FILE:close(Fd2), %% Try renaming something to itself - ?line ok = ?PRIM_FILE_call(rename, Handle, [Name2, Name2]), + ok = ?PRIM_FILE_call(rename, Handle, [Name2, Name2]), %% Try renaming something that doesn't exist - ?line {error, enoent} = + {error, enoent} = ?PRIM_FILE_call(rename, Handle, [Name1, Name2]), %% Try renaming to something else than a string - ?line {error, badarg} = + {error, badarg} = ?PRIM_FILE_call(rename, Handle, [Name1, foobar]), - + %% Move between directories - ?line DirName1 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_rename_dir"++Suffix), - ?line DirName2 = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_second_rename_dir"++Suffix), - ?line Name1foo = filename:join(DirName1, "foo.fil"), - ?line Name2foo = filename:join(DirName2, "foo.fil"), - ?line Name2bar = filename:join(DirName2, "bar.dir"), - ?line ok = ?PRIM_FILE:make_dir(DirName1), + DirName1 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_rename_dir"++Suffix), + DirName2 = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_second_rename_dir"++Suffix), + Name1foo = filename:join(DirName1, "foo.fil"), + Name2foo = filename:join(DirName2, "foo.fil"), + Name2bar = filename:join(DirName2, "bar.dir"), + ok = ?PRIM_FILE:make_dir(DirName1), %% The name has to include the full file name, path is not enough - ?line expect( - {error, eexist}, {error, eisdir}, - ?PRIM_FILE_call(rename, Handle, [Name2, DirName1])), - ?line ok = + expect( + {error, eexist}, {error, eisdir}, + ?PRIM_FILE_call(rename, Handle, [Name2, DirName1])), + ok = ?PRIM_FILE_call(rename, Handle, [Name2, Name1foo]), %% Now rename the directory - ?line ok = ?PRIM_FILE_call(rename, Handle, [DirName1, DirName2]), + ok = ?PRIM_FILE_call(rename, Handle, [DirName1, DirName2]), %% And check that the file is there now - ?line {ok,Fd3} = ?PRIM_FILE:open(Name2foo, [read]), - ?line ok = ?PRIM_FILE:close(Fd3), + {ok,Fd3} = ?PRIM_FILE:open(Name2foo, [read]), + ok = ?PRIM_FILE:close(Fd3), %% Try some dirty things now: move the directory into itself - ?line {error, Msg1} = + {error, Msg1} = ?PRIM_FILE_call(rename, Handle, [DirName2, Name2bar]), - ?line io:format("Errmsg1: ~p",[Msg1]), + io:format("Errmsg1: ~p",[Msg1]), %% move dir into a file in itself - ?line {error, Msg2} = + {error, Msg2} = ?PRIM_FILE_call(rename, Handle, [DirName2, Name2foo]), - ?line io:format("Errmsg2: ~p",[Msg2]), + io:format("Errmsg2: ~p",[Msg2]), ok. @@ -1509,45 +1434,41 @@ rename(Config, Handle, Suffix) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -e_delete(suite) -> []; -e_delete(doc) -> []; e_delete(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_delete"), - ?line ok = ?PRIM_FILE:make_dir(Base), + RootDir = proplists:get_value(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_delete"), + ok = ?PRIM_FILE:make_dir(Base), %% Delete a non-existing file. - ?line {error, enoent} = + {error, enoent} = ?PRIM_FILE:delete(filename:join(Base, "non_existing")), %% Delete a directory. - ?line {error, eperm} = ?PRIM_FILE:delete(Base), + {error, eperm} = ?PRIM_FILE:delete(Base), %% Use a path-name with a non-directory component. - ?line Afile = filename:join(Base, "a_file"), - ?line ok = ?PRIM_FILE:write_file(Afile, "hello\n"), - ?line {error, E} = + Afile = filename:join(Base, "a_file"), + ok = ?PRIM_FILE:write_file(Afile, "hello\n"), + {error, E} = expect( {error, enotdir}, {error, enoent}, ?PRIM_FILE:delete(filename:join(Afile, "another_file"))), - ?line io:format("Result: ~p~n", [E]), + io:format("Result: ~p~n", [E]), %% No permission. - ?line case os:type() of - {win32, _} -> - %% Remove a character device. - ?line {error, eacces} = ?PRIM_FILE:delete("nul"); - _ -> - ?line ?PRIM_FILE:write_file_info( - Base, #file_info {mode=0}), - ?line {error, eacces} = ?PRIM_FILE:delete(Afile), - ?line ?PRIM_FILE:write_file_info( - Base, #file_info {mode=8#600}) - end, - - ?line test_server:timetrap_cancel(Dog), + case os:type() of + {win32, _} -> + %% Remove a character device. + {error, eacces} = ?PRIM_FILE:delete("nul"); + _ -> + ?PRIM_FILE:write_file_info( + Base, #file_info {mode=0}), + {error, eacces} = ?PRIM_FILE:delete(Afile), + ?PRIM_FILE:write_file_info( + Base, #file_info {mode=8#600}) + end, + ok. %%% FreeBSD gives EEXIST when renaming a file to an empty dir, although the @@ -1555,66 +1476,63 @@ e_delete(Config) when is_list(Config) -> %%% (What about FreeBSD? We store our nightly build results on a FreeBSD %%% file system, that's what.) -e_rename(suite) -> []; -e_rename(doc) -> []; e_rename(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_rename"), - ?line ok = ?PRIM_FILE:make_dir(Base), + RootDir = proplists:get_value(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_rename"), + ok = ?PRIM_FILE:make_dir(Base), %% Create an empty directory. - ?line EmptyDir = filename:join(Base, "empty_dir"), - ?line ok = ?PRIM_FILE:make_dir(EmptyDir), + EmptyDir = filename:join(Base, "empty_dir"), + ok = ?PRIM_FILE:make_dir(EmptyDir), %% Create a non-empty directory. - ?line NonEmptyDir = filename:join(Base, "non_empty_dir"), - ?line ok = ?PRIM_FILE:make_dir(NonEmptyDir), - ?line ok = ?PRIM_FILE:write_file( - filename:join(NonEmptyDir, "a_file"), - "hello\n"), + NonEmptyDir = filename:join(Base, "non_empty_dir"), + ok = ?PRIM_FILE:make_dir(NonEmptyDir), + ok = ?PRIM_FILE:write_file( + filename:join(NonEmptyDir, "a_file"), + "hello\n"), %% Create another non-empty directory. - ?line ADirectory = filename:join(Base, "a_directory"), - ?line ok = ?PRIM_FILE:make_dir(ADirectory), - ?line ok = ?PRIM_FILE:write_file( - filename:join(ADirectory, "a_file"), - "howdy\n\n"), + ADirectory = filename:join(Base, "a_directory"), + ok = ?PRIM_FILE:make_dir(ADirectory), + ok = ?PRIM_FILE:write_file( + filename:join(ADirectory, "a_file"), + "howdy\n\n"), %% Create a data file. - ?line File = filename:join(Base, "just_a_file"), - ?line ok = ?PRIM_FILE:write_file(File, "anything goes\n\n"), + File = filename:join(Base, "just_a_file"), + ok = ?PRIM_FILE:write_file(File, "anything goes\n\n"), %% Move an existing directory to a non-empty directory. - ?line {error, eexist} = - ?PRIM_FILE:rename(ADirectory, NonEmptyDir), + {error, eexist} = + ?PRIM_FILE:rename(ADirectory, NonEmptyDir), %% Move a root directory. - ?line {error, einval} = ?PRIM_FILE:rename("/", "arne"), + {error, einval} = ?PRIM_FILE:rename("/", "arne"), %% Move Base into Base/new_name. - ?line {error, einval} = - ?PRIM_FILE:rename(Base, filename:join(Base, "new_name")), + {error, einval} = + ?PRIM_FILE:rename(Base, filename:join(Base, "new_name")), %% Overwrite a directory with a file. - ?line expect({error, eexist}, % FreeBSD (?) - {error, eisdir}, - ?PRIM_FILE:rename(File, EmptyDir)), - ?line expect({error, eexist}, % FreeBSD (?) - {error, eisdir}, - ?PRIM_FILE:rename(File, NonEmptyDir)), + expect({error, eexist}, % FreeBSD (?) + {error, eisdir}, + ?PRIM_FILE:rename(File, EmptyDir)), + expect({error, eexist}, % FreeBSD (?) + {error, eisdir}, + ?PRIM_FILE:rename(File, NonEmptyDir)), %% Move a non-existing file. - ?line NonExistingFile = filename:join( - Base, "non_existing_file"), - ?line {error, enoent} = - ?PRIM_FILE:rename(NonExistingFile, NonEmptyDir), + NonExistingFile = filename:join( + Base, "non_existing_file"), + {error, enoent} = + ?PRIM_FILE:rename(NonExistingFile, NonEmptyDir), %% Overwrite a file with a directory. - ?line expect({error, eexist}, % FreeBSD (?) - {error, enotdir}, - ?PRIM_FILE:rename(ADirectory, File)), + expect({error, eexist}, % FreeBSD (?) + {error, enotdir}, + ?PRIM_FILE:rename(ADirectory, File)), %% Move a file to another filesystem. %% XXX - This test case is bogus. We cannot be guaranteed that @@ -1622,166 +1540,149 @@ e_rename(Config) when is_list(Config) -> %% different filesystems. %% %% XXX - Gross hack! - ?line Comment = - case os:type() of - {win32, _} -> - %% At least Windows NT can - %% successfully move a file to - %% another drive. - ok; - {unix, _ } -> - OtherFs = "/tmp", - ?line NameOnOtherFs = - filename:join(OtherFs, - filename:basename(File)), - ?line {ok, Com} = - case ?PRIM_FILE:rename( - File, NameOnOtherFs) of - {error, exdev} -> - %% The file could be in - %% the same filesystem! - {ok, ok}; - ok -> - {ok, {comment, - "Moving between filesystems " - "suceeded, files are probably " - "in the same filesystem!"}}; - {error, eperm} -> - {ok, {comment, "SBS! You don't " - "have the permission to do " - "this test!"}}; - Else -> - Else - end, - Com; - {ose, _} -> - %% disabled for now - ok - end, - ?line test_server:timetrap_cancel(Dog), + Comment = + case os:type() of + {win32, _} -> + %% At least Windows NT can + %% successfully move a file to + %% another drive. + ok; + _ -> + OtherFs = "/tmp", + NameOnOtherFs = + filename:join(OtherFs, + filename:basename(File)), + {ok, Com} = + case ?PRIM_FILE:rename( + File, NameOnOtherFs) of + {error, exdev} -> + %% The file could be in + %% the same filesystem! + {ok, ok}; + ok -> + {ok, {comment, + "Moving between filesystems " + "suceeded, files are probably " + "in the same filesystem!"}}; + {error, eperm} -> + {ok, {comment, "SBS! You don't " + "have the permission to do " + "this test!"}}; + Else -> + Else + end, + Com + end, Comment. -e_make_dir(suite) -> []; -e_make_dir(doc) -> []; e_make_dir(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_make_dir"), - ?line ok = ?PRIM_FILE:make_dir(Base), + RootDir = proplists:get_value(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_make_dir"), + ok = ?PRIM_FILE:make_dir(Base), %% A component of the path does not exist. - ?line {error, enoent} = + {error, enoent} = ?PRIM_FILE:make_dir(filename:join([Base, "a", "b"])), %% Use a path-name with a non-directory component. - ?line Afile = filename:join(Base, "a_directory"), - ?line ok = ?PRIM_FILE:write_file(Afile, "hello\n"), - ?line case ?PRIM_FILE:make_dir( - filename:join(Afile, "another_directory")) of - {error, enotdir} -> io:format("Result: enotdir"); - {error, enoent} -> io:format("Result: enoent") - end, + Afile = filename:join(Base, "a_directory"), + ok = ?PRIM_FILE:write_file(Afile, "hello\n"), + case ?PRIM_FILE:make_dir( + filename:join(Afile, "another_directory")) of + {error, enotdir} -> io:format("Result: enotdir"); + {error, enoent} -> io:format("Result: enoent") + end, %% No permission (on Unix only). case os:type() of {win32, _} -> ok; _ -> - ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}), - ?line {error, eacces} = + ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}), + {error, eacces} = ?PRIM_FILE:make_dir(filename:join(Base, "xxxx")), - ?line - ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600}) + ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600}) end, - ?line test_server:timetrap_cancel(Dog), ok. -e_del_dir(suite) -> []; -e_del_dir(doc) -> []; e_del_dir(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line Base = filename:join(RootDir, - atom_to_list(?MODULE)++"_e_del_dir"), - ?line io:format("Base: ~p", [Base]), - ?line ok = ?PRIM_FILE:make_dir(Base), + RootDir = proplists:get_value(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_del_dir"), + io:format("Base: ~p", [Base]), + ok = ?PRIM_FILE:make_dir(Base), %% Delete a non-existent directory. - ?line {error, enoent} = + {error, enoent} = ?PRIM_FILE:del_dir(filename:join(Base, "non_existing")), %% Use a path-name with a non-directory component. - ?line Afile = filename:join(Base, "a_directory"), - ?line ok = ?PRIM_FILE:write_file(Afile, "hello\n"), - ?line {error, E1} = + Afile = filename:join(Base, "a_directory"), + ok = ?PRIM_FILE:write_file(Afile, "hello\n"), + {error, E1} = expect({error, enotdir}, {error, enoent}, ?PRIM_FILE:del_dir( filename:join(Afile, "another_directory"))), - ?line io:format("Result: ~p", [E1]), + io:format("Result: ~p", [E1]), %% Delete a non-empty directory. %% Delete a non-empty directory. - ?line {error, E2} = + {error, E2} = expect({error, enotempty}, {error, eexist}, {error, eacces}, ?PRIM_FILE:del_dir(Base)), - ?line io:format("Result: ~p", [E2]), + io:format("Result: ~p", [E2]), %% Remove the current directory. - ?line {error, E3} = + {error, E3} = expect({error, einval}, {error, eperm}, % Linux and DUX {error, eacces}, {error, ebusy}, ?PRIM_FILE:del_dir(".")), - ?line io:format("Result: ~p", [E3]), + io:format("Result: ~p", [E3]), %% No permission. case os:type() of {win32, _} -> ok; _ -> - ?line ADirectory = filename:join(Base, "no_perm"), - ?line ok = ?PRIM_FILE:make_dir(ADirectory), - ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}), - ?line {error, eacces} = ?PRIM_FILE:del_dir(ADirectory), - ?line ?PRIM_FILE:write_file_info( - Base, #file_info {mode=8#600}) + ADirectory = filename:join(Base, "no_perm"), + ok = ?PRIM_FILE:make_dir(ADirectory), + ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}), + {error, eacces} = ?PRIM_FILE:del_dir(ADirectory), + ?PRIM_FILE:write_file_info( + Base, #file_info {mode=8#600}) end, - ?line test_server:timetrap_cancel(Dog), ok. %% Trying reading and positioning from a compressed file. -read_compressed(suite) -> []; -read_compressed(doc) -> []; read_compressed(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Real = filename:join(Data, "realmen.html.gz"), - ?line {ok, Fd} = ?PRIM_FILE:open(Real, [read, compressed]), - ?line try_read_file(Fd). + Data = proplists:get_value(data_dir, Config), + Real = filename:join(Data, "realmen.html.gz"), + {ok, Fd} = ?PRIM_FILE:open(Real, [read, compressed]), + try_read_file(Fd). %% Trying reading and positioning from an uncompressed file, %% but with the compressed flag given. -read_not_really_compressed(suite) -> []; -read_not_really_compressed(doc) -> []; read_not_really_compressed(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Priv = ?config(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + Priv = proplists:get_value(priv_dir, Config), %% The file realmen.html might have got CRs added (by WinZip). %% Remove them, or the file positions will not be correct. - ?line Real = filename:join(Data, "realmen.html"), - ?line RealPriv = filename:join(Priv, - atom_to_list(?MODULE)++"_realmen.html"), - ?line {ok, RealDataBin} = ?PRIM_FILE:read_file(Real), - ?line RealData = remove_crs(binary_to_list(RealDataBin), []), - ?line ok = ?PRIM_FILE:write_file(RealPriv, RealData), - ?line {ok, Fd} = ?PRIM_FILE:open(RealPriv, [read, compressed]), - ?line try_read_file(Fd). + Real = filename:join(Data, "realmen.html"), + RealPriv = filename:join(Priv, + atom_to_list(?MODULE)++"_realmen.html"), + {ok, RealDataBin} = ?PRIM_FILE:read_file(Real), + RealData = remove_crs(binary_to_list(RealDataBin), []), + ok = ?PRIM_FILE:write_file(RealPriv, RealData), + {ok, Fd} = ?PRIM_FILE:open(RealPriv, [read, compressed]), + try_read_file(Fd). remove_crs([$\r|Rest], Result) -> remove_crs(Rest, Result); @@ -1791,72 +1692,66 @@ remove_crs([], Result) -> lists:reverse(Result). try_read_file(Fd) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - %% Seek to the current position (nothing should happen). - ?line {ok, 0} = ?PRIM_FILE:position(Fd, 0), - ?line {ok, 0} = ?PRIM_FILE:position(Fd, {cur, 0}), + {ok, 0} = ?PRIM_FILE:position(Fd, 0), + {ok, 0} = ?PRIM_FILE:position(Fd, {cur, 0}), %% Read a few lines from a compressed file. - ?line ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n", - ?line {ok, ShouldBe} = ?PRIM_FILE:read(Fd, length(ShouldBe)), + ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n", + {ok, ShouldBe} = ?PRIM_FILE:read(Fd, length(ShouldBe)), %% Now seek forward. - ?line {ok, 381} = ?PRIM_FILE:position(Fd, 381), - ?line Back = "Back in the good old days -- the \"Golden Era\" " ++ + {ok, 381} = ?PRIM_FILE:position(Fd, 381), + Back = "Back in the good old days -- the \"Golden Era\" " ++ "of computers, it was\n", - ?line {ok, Back} = ?PRIM_FILE:read(Fd, length(Back)), + {ok, Back} = ?PRIM_FILE:read(Fd, length(Back)), %% Try to search forward relative to the current position. - ?line {ok, CurPos} = ?PRIM_FILE:position(Fd, {cur, 0}), - ?line RealPos = 4273, - ?line {ok, RealPos} = ?PRIM_FILE:position(Fd, {cur, RealPos-CurPos}), - ?line RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n", - ?line {ok, RealProg} = ?PRIM_FILE:read(Fd, length(RealProg)), + {ok, CurPos} = ?PRIM_FILE:position(Fd, {cur, 0}), + RealPos = 4273, + {ok, RealPos} = ?PRIM_FILE:position(Fd, {cur, RealPos-CurPos}), + RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n", + {ok, RealProg} = ?PRIM_FILE:read(Fd, length(RealProg)), %% Seek backward. - ?line AfterTitle = length("<TITLE>"), - ?line {ok, AfterTitle} = ?PRIM_FILE:position(Fd, AfterTitle), - ?line Title = "Real Programmers Don't Use PASCAL</TITLE>\n", - ?line {ok, Title} = ?PRIM_FILE:read(Fd, length(Title)), + AfterTitle = length("<TITLE>"), + {ok, AfterTitle} = ?PRIM_FILE:position(Fd, AfterTitle), + Title = "Real Programmers Don't Use PASCAL</TITLE>\n", + {ok, Title} = ?PRIM_FILE:read(Fd, length(Title)), %% Done. - ?line ?PRIM_FILE:close(Fd), - ?line test_server:timetrap_cancel(Dog), + ?PRIM_FILE:close(Fd), ok. -write_compressed(suite) -> []; -write_compressed(doc) -> []; write_compressed(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line Priv = ?config(priv_dir, Config), - ?line MyFile = filename:join(Priv, - atom_to_list(?MODULE)++"_test.gz"), + Priv = proplists:get_value(priv_dir, Config), + MyFile = filename:join(Priv, + atom_to_list(?MODULE)++"_test.gz"), %% Write a file. - ?line {ok, Fd} = ?PRIM_FILE:open(MyFile, [write, compressed]), - ?line {ok, 0} = ?PRIM_FILE:position(Fd, 0), - ?line Prefix = "hello\n", - ?line End = "end\n", - ?line ok = ?PRIM_FILE:write(Fd, Prefix), - ?line {ok, 143} = ?PRIM_FILE:position(Fd, 143), - ?line ok = ?PRIM_FILE:write(Fd, End), - ?line ok = ?PRIM_FILE:close(Fd), + {ok, Fd} = ?PRIM_FILE:open(MyFile, [write, compressed]), + {ok, 0} = ?PRIM_FILE:position(Fd, 0), + Prefix = "hello\n", + End = "end\n", + ok = ?PRIM_FILE:write(Fd, Prefix), + {ok, 143} = ?PRIM_FILE:position(Fd, 143), + ok = ?PRIM_FILE:write(Fd, End), + ok = ?PRIM_FILE:close(Fd), %% Read the file and verify the contents. - ?line {ok, Fd1} = ?PRIM_FILE:open(MyFile, [read, compressed]), - ?line {ok, Prefix} = ?PRIM_FILE:read(Fd1, length(Prefix)), - ?line Second = lists:duplicate(143-length(Prefix), 0) ++ End, - ?line {ok, Second} = ?PRIM_FILE:read(Fd1, length(Second)), - ?line ok = ?PRIM_FILE:close(Fd1), + {ok, Fd1} = ?PRIM_FILE:open(MyFile, [read, compressed]), + {ok, Prefix} = ?PRIM_FILE:read(Fd1, length(Prefix)), + Second = lists:duplicate(143-length(Prefix), 0) ++ End, + {ok, Second} = ?PRIM_FILE:read(Fd1, length(Second)), + ok = ?PRIM_FILE:close(Fd1), %% Ensure that the file is compressed. @@ -1865,71 +1760,61 @@ write_compressed(Config) when is_list(Config) -> {ok, #file_info{size=Size}} when Size < TotalSize -> ok; {ok, #file_info{size=Size}} when Size == TotalSize -> - test_server:fail(file_not_compressed) + ct:fail(file_not_compressed) end, %% Write again to ensure that the file is truncated. - ?line {ok, Fd2} = ?PRIM_FILE:open(MyFile, [write, compressed]), - ?line NewString = "aaaaaaaaaaa", - ?line ok = ?PRIM_FILE:write(Fd2, NewString), - ?line ok = ?PRIM_FILE:close(Fd2), - ?line {ok, Fd3} = ?PRIM_FILE:open(MyFile, [read, compressed]), - ?line {ok, NewString} = ?PRIM_FILE:read(Fd3, 1024), - ?line ok = ?PRIM_FILE:close(Fd3), + {ok, Fd2} = ?PRIM_FILE:open(MyFile, [write, compressed]), + NewString = "aaaaaaaaaaa", + ok = ?PRIM_FILE:write(Fd2, NewString), + ok = ?PRIM_FILE:close(Fd2), + {ok, Fd3} = ?PRIM_FILE:open(MyFile, [read, compressed]), + {ok, NewString} = ?PRIM_FILE:read(Fd3, 1024), + ok = ?PRIM_FILE:close(Fd3), - %% Done. - - ?line test_server:timetrap_cancel(Dog), ok. -compress_errors(suite) -> []; -compress_errors(doc) -> []; compress_errors(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line Data = ?config(data_dir, Config), - ?line {error, enoent} = ?PRIM_FILE:open("non_existing__", + Data = proplists:get_value(data_dir, Config), + {error, enoent} = ?PRIM_FILE:open("non_existing__", [compressed, read]), - ?line {error, einval} = ?PRIM_FILE:open("non_existing__", + {error, einval} = ?PRIM_FILE:open("non_existing__", [compressed, read, write]), %% Read a corrupted .gz file. - ?line Corrupted = filename:join(Data, "corrupted.gz"), - ?line {ok, Fd} = ?PRIM_FILE:open(Corrupted, [read, compressed]), - ?line {error, eio} = ?PRIM_FILE:read(Fd, 100), - ?line ?PRIM_FILE:close(Fd), + Corrupted = filename:join(Data, "corrupted.gz"), + {ok, Fd} = ?PRIM_FILE:open(Corrupted, [read, compressed]), + {error, eio} = ?PRIM_FILE:read(Fd, 100), + ?PRIM_FILE:close(Fd), - ?line test_server:timetrap_cancel(Dog), ok. -make_link_a(doc) -> "Test creating a hard link."; -make_link_a(suite) -> []; +%% Test creating a hard link. make_link_a(Config) when is_list(Config) -> make_link(Config, [], "_a"). -make_link_b(doc) -> "Test creating a hard link."; -make_link_b(suite) -> []; +%% Test creating a hard link. make_link_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = make_link(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. make_link(Config, Handle, Suffix) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_make_link"++Suffix), - ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), - - ?line Name = filename:join(NewDir, "a_file"), - ?line ok = ?PRIM_FILE:write_file(Name, "some contents\n"), - - ?line Alias = filename:join(NewDir, "an_alias"), - ?line Result = + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_make_link"++Suffix), + ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), + + Name = filename:join(NewDir, "a_file"), + ok = ?PRIM_FILE:write_file(Name, "some contents\n"), + + Alias = filename:join(NewDir, "an_alias"), + Result = case ?PRIM_FILE_call(make_link, Handle, [Name, Alias]) of {error, enotsup} -> {skipped, "Links not supported on this platform"}; @@ -1939,58 +1824,48 @@ make_link(Config, Handle, Suffix) -> %% which should in behave exactly as %% ?PRIM_FILE:read_file_info/1 %% since they are not used on symbolic links. - - ?line {ok, Info} = + + {ok, Info} = ?PRIM_FILE_call(read_link_info, Handle, [Name]), - ?line {ok, Info} = + {ok, Info} = ?PRIM_FILE_call(read_link_info, Handle, [Alias]), - ?line #file_info{links = 2, type = regular} = Info, - ?line {error, eexist} = + #file_info{links = 2, type = regular} = Info, + {error, eexist} = ?PRIM_FILE_call(make_link, Handle, [Name, Alias]), ok end, - - ?line test_server:timetrap_cancel(Dog), + Result. -read_link_info_for_non_link(doc) -> - "Test that reading link info for an ordinary file or directory works " - "(on all platforms)."; -read_link_info_for_non_link(suite) -> []; +%% Test that reading link info for an ordinary file or directory works +%% (on all platforms). read_link_info_for_non_link(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - - ?line {ok, #file_info{type=directory}} = ?PRIM_FILE:read_link_info("."), - - ?line test_server:timetrap_cancel(Dog), + {ok, #file_info{type=directory}} = ?PRIM_FILE:read_link_info("."), ok. - -symlinks_a(doc) -> "Test operations on symbolic links (for Unix)."; -symlinks_a(suite) -> []; + +%% Test operations on symbolic links (for Unix). symlinks_a(Config) when is_list(Config) -> symlinks(Config, [], "_a"). -symlinks_b(doc) -> "Test operations on symbolic links (for Unix)."; -symlinks_b(suite) -> []; +%% Test operations on symbolic links (for Unix). symlinks_b(Config) when is_list(Config) -> - ?line {ok, Handle} = ?PRIM_FILE:start(), + {ok, Handle} = ?PRIM_FILE:start(), Result = symlinks(Config, Handle, "_b"), - ?line ok = ?PRIM_FILE:stop(Handle), + ok = ?PRIM_FILE:stop(Handle), Result. symlinks(Config, Handle, Suffix) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE) - ++"_make_symlink"++Suffix), - ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), - - ?line Name = filename:join(NewDir, "a_plain_file"), - ?line ok = ?PRIM_FILE:write_file(Name, "some stupid content\n"), - - ?line Alias = filename:join(NewDir, "a_symlink_alias"), - ?line Result = + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE) + ++"_make_symlink"++Suffix), + ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]), + + Name = filename:join(NewDir, "a_plain_file"), + ok = ?PRIM_FILE:write_file(Name, "some stupid content\n"), + + Alias = filename:join(NewDir, "a_symlink_alias"), + Result = case ?PRIM_FILE_call(make_symlink, Handle, [Name, Alias]) of {error, enotsup} -> {skipped, "Links not supported on this platform"}; @@ -1998,18 +1873,18 @@ symlinks(Config, Handle, Suffix) -> {win32,_} = os:type(), {skipped, "Windows user not privileged to create links"}; ok -> - ?line {ok, Info1} = + {ok, Info1} = ?PRIM_FILE_call(read_file_info, Handle, [Name]), - ?line {ok, Info1} = + {ok, Info1} = ?PRIM_FILE_call(read_file_info, Handle, [Alias]), - ?line {ok, Info1} = + {ok, Info1} = ?PRIM_FILE_call(read_link_info, Handle, [Name]), - ?line #file_info{links = 1, type = regular} = Info1, - - ?line {ok, Info2} = + #file_info{links = 1, type = regular} = Info1, + + {ok, Info2} = ?PRIM_FILE_call(read_link_info, Handle, [Alias]), - ?line #file_info{links=1, type=symlink} = Info2, - ?line {ok, Name} = + #file_info{links=1, type=symlink} = Info2, + {ok, Name} = ?PRIM_FILE_call(read_link, Handle, [Alias]), {ok, Name} = ?PRIM_FILE_call(read_link_all, Handle, [Alias]), @@ -2017,45 +1892,39 @@ symlinks(Config, Handle, Suffix) -> rm_rf(?PRIM_FILE,NewDir), ok end, - - ?line test_server:timetrap_cancel(Dog), + Result. %% Creates as many files as possible during a certain time, %% periodically calls list_dir/2 to check if it works, %% then deletes all files. -list_dir_limit(doc) -> - "Tests if large directories can be read"; -list_dir_limit(suite) -> - []; +%% Tests if large directories can be read. list_dir_limit(Config) when is_list(Config) -> - ?line MaxTime = 120, - ?line MaxNumber = 20000, - ?line Dog = test_server:timetrap( - test_server:seconds(2*MaxTime + MaxTime)), - ?line RootDir = ?config(priv_dir, Config), - ?line NewDir = filename:join(RootDir, - atom_to_list(?MODULE)++"_list_dir_limit"), - ?line {ok, Handle1} = ?PRIM_FILE:start(), - ?line ok = ?PRIM_FILE_call(make_dir, Handle1, [NewDir]), + MaxTime = 120, + MaxNumber = 20000, + ct:timetrap({seconds,2*MaxTime + MaxTime}), + RootDir = proplists:get_value(priv_dir, Config), + NewDir = filename:join(RootDir, + atom_to_list(?MODULE)++"_list_dir_limit"), + {ok, Handle1} = ?PRIM_FILE:start(), + ok = ?PRIM_FILE_call(make_dir, Handle1, [NewDir]), Ref = erlang:start_timer(MaxTime*1000, self(), []), - ?line Result = list_dir_limit_loop(NewDir, Handle1, Ref, MaxNumber, 0), - ?line Time = case erlang:cancel_timer(Ref) of - false -> MaxTime; - T -> MaxTime - (T div 1000) - end, - ?line Number = case Result of - {ok, N} -> N; - {error, _Reason, N} -> N; - _ -> 0 - end, - ?line {ok, Handle2} = ?PRIM_FILE:start(), - ?line list_dir_limit_cleanup(NewDir, Handle2, Number, 0), - ?line ok = ?PRIM_FILE:stop(Handle1), - ?line ok = ?PRIM_FILE:stop(Handle2), - ?line {ok, Number} = Result, - ?line test_server:timetrap_cancel(Dog), + Result = list_dir_limit_loop(NewDir, Handle1, Ref, MaxNumber, 0), + Time = case erlang:cancel_timer(Ref) of + false -> MaxTime; + T -> MaxTime - (T div 1000) + end, + Number = case Result of + {ok, N} -> N; + {error, _Reason, N} -> N; + _ -> 0 + end, + {ok, Handle2} = ?PRIM_FILE:start(), + list_dir_limit_cleanup(NewDir, Handle2, Number, 0), + ok = ?PRIM_FILE:stop(Handle1), + ok = ?PRIM_FILE:stop(Handle2), + {ok, Number} = Result, {comment, "Created " ++ integer_to_list(Number) ++ " files in " ++ integer_to_list(Time) ++ " seconds."}. @@ -2124,7 +1993,7 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) -> %%% list_dir_error(Config) -> - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), NonExisting = filename:join(Priv, "non-existing-dir"), {error,enoent} = prim_file:list_dir(NonExisting), ok. @@ -2134,7 +2003,7 @@ list_dir_error(Config) -> %%% list_dir(Config) -> - RootDir = ?config(priv_dir, Config), + RootDir = proplists:get_value(priv_dir, Config), TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"), ?PRIM_FILE:make_dir(TestDir), list_dir_1(TestDir, 42, []). @@ -2165,11 +2034,13 @@ run_large_file_test(Config, Run, Name) -> {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; {{unix,_},_} -> - N = unix_free(?config(priv_dir, Config)), - io:format("Free disk: ~w KByte~n", [N]), - if N < 5 bsl 20 -> + DiscFree = unix_free(proplists:get_value(priv_dir, Config)), + MemFree = free_memory(), + io:format("Free disk: ~w KByte~n", [DiscFree]), + io:format("Free mem: ~w MByte~n", [MemFree]), + if DiscFree < 5 bsl 20; MemFree < 5 bsl 10 -> %% Less than 5 GByte free - {skip,"Less than 5 GByte free disk"}; + {skip,"Less than 5 GByte free disk/mem"}; true -> do_run_large_file_test(Config, Run, Name) end; @@ -2179,9 +2050,9 @@ run_large_file_test(Config, Run, Name) -> do_run_large_file_test(Config, Run, Name0) -> - Name = filename:join(?config(priv_dir, Config), + Name = filename:join(proplists:get_value(priv_dir, Config), ?MODULE_STRING ++ Name0), - + %% Set up a process that will delete this file. Tester = self(), Deleter = @@ -2194,7 +2065,7 @@ do_run_large_file_test(Config, Run, Name0) -> end, prim_file:delete(Name) end), - + %% Run the test case. Res = Run(Name), @@ -2222,6 +2093,40 @@ zip_data([], Bs) -> zip_data(As, []) -> As. +%% Stolen from emulator -> alloc_SUITE +free_memory() -> + %% Free memory in MB. + try + SMD = memsup:get_system_memory_data(), + {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD), + TotFree = (Free + + case lists:keysearch(cached_memory, 1, SMD) of + {value, {cached_memory, Cached}} -> Cached; + false -> 0 + end + + case lists:keysearch(buffered_memory, 1, SMD) of + {value, {buffered_memory, Buffed}} -> Buffed; + false -> 0 + end), + usable_mem(TotFree) div (1024*1024) + catch + error : undef -> + ct:fail({"os_mon not built"}) + end. + +usable_mem(Memory) -> + case test_server:is_valgrind() of + true -> + %% Valgrind uses extra memory for the V- and A-bits. + %% http://valgrind.org/docs/manual/mc-manual.html#mc-manual.value + %% Docs says it uses "compression to represent the V bits compactly" + %% but let's be conservative and cut usable memory in half. + Memory div 2; + false -> + Memory + end. + + %%%----------------------------------------------------------------- %%% Utilities rm_rf(Mod,Dir) -> diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl index 933dc88d21..b0265393bd 100644 --- a/lib/kernel/test/ram_file_SUITE.erl +++ b/lib/kernel/test/ram_file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2016. 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. @@ -26,9 +26,10 @@ init_per_testcase/2, end_per_testcase/2]). -export([open_modes/1, open_old_modes/1, pread_pwrite/1, position/1, truncate/1, sync/1, get_set_file/1, compress/1, uuencode/1, - large_file_errors/1, large_file_light/1, large_file_heavy/1]). + large_file_errors/1, large_file_light/1, + large_file_heavy/0, large_file_heavy/1]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/file.hrl"). -define(FILE_MODULE, file). % Name of module to test @@ -36,7 +37,9 @@ %%-------------------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [open_modes, open_old_modes, pread_pwrite, position, @@ -59,37 +62,23 @@ end_per_group(_GroupName, Config) -> Config. -init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Time = - case Func of - large_file_heavy -> - ?t:minutes(5); - _ -> - ?t:seconds(10) - end, - Dog = ?t:timetrap(Time), - %% error_logger:info_msg("~p:~p *****~n", [?MODULE, Func]), - [{watchdog, Dog} | Config]. +init_per_testcase(Func, Config) -> + Config. end_per_testcase(_Func, Config) -> - %% error_logger:info_msg("~p:~p END *****~n", [?MODULE, Func]), - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog). + Config. %%-------------------------------------------------------------------------- %% Test suites -open_modes(suite) -> - []; -open_modes(doc) -> - ["Test that the basic read, write and binary options works for open/2."]; +%% Test that the basic read, write and binary options works for open/2. open_modes(Config) when is_list(Config) -> - ?line Str1 = "The quick brown fox ", - ?line Str2 = "jumps over a lazy dog ", - ?line Str = Str1 ++ Str2, - ?line Bin1 = list_to_binary(Str1), - ?line Bin2 = list_to_binary(Str2), - ?line Bin = list_to_binary(Str), + Str1 = "The quick brown fox ", + Str2 = "jumps over a lazy dog ", + Str = Str1 ++ Str2, + Bin1 = list_to_binary(Str1), + Bin2 = list_to_binary(Str2), + Bin = list_to_binary(Str), %% open_read_write(?FILE_MODULE, Str1, [ram, read, write], Str2), open_read(?FILE_MODULE, Str, [ram]), @@ -98,18 +87,15 @@ open_modes(Config) when is_list(Config) -> %% ok. -open_old_modes(suite) -> - []; -open_old_modes(doc) -> - ["Test that the old style read, write and binary options ", - "works for open/2."]; +%% Test that the old style read, write and binary options +%% works for open/2. open_old_modes(Config) when is_list(Config) -> - ?line Str1 = "The quick brown fox ", - ?line Str2 = "jumps over a lazy dog ", - ?line Str = Str1 ++ Str2, - ?line Bin1 = list_to_binary(Str1), - ?line Bin2 = list_to_binary(Str2), - ?line Bin = list_to_binary(Str), + Str1 = "The quick brown fox ", + Str2 = "jumps over a lazy dog ", + Str = Str1 ++ Str2, + Bin1 = list_to_binary(Str1), + Bin2 = list_to_binary(Str2), + Bin = list_to_binary(Str), %% open_read_write(?RAM_FILE_MODULE, Str1, read_write, Str2), open_read(?RAM_FILE_MODULE, Str, read), @@ -119,57 +105,54 @@ open_old_modes(Config) when is_list(Config) -> ok. open_read_write(Module, Data1, Options, Data2) -> - ?line io:format("~p:open_read_write(~p, ~p, ~p, ~p)~n", - [?MODULE, Module, Data1, Options, Data2]), - %% - ?line Size1 = sizeof(Data1), - ?line Size2 = sizeof(Data2), - ?line Data = append(Data1, Data2), - ?line Size = Size1 + Size2, - %% - ?line {ok, Fd} = Module:open(Data1, Options), - ?line {ok, Data1} = Module:read(Fd, Size1), - ?line eof = Module:read(Fd, 1), - ?line {ok, Zero} = Module:read(Fd, 0), - ?line 0 = sizeof(Zero), - ?line ok = Module:write(Fd, Data2), - ?line {ok, 0} = Module:position(Fd, bof), - ?line {ok, Data} = Module:read(Fd, Size), - ?line eof = Module:read(Fd, 1), - ?line {ok, Zero} = Module:read(Fd, 0), - ?line ok = Module:close(Fd), - %% - ?line ok. + io:format("~p:open_read_write(~p, ~p, ~p, ~p)~n", + [?MODULE, Module, Data1, Options, Data2]), + %% + Size1 = sizeof(Data1), + Size2 = sizeof(Data2), + Data = append(Data1, Data2), + Size = Size1 + Size2, + %% + {ok, Fd} = Module:open(Data1, Options), + {ok, Data1} = Module:read(Fd, Size1), + eof = Module:read(Fd, 1), + {ok, Zero} = Module:read(Fd, 0), + 0 = sizeof(Zero), + ok = Module:write(Fd, Data2), + {ok, 0} = Module:position(Fd, bof), + {ok, Data} = Module:read(Fd, Size), + eof = Module:read(Fd, 1), + {ok, Zero} = Module:read(Fd, 0), + ok = Module:close(Fd), + %% + ok. open_read(Module, Data, Options) -> - ?line io:format("~p:open_read(~p, ~p, ~p)~n", - [?MODULE, Module, Data, Options]), - %% - ?line Size = sizeof(Data), - %% - ?line {ok, Fd} = Module:open(Data, Options), - ?line {ok, Data} = Module:read(Fd, Size), - ?line eof = Module:read(Fd, 1), - ?line {ok, Zero} = Module:read(Fd, 0), - ?line 0 = sizeof(Zero), - ?line {error, ebadf} = Module:write(Fd, Data), - ?line {ok, 0} = Module:position(Fd, bof), - ?line {ok, Data} = Module:read(Fd, Size), - ?line eof = Module:read(Fd, 1), - ?line {ok, Zero} = Module:read(Fd, 0), - ?line ok = Module:close(Fd), + io:format("~p:open_read(~p, ~p, ~p)~n", + [?MODULE, Module, Data, Options]), + %% + Size = sizeof(Data), + %% + {ok, Fd} = Module:open(Data, Options), + {ok, Data} = Module:read(Fd, Size), + eof = Module:read(Fd, 1), + {ok, Zero} = Module:read(Fd, 0), + 0 = sizeof(Zero), + {error, ebadf} = Module:write(Fd, Data), + {ok, 0} = Module:position(Fd, bof), + {ok, Data} = Module:read(Fd, Size), + eof = Module:read(Fd, 1), + {ok, Zero} = Module:read(Fd, 0), + ok = Module:close(Fd), %% - ?line ok. + ok. -pread_pwrite(suite) -> - []; -pread_pwrite(doc) -> - ["Test that pread/2,3 and pwrite/2,3 works."]; +%% Test that pread/2,3 and pwrite/2,3 works. pread_pwrite(Config) when is_list(Config) -> - ?line Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x", - ?line Bin = list_to_binary(Str), + Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x", + Bin = list_to_binary(Str), %% pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]), pread_pwrite_test(?FILE_MODULE, Bin, [ram, binary, read, write]), @@ -179,36 +162,33 @@ pread_pwrite(Config) when is_list(Config) -> ok. pread_pwrite_test(Module, Data, Options) -> - ?line io:format("~p:pread_pwrite_test(~p, ~p, ~p)~n", - [?MODULE, Module, Data, Options]), - %% - ?line Size = sizeof(Data), - %% - ?line {ok, Fd} = Module:open([], Options), - ?line ok = Module:pwrite(Fd, 0, Data), - ?line {ok, Data} = Module:pread(Fd, 0, Size+1), - ?line eof = Module:pread(Fd, Size+1, 1), - ?line {ok, Zero} = Module:pread(Fd, Size+1, 0), - ?line 0 = sizeof(Zero), - ?line ok = Module:pwrite(Fd, [{0, Data}, {Size+17, Data}]), - ?line {ok, [Data, - eof, - Data, - Zero]} = Module:pread(Fd, [{Size+17, Size+1}, - {2*Size+17+1, 1}, - {0, Size}, - {2*Size+17+1, 0}]), - ?line ok = Module:close(Fd), - %% - ?line ok. - -position(suite) -> - []; -position(doc) -> - ["Test that position/2 works."]; + io:format("~p:pread_pwrite_test(~p, ~p, ~p)~n", + [?MODULE, Module, Data, Options]), + %% + Size = sizeof(Data), + %% + {ok, Fd} = Module:open([], Options), + ok = Module:pwrite(Fd, 0, Data), + {ok, Data} = Module:pread(Fd, 0, Size+1), + eof = Module:pread(Fd, Size+1, 1), + {ok, Zero} = Module:pread(Fd, Size+1, 0), + 0 = sizeof(Zero), + ok = Module:pwrite(Fd, [{0, Data}, {Size+17, Data}]), + {ok, [Data, + eof, + Data, + Zero]} = Module:pread(Fd, [{Size+17, Size+1}, + {2*Size+17+1, 1}, + {0, Size}, + {2*Size+17+1, 0}]), + ok = Module:close(Fd), + %% + ok. + +%% Test that position/2 works. position(Config) when is_list(Config) -> - ?line Str = "Att vara eller icke vara, det är frågan. ", - ?line Bin = list_to_binary(Str), + Str = "Att vara eller icke vara, det är frågan. ", + Bin = list_to_binary(Str), %% position_test(?FILE_MODULE, Str, [ram, read]), position_test(?FILE_MODULE, Bin, [ram, binary]), @@ -218,79 +198,76 @@ position(Config) when is_list(Config) -> ok. position_test(Module, Data, Options) -> - ?line io:format("~p:position_test(~p, ~p, ~p)~n", - [?MODULE, Module, Data, Options]), - %% - ?line Size = sizeof(Data), - ?line Size_7 = Size+7, - %% - ?line Slice_0_2 = slice(Data, 0, 2), - ?line Slice_0_3 = slice(Data, 0, 3), - ?line Slice_2_5 = slice(Data, 2, 5), - ?line Slice_3_4 = slice(Data, 3, 4), - ?line Slice_5 = slice(Data, 5, Size), - %% - ?line {ok, Fd} = Module:open(Data, Options), - %% - ?line io:format("CUR positions"), - ?line {ok, Slice_0_2} = Module:read(Fd, 2), - ?line {ok, 2} = Module:position(Fd, cur), - ?line {ok, Slice_2_5} = Module:read(Fd, 5), - ?line {ok, 3} = Module:position(Fd, {cur, -4}), - ?line {ok, Slice_3_4} = Module:read(Fd, 4), - ?line {ok, 0} = Module:position(Fd, {cur, -7}), - ?line {ok, Slice_0_3} = Module:read(Fd, 3), - ?line {ok, 0} = Module:position(Fd, {cur, -3}), - ?line {error, einval} = Module:position(Fd, {cur, -1}), - ?line {ok, 0} = Module:position(Fd, 0), - ?line {ok, 2} = Module:position(Fd, {cur, 2}), - ?line {ok, Slice_2_5} = Module:read(Fd, 5), - ?line {ok, Size_7} = Module:position(Fd, {cur, Size}), - ?line {ok, Zero} = Module:read(Fd, 0), - ?line 0 = sizeof(Zero), - ?line eof = Module:read(Fd, 1), - %% - ?line io:format("Absolute and BOF positions"), - ?line {ok, Size} = Module:position(Fd, Size), - ?line eof = Module:read(Fd, 1), - ?line {ok, 5} = Module:position(Fd, 5), - ?line {ok, Slice_5} = Module:read(Fd, Size), - ?line {ok, 2} = Module:position(Fd, {bof, 2}), - ?line {ok, Slice_2_5} = Module:read(Fd, 5), - ?line {ok, 3} = Module:position(Fd, 3), - ?line {ok, Slice_3_4} = Module:read(Fd, 4), - ?line {ok, 0} = Module:position(Fd, bof), - ?line {ok, Slice_0_2} = Module:read(Fd, 2), - ?line {ok, Size_7} = Module:position(Fd, {bof, Size_7}), - ?line {ok, Zero} = Module:read(Fd, 0), - %% - ?line io:format("EOF positions"), - ?line {ok, Size} = Module:position(Fd, eof), - ?line eof = Module:read(Fd, 1), - ?line {ok, 5} = Module:position(Fd, {eof, -Size+5}), - ?line {ok, Slice_5} = Module:read(Fd, Size), - ?line {ok, 2} = Module:position(Fd, {eof, -Size+2}), - ?line {ok, Slice_2_5} = Module:read(Fd, 5), - ?line {ok, 3} = Module:position(Fd, {eof, -Size+3}), - ?line {ok, Slice_3_4} = Module:read(Fd, 4), - ?line {ok, 0} = Module:position(Fd, {eof, -Size}), - ?line {ok, Slice_0_2} = Module:read(Fd, 2), - ?line {ok, Size_7} = Module:position(Fd, {eof, 7}), - ?line {ok, Zero} = Module:read(Fd, 0), - ?line eof = Module:read(Fd, 1), - %% - ?line ok. - - - -truncate(suite) -> - []; -truncate(doc) -> - ["Test that truncate/1 works."]; + io:format("~p:position_test(~p, ~p, ~p)~n", + [?MODULE, Module, Data, Options]), + %% + Size = sizeof(Data), + Size_7 = Size+7, + %% + Slice_0_2 = slice(Data, 0, 2), + Slice_0_3 = slice(Data, 0, 3), + Slice_2_5 = slice(Data, 2, 5), + Slice_3_4 = slice(Data, 3, 4), + Slice_5 = slice(Data, 5, Size), + %% + {ok, Fd} = Module:open(Data, Options), + %% + io:format("CUR positions"), + {ok, Slice_0_2} = Module:read(Fd, 2), + {ok, 2} = Module:position(Fd, cur), + {ok, Slice_2_5} = Module:read(Fd, 5), + {ok, 3} = Module:position(Fd, {cur, -4}), + {ok, Slice_3_4} = Module:read(Fd, 4), + {ok, 0} = Module:position(Fd, {cur, -7}), + {ok, Slice_0_3} = Module:read(Fd, 3), + {ok, 0} = Module:position(Fd, {cur, -3}), + {error, einval} = Module:position(Fd, {cur, -1}), + {ok, 0} = Module:position(Fd, 0), + {ok, 2} = Module:position(Fd, {cur, 2}), + {ok, Slice_2_5} = Module:read(Fd, 5), + {ok, Size_7} = Module:position(Fd, {cur, Size}), + {ok, Zero} = Module:read(Fd, 0), + 0 = sizeof(Zero), + eof = Module:read(Fd, 1), + %% + io:format("Absolute and BOF positions"), + {ok, Size} = Module:position(Fd, Size), + eof = Module:read(Fd, 1), + {ok, 5} = Module:position(Fd, 5), + {ok, Slice_5} = Module:read(Fd, Size), + {ok, 2} = Module:position(Fd, {bof, 2}), + {ok, Slice_2_5} = Module:read(Fd, 5), + {ok, 3} = Module:position(Fd, 3), + {ok, Slice_3_4} = Module:read(Fd, 4), + {ok, 0} = Module:position(Fd, bof), + {ok, Slice_0_2} = Module:read(Fd, 2), + {ok, Size_7} = Module:position(Fd, {bof, Size_7}), + {ok, Zero} = Module:read(Fd, 0), + %% + io:format("EOF positions"), + {ok, Size} = Module:position(Fd, eof), + eof = Module:read(Fd, 1), + {ok, 5} = Module:position(Fd, {eof, -Size+5}), + {ok, Slice_5} = Module:read(Fd, Size), + {ok, 2} = Module:position(Fd, {eof, -Size+2}), + {ok, Slice_2_5} = Module:read(Fd, 5), + {ok, 3} = Module:position(Fd, {eof, -Size+3}), + {ok, Slice_3_4} = Module:read(Fd, 4), + {ok, 0} = Module:position(Fd, {eof, -Size}), + {ok, Slice_0_2} = Module:read(Fd, 2), + {ok, Size_7} = Module:position(Fd, {eof, 7}), + {ok, Zero} = Module:read(Fd, 0), + eof = Module:read(Fd, 1), + %% + ok. + + + +%% Test that truncate/1 works. truncate(Config) when is_list(Config) -> - ?line Str = "Mån ädlare att lida och fördraga " + Str = "Mån ädlare att lida och fördraga " ++ "ett bittert ödes stygn av pilar, ", - ?line Bin = list_to_binary(Str), + Bin = list_to_binary(Str), %% ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]), ok = truncate_test(?FILE_MODULE, Bin, [ram, binary, read, write]), @@ -305,35 +282,32 @@ truncate(Config) when is_list(Config) -> ok. truncate_test(Module, Data, Options) -> - ?line io:format("~p:truncate_test(~p, ~p, ~p)~n", - [?MODULE, Module, Data, Options]), - %% - ?line Size = sizeof(Data), - ?line Size1 = Size-2, - ?line Data1 = slice(Data, 0, Size1), - %% - ?line {ok, Fd} = Module:open(Data, Options), - ?line {ok, Size1} = Module:position(Fd, Size1), - ?line case Module:truncate(Fd) of - ok -> - ?line {ok, 0} = Module:position(Fd, 0), - ?line {ok, Data1} = Module:read(Fd, Size), - ?line ok = Module:close(Fd), - ?line ok; - Error -> - ?line ok = Module:close(Fd), - ?line Error - end. - - - -sync(suite) -> - []; -sync(doc) -> - ["Test that sync/1 at least does not crash."]; + io:format("~p:truncate_test(~p, ~p, ~p)~n", + [?MODULE, Module, Data, Options]), + %% + Size = sizeof(Data), + Size1 = Size-2, + Data1 = slice(Data, 0, Size1), + %% + {ok, Fd} = Module:open(Data, Options), + {ok, Size1} = Module:position(Fd, Size1), + case Module:truncate(Fd) of + ok -> + {ok, 0} = Module:position(Fd, 0), + {ok, Data1} = Module:read(Fd, Size), + ok = Module:close(Fd), + ok; + Error -> + ok = Module:close(Fd), + Error + end. + + + +%% Test that sync/1 at least does not crash. sync(Config) when is_list(Config) -> - ?line Str = "än att ta till vapen mot ett hav av kval. ", - ?line Bin = list_to_binary(Str), + Str = "än att ta till vapen mot ett hav av kval. ", + Bin = list_to_binary(Str), %% sync_test(?FILE_MODULE, Str, [ram, read, write]), sync_test(?FILE_MODULE, Bin, [ram, binary, read, write]), @@ -348,28 +322,25 @@ sync(Config) when is_list(Config) -> ok. sync_test(Module, Data, Options) -> - ?line io:format("~p:sync_test(~p, ~p, ~p)~n", - [?MODULE, Module, Data, Options]), + io:format("~p:sync_test(~p, ~p, ~p)~n", + [?MODULE, Module, Data, Options]), %% - ?line Size = sizeof(Data), + Size = sizeof(Data), %% - ?line {ok, Fd} = Module:open(Data, Options), - ?line ok = Module:sync(Fd), - ?line {ok, Data} = Module:read(Fd, Size+1), - ?line ok. + {ok, Fd} = Module:open(Data, Options), + ok = Module:sync(Fd), + {ok, Data} = Module:read(Fd, Size+1), + ok. -get_set_file(suite) -> - []; -get_set_file(doc) -> - ["Tests get_file/1, set_file/2, get_file_close/1 and get_size/1."]; +%% Tests get_file/1, set_file/2, get_file_close/1 and get_size/1. get_set_file(Config) when is_list(Config) -> %% These two strings should not be of equal length. - ?line Str = "När högan nord blir snöbetäckt, ", - ?line Str2 = "får alla harar byta dräkt. ", - ?line Bin = list_to_binary(Str), - ?line Bin2 = list_to_binary(Str2), + Str = "När högan nord blir snöbetäckt, ", + Str2 = "får alla harar byta dräkt. ", + Bin = list_to_binary(Str), + Bin2 = list_to_binary(Str2), %% ok = get_set_file_test(Str, read_write, Str2), ok = get_set_file_test(Bin, [binary, read, write], Bin2), @@ -379,87 +350,84 @@ get_set_file(Config) when is_list(Config) -> ok. get_set_file_test(Data, Options, Data2) -> - ?line io:format("~p:get_set_file_test(~p, ~p, ~p)~n", - [?MODULE, Data, Options, Data2]), - %% - ?line Size = sizeof(Data), - ?line Size2 = sizeof(Data2), - %% - ?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, Options), - ?line {ok, Size} = ?RAM_FILE_MODULE:get_size(Fd), - ?line {ok, Data} = ?RAM_FILE_MODULE:get_file(Fd), - ?line {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd), - ?line {error, einval} = ?RAM_FILE_MODULE:get_size(Fd), - ?line {ok, Fd2} = ?RAM_FILE_MODULE:open(Data, Options), - ?line case ?RAM_FILE_MODULE:set_file(Fd2, Data2) of - {ok, Size2} -> - ?line {ok, Size2} = ?RAM_FILE_MODULE:get_size(Fd2), - ?line {ok, Data2} = ?RAM_FILE_MODULE:get_file(Fd2), - ?line {ok, Data2} = ?RAM_FILE_MODULE:get_file_close(Fd2), - ?line ok; - {error, _} = Error -> - ?line {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd2), - ?line Error - end. - - - -compress(suite) -> - []; -compress(doc) -> - ["Test that compress/1 and uncompress/1 works."]; + io:format("~p:get_set_file_test(~p, ~p, ~p)~n", + [?MODULE, Data, Options, Data2]), + %% + Size = sizeof(Data), + Size2 = sizeof(Data2), + %% + {ok, Fd} = ?RAM_FILE_MODULE:open(Data, Options), + {ok, Size} = ?RAM_FILE_MODULE:get_size(Fd), + {ok, Data} = ?RAM_FILE_MODULE:get_file(Fd), + {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd), + {error, einval} = ?RAM_FILE_MODULE:get_size(Fd), + {ok, Fd2} = ?RAM_FILE_MODULE:open(Data, Options), + case ?RAM_FILE_MODULE:set_file(Fd2, Data2) of + {ok, Size2} -> + {ok, Size2} = ?RAM_FILE_MODULE:get_size(Fd2), + {ok, Data2} = ?RAM_FILE_MODULE:get_file(Fd2), + {ok, Data2} = ?RAM_FILE_MODULE:get_file_close(Fd2), + ok; + {error, _} = Error -> + {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd2), + Error + end. + + + +%% Test that compress/1 and uncompress/1 works. compress(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Real = filename:join(Data, "realmen.html"), - ?line RealGz = filename:join(Data, "realmen.html.gz"), + Data = proplists:get_value(data_dir, Config), + Real = filename:join(Data, "realmen.html"), + RealGz = filename:join(Data, "realmen.html.gz"), %% %% Uncompress test %% - ?line {ok, FdReal} = ?FILE_MODULE:open(Real, []), - ?line {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]), - ?line {ok, FdRealGz} = ?FILE_MODULE:open(RealGz, []), + {ok, FdReal} = ?FILE_MODULE:open(Real, []), + {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]), + {ok, FdRealGz} = ?FILE_MODULE:open(RealGz, []), %% - ?line {ok, SzGz} = ?FILE_MODULE:copy(FdRealGz, Fd), - ?line {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line true = compare(FdReal, Fd), + {ok, SzGz} = ?FILE_MODULE:copy(FdRealGz, Fd), + {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + true = compare(FdReal, Fd), %% - ?line true = (SzGz =< Sz), + true = (SzGz =< Sz), %% %% Compress and uncompress test %% - ?line {ok, 0} = ?FILE_MODULE:position(FdReal, bof), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line ok = ?FILE_MODULE:truncate(Fd), - ?line {ok, Sz} = ?FILE_MODULE:copy(FdReal, Fd), - ?line {ok, SzGz} = ?RAM_FILE_MODULE:compress(Fd), - ?line {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line {ok, 0} = ?FILE_MODULE:position(FdReal, bof), - ?line true = compare(FdReal, Fd), + {ok, 0} = ?FILE_MODULE:position(FdReal, bof), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + ok = ?FILE_MODULE:truncate(Fd), + {ok, Sz} = ?FILE_MODULE:copy(FdReal, Fd), + {ok, SzGz} = ?RAM_FILE_MODULE:compress(Fd), + {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + {ok, 0} = ?FILE_MODULE:position(FdReal, bof), + true = compare(FdReal, Fd), %% - ?line ok = ?FILE_MODULE:close(FdReal), - ?line ok = ?FILE_MODULE:close(Fd), - ?line ok = ?FILE_MODULE:close(FdRealGz), + ok = ?FILE_MODULE:close(FdReal), + ok = ?FILE_MODULE:close(Fd), + ok = ?FILE_MODULE:close(FdRealGz), %% Test uncompressing data that will be expanded many times. - ?line Huge = iolist_to_binary(mk_42(18)), - ?line HugeSize = byte_size(Huge), - ?line HugeGz = zlib:gzip(Huge), + Huge = iolist_to_binary(mk_42(18)), + HugeSize = byte_size(Huge), + HugeGz = zlib:gzip(Huge), - ?line {ok,HugeFd} = ?FILE_MODULE:open([], [ram,read,write,binary]), - ?line ok = ?FILE_MODULE:write(HugeFd, HugeGz), - ?line {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd), - ?line {ok,0} = ?FILE_MODULE:position(HugeFd, bof), - ?line {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize), + {ok,HugeFd} = ?FILE_MODULE:open([], [ram,read,write,binary]), + ok = ?FILE_MODULE:write(HugeFd, HugeGz), + {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd), + {ok,0} = ?FILE_MODULE:position(HugeFd, bof), + {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize), %% Uncompressing again should do nothing. - ?line {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd), - ?line {ok,0} = ?FILE_MODULE:position(HugeFd, bof), - ?line {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize), + {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd), + {ok,0} = ?FILE_MODULE:position(HugeFd, bof), + {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize), - ?line ok = ?FILE_MODULE:close(HugeFd), + ok = ?FILE_MODULE:close(HugeFd), ok. @@ -469,118 +437,108 @@ mk_42(N) -> B = mk_42(N-1), [B|B]. -uuencode(suite) -> - []; -uuencode(doc) -> - ["Test that uuencode/1 and uudecode/1 works."]; +%% Test that uuencode/1 and uudecode/1 works. uuencode(Config) when is_list(Config) -> - ?line Data = ?config(data_dir, Config), - ?line Real = filename:join(Data, "realmen.html"), - ?line RealUu = filename:join(Data, "realmen.html.uu"), + Data = proplists:get_value(data_dir, Config), + Real = filename:join(Data, "realmen.html"), + RealUu = filename:join(Data, "realmen.html.uu"), %% %% Uudecode test %% - ?line {ok, FdReal} = ?FILE_MODULE:open(Real, []), - ?line {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]), - ?line {ok, FdRealUu} = ?FILE_MODULE:open(RealUu, []), + {ok, FdReal} = ?FILE_MODULE:open(Real, []), + {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]), + {ok, FdRealUu} = ?FILE_MODULE:open(RealUu, []), %% - ?line {ok, SzUu} = ?FILE_MODULE:copy(FdRealUu, Fd), - ?line {ok, Sz} = ?RAM_FILE_MODULE:uudecode(Fd), - ?line true = (Sz =< SzUu), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line true = compare(FdReal, Fd), + {ok, SzUu} = ?FILE_MODULE:copy(FdRealUu, Fd), + {ok, Sz} = ?RAM_FILE_MODULE:uudecode(Fd), + true = (Sz =< SzUu), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + true = compare(FdReal, Fd), %% %% Uuencode and decode test %% F = fun(Offs) -> Size = Sz - Offs, - ?line {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line ok = ?FILE_MODULE:truncate(Fd), - ?line {ok, Size} = ?FILE_MODULE:copy(FdReal, Fd), - ?line {ok, SizeUu} = ?RAM_FILE_MODULE:uuencode(Fd), - ?line true = (Size =< SizeUu), - ?line {ok, Size} = ?RAM_FILE_MODULE:uudecode(Fd), - ?line {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line true = compare(FdReal, Fd) + {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + ok = ?FILE_MODULE:truncate(Fd), + {ok, Size} = ?FILE_MODULE:copy(FdReal, Fd), + {ok, SizeUu} = ?RAM_FILE_MODULE:uuencode(Fd), + true = (Size =< SizeUu), + {ok, Size} = ?RAM_FILE_MODULE:uudecode(Fd), + {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + true = compare(FdReal, Fd) end, lists:foreach(F, lists:seq(0,Sz-1, 43)), - ?line ok = ?FILE_MODULE:close(FdReal), - ?line ok = ?FILE_MODULE:close(Fd), - ?line ok = ?FILE_MODULE:close(FdRealUu), + ok = ?FILE_MODULE:close(FdReal), + ok = ?FILE_MODULE:close(Fd), + ok = ?FILE_MODULE:close(FdRealUu), %% ok. - -large_file_errors(suite) -> - []; -large_file_errors(doc) -> - ["Test error checking of large file offsets."]; +%% Test error checking of large file offsets. large_file_errors(Config) when is_list(Config) -> - ?line TwoGig = 1 bsl 31, - ?line {ok,Fd} = ?RAM_FILE_MODULE:open("1234567890", [read,write]), - ?line {error, einval} = ?FILE_MODULE:read(Fd, TwoGig), - ?line {error, badarg} = ?FILE_MODULE:read(Fd, -1), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,TwoGig}), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,-TwoGig-1}), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,-1}), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur,TwoGig}), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur,-TwoGig-1}), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {eof,TwoGig}), - ?line {error, einval} = ?FILE_MODULE:position(Fd, {eof,-TwoGig-1}), - ?line {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 1), - ?line {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 1), - ?line {error, einval} = ?FILE_MODULE:pread(Fd, -1, 1), - ?line {error, einval} = ?FILE_MODULE:pwrite(Fd, TwoGig, "@"), - ?line {error, einval} = ?FILE_MODULE:pwrite(Fd, -TwoGig-1, "@"), - ?line {error, einval} = ?FILE_MODULE:pwrite(Fd, -1, "@"), - ?line {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 0), - ?line {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 0), - ?line {error, einval} = ?FILE_MODULE:pread(Fd, -1, 0), - ?line ok = ?FILE_MODULE:close(Fd), + TwoGig = 1 bsl 31, + {ok,Fd} = ?RAM_FILE_MODULE:open("1234567890", [read,write]), + {error, einval} = ?FILE_MODULE:read(Fd, TwoGig), + {error, badarg} = ?FILE_MODULE:read(Fd, -1), + {error, einval} = ?FILE_MODULE:position(Fd, {bof,TwoGig}), + {error, einval} = ?FILE_MODULE:position(Fd, {bof,-TwoGig-1}), + {error, einval} = ?FILE_MODULE:position(Fd, {bof,-1}), + {error, einval} = ?FILE_MODULE:position(Fd, {cur,TwoGig}), + {error, einval} = ?FILE_MODULE:position(Fd, {cur,-TwoGig-1}), + {error, einval} = ?FILE_MODULE:position(Fd, {eof,TwoGig}), + {error, einval} = ?FILE_MODULE:position(Fd, {eof,-TwoGig-1}), + {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 1), + {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 1), + {error, einval} = ?FILE_MODULE:pread(Fd, -1, 1), + {error, einval} = ?FILE_MODULE:pwrite(Fd, TwoGig, "@"), + {error, einval} = ?FILE_MODULE:pwrite(Fd, -TwoGig-1, "@"), + {error, einval} = ?FILE_MODULE:pwrite(Fd, -1, "@"), + {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 0), + {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 0), + {error, einval} = ?FILE_MODULE:pread(Fd, -1, 0), + ok = ?FILE_MODULE:close(Fd), ok. -large_file_light(suite) -> - []; -large_file_light(doc) -> - ["Test light operations on a \"large\" ram_file."]; +%% Test light operations on a \large\ ram_file. large_file_light(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), %% Marker for next test case that is to heavy to run in a suite. - ?line ok = ?FILE_MODULE:write_file( - filename:join(PrivDir, "large_file_light"), - <<"TAG">>), - %% - ?line Data = "abcdefghijklmnopqrstuvwzyz", - ?line Size = sizeof(Data), - ?line Max = (1 bsl 31) - 1, - ?line Max__1 = Max - 1, - ?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read]), - ?line {ok, Data} = ?FILE_MODULE:read(Fd, Size+1), - ?line {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, Max-Size-1}), - ?line eof = ?FILE_MODULE:read(Fd, 1), - ?line {ok, Max} = ?FILE_MODULE:position(Fd, {bof, Max}), - ?line {ok, Zero} = ?FILE_MODULE:read(Fd, 0), - ?line 0 = sizeof(Zero), - ?line eof = ?FILE_MODULE:read(Fd, 1), - ?line eof = ?FILE_MODULE:pread(Fd, Max__1, 1), - ?line {ok, Zero} = ?FILE_MODULE:pread(Fd, Max, 0), - ?line eof = ?FILE_MODULE:pread(Fd, Max, 1), + ok = ?FILE_MODULE:write_file( + filename:join(PrivDir, "large_file_light"), + <<"TAG">>), + %% + Data = "abcdefghijklmnopqrstuvwzyz", + Size = sizeof(Data), + Max = (1 bsl 31) - 1, + Max__1 = Max - 1, + {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read]), + {ok, Data} = ?FILE_MODULE:read(Fd, Size+1), + {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, Max-Size-1}), + eof = ?FILE_MODULE:read(Fd, 1), + {ok, Max} = ?FILE_MODULE:position(Fd, {bof, Max}), + {ok, Zero} = ?FILE_MODULE:read(Fd, 0), + 0 = sizeof(Zero), + eof = ?FILE_MODULE:read(Fd, 1), + eof = ?FILE_MODULE:pread(Fd, Max__1, 1), + {ok, Zero} = ?FILE_MODULE:pread(Fd, Max, 0), + eof = ?FILE_MODULE:pread(Fd, Max, 1), ok. -large_file_heavy(suite) -> - []; -large_file_heavy(doc) -> - ["Test operations on a maximum size (2 GByte - 1) ram_file."]; +large_file_heavy() -> + [{timetrap,{minutes,5}}]. + +%% Test operations on a maximum size (2 GByte - 1) ram_file. large_file_heavy(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), %% Check previous test case marker. case ?FILE_MODULE:read_file_info( filename:join(PrivDir, "large_file_light")) of @@ -591,33 +549,33 @@ large_file_heavy(Config) when is_list(Config) -> end. do_large_file_heavy(_Config) -> - ?line Data = "qwertyuiopasdfghjklzxcvbnm", - ?line Size = sizeof(Data), - ?line Max = (1 bsl 31) - 1, - ?line Max__1 = Max - 1, - ?line Max__3 = Max - 3, - ?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read,write]), - ?line {ok, Data} = ?FILE_MODULE:read(Fd, Size+1), - ?line {ok, Max} = ?FILE_MODULE:position(Fd, {eof, Max-Size}), - ?line eof = ?FILE_MODULE:read(Fd, 1), - ?line erlang:display({allocating,2,'GByte',please,be,patient,'...'}), - ?line ok = ?FILE_MODULE:write(Fd, ""), - ?line erlang:display({allocating,2,'GByte',succeeded}), - ?line {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, -1}), - ?line {ok, [0]} = ?FILE_MODULE:read(Fd, 1), - ?line {ok, []} = ?FILE_MODULE:read(Fd, 0), - ?line eof = ?FILE_MODULE:read(Fd, 1), - ?line ok = ?FILE_MODULE:pwrite(Fd, Max-3, "TAG"), - ?line {ok, Max} = ?FILE_MODULE:position(Fd, cur), - ?line {ok, Max__3} = ?FILE_MODULE:position(Fd, {eof, -3}), - ?line {ok, "TAG"} = ?FILE_MODULE:read(Fd, 3+1), - ?line {ok, Max__3} = ?FILE_MODULE:position(Fd, {cur, -3}), - ?line ok = ?FILE_MODULE:write(Fd, "tag"), - ?line {ok, Max} = ?FILE_MODULE:position(Fd, cur), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof), - ?line {ok, "tag"} = ?FILE_MODULE:pread(Fd, Max__3, 3+1), - ?line {ok, 0} = ?FILE_MODULE:position(Fd, cur), - ?line ok = ?FILE_MODULE:close(Fd), + Data = "qwertyuiopasdfghjklzxcvbnm", + Size = sizeof(Data), + Max = (1 bsl 31) - 1, + Max__1 = Max - 1, + Max__3 = Max - 3, + {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read,write]), + {ok, Data} = ?FILE_MODULE:read(Fd, Size+1), + {ok, Max} = ?FILE_MODULE:position(Fd, {eof, Max-Size}), + eof = ?FILE_MODULE:read(Fd, 1), + erlang:display({allocating,2,'GByte',please,be,patient,'...'}), + ok = ?FILE_MODULE:write(Fd, ""), + erlang:display({allocating,2,'GByte',succeeded}), + {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, -1}), + {ok, [0]} = ?FILE_MODULE:read(Fd, 1), + {ok, []} = ?FILE_MODULE:read(Fd, 0), + eof = ?FILE_MODULE:read(Fd, 1), + ok = ?FILE_MODULE:pwrite(Fd, Max-3, "TAG"), + {ok, Max} = ?FILE_MODULE:position(Fd, cur), + {ok, Max__3} = ?FILE_MODULE:position(Fd, {eof, -3}), + {ok, "TAG"} = ?FILE_MODULE:read(Fd, 3+1), + {ok, Max__3} = ?FILE_MODULE:position(Fd, {cur, -3}), + ok = ?FILE_MODULE:write(Fd, "tag"), + {ok, Max} = ?FILE_MODULE:position(Fd, cur), + {ok, 0} = ?FILE_MODULE:position(Fd, bof), + {ok, "tag"} = ?FILE_MODULE:pread(Fd, Max__3, 3+1), + {ok, 0} = ?FILE_MODULE:position(Fd, cur), + ok = ?FILE_MODULE:close(Fd), ok. %%-------------------------------------------------------------------------- @@ -651,7 +609,7 @@ compare_data(A, B) when is_binary(A), is_list(B) -> A == list_to_binary(B); compare_data(A, B) when is_binary(A), is_binary(B) -> A == B. - + sizeof(Data) when is_list(Data) -> length(Data); sizeof(Data) when is_binary(Data) -> diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl index ed30c2dffa..a89a7600a2 100644 --- a/lib/kernel/test/rpc_SUITE.erl +++ b/lib/kernel/test/rpc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. 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,19 +21,22 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). --export([call/1, block_call/1, multicall/1, multicall_timeout/1, +-export([off_heap/1, + call/1, block_call/1, multicall/1, multicall_timeout/1, multicall_dies/1, multicall_node_dies/1, called_dies/1, called_node_dies/1, called_throws/1, call_benchmark/1, async_call/1]). -export([suicide/2, suicide/3, f/0, f2/0]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> - [call, block_call, multicall, multicall_timeout, + [off_heap, call, block_call, multicall, multicall_timeout, multicall_dies, multicall_node_dies, called_dies, called_node_dies, called_throws, call_benchmark, async_call]. @@ -53,274 +56,261 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +off_heap(_Config) -> + %% The rex server process may receive a huge amount of + %% messages. Make sure that they are stored off heap to + %% avoid exessive GCs. + MQD = message_queue_data, + {MQD,off_heap} = process_info(whereis(rex), MQD), + ok. -call(doc) -> "Test different rpc calls"; +%% Test different rpc calls. call(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(30)), - ?line PA = filename:dirname(code:which(?MODULE)), + PA = filename:dirname(code:which(?MODULE)), %% Note. First part of nodename sets response delay in seconds - ?line {ok, N1} = ?t:start_node('3_rpc_SUITE_call', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N2} = ?t:start_node('1_rcp_SUITE_call', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N3} = ?t:start_node('4_rcp_SUITE_call', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N4} = ?t:start_node('8_rcp_SUITE_call', slave, - [{args, "-pa " ++ PA}]), - ?line ok = io:format("~p~n", [[N1, N2, N3]]), - ?line {hej,_,N1} = rpc:call(N1, ?MODULE, f, []), - ?line {hej,_,N2} = rpc:call(N2, ?MODULE, f, [], 2000), - ?line {badrpc,timeout} = rpc:call(N3, ?MODULE, f, [], 2000), - ?line receive after 6000 -> ok end, - ?line [] = flush([]), - ?line {hej,_,N4} = rpc:call(N4, ?MODULE, f, []), - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2), - ?line ?t:stop_node(N3), - ?line ?t:stop_node(N4), - ?t:timetrap_cancel(Timetrap), + {ok, N1} = test_server:start_node('3_rpc_SUITE_call', slave, + [{args, "-pa " ++ PA}]), + {ok, N2} = test_server:start_node('1_rcp_SUITE_call', slave, + [{args, "-pa " ++ PA}]), + {ok, N3} = test_server:start_node('4_rcp_SUITE_call', slave, + [{args, "-pa " ++ PA}]), + {ok, N4} = test_server:start_node('8_rcp_SUITE_call', slave, + [{args, "-pa " ++ PA}]), + ok = io:format("~p~n", [[N1, N2, N3]]), + {hej,_,N1} = rpc:call(N1, ?MODULE, f, []), + {hej,_,N2} = rpc:call(N2, ?MODULE, f, [], 2000), + {badrpc,timeout} = rpc:call(N3, ?MODULE, f, [], 2000), + receive after 6000 -> ok end, + [] = flush([]), + {hej,_,N4} = rpc:call(N4, ?MODULE, f, []), + test_server:stop_node(N1), + test_server:stop_node(N2), + test_server:stop_node(N3), + test_server:stop_node(N4), ok. -block_call(doc) -> "Test different rpc calls"; +%% Test different rpc calls. block_call(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(30)), - ?line PA = filename:dirname(code:which(?MODULE)), + PA = filename:dirname(code:which(?MODULE)), %% Note. First part of nodename sets response delay in seconds - ?line {ok, N1} = ?t:start_node('3_rpc_SUITE_block_call', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N2} = ?t:start_node('1_rcp_SUITE_block_call', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N3} = ?t:start_node('4_rcp_SUITE_block_call', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N4} = ?t:start_node('8_rcp_SUITE_block_call', slave, - [{args, "-pa " ++ PA}]), - ?line ok = io:format("~p~n", [[N1, N2, N3]]), - ?line {hej,_,N1} = rpc:block_call(N1, ?MODULE, f, []), - ?line {hej,_,N2} = rpc:block_call(N2, ?MODULE, f, [], 2000), - ?line {badrpc,timeout} = rpc:block_call(N3, ?MODULE, f, [], 2000), - ?line receive after 6000 -> ok end, - ?line [] = flush([]), - ?line {hej,_,N4} = rpc:block_call(N4, ?MODULE, f, []), - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2), - ?line ?t:stop_node(N3), - ?line ?t:stop_node(N4), - ?t:timetrap_cancel(Timetrap), + {ok, N1} = test_server:start_node('3_rpc_SUITE_block_call', slave, + [{args, "-pa " ++ PA}]), + {ok, N2} = test_server:start_node('1_rcp_SUITE_block_call', slave, + [{args, "-pa " ++ PA}]), + {ok, N3} = test_server:start_node('4_rcp_SUITE_block_call', slave, + [{args, "-pa " ++ PA}]), + {ok, N4} = test_server:start_node('8_rcp_SUITE_block_call', slave, + [{args, "-pa " ++ PA}]), + ok = io:format("~p~n", [[N1, N2, N3]]), + {hej,_,N1} = rpc:block_call(N1, ?MODULE, f, []), + {hej,_,N2} = rpc:block_call(N2, ?MODULE, f, [], 2000), + {badrpc,timeout} = rpc:block_call(N3, ?MODULE, f, [], 2000), + receive after 6000 -> ok end, + [] = flush([]), + {hej,_,N4} = rpc:block_call(N4, ?MODULE, f, []), + test_server:stop_node(N1), + test_server:stop_node(N2), + test_server:stop_node(N3), + test_server:stop_node(N4), ok. -multicall(doc) -> - "OTP-3449"; +%% OTP-3449. multicall(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(20)), - ?line PA = filename:dirname(code:which(?MODULE)), + PA = filename:dirname(code:which(?MODULE)), %% Note. First part of nodename sets response delay in seconds - ?line {ok, N1} = ?t:start_node('3_rpc_SUITE_multicall', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N2} = ?t:start_node('1_rcp_SUITE_multicall', slave, - [{args, "-pa " ++ PA}]), - ?line ok = io:format("~p~n", [[N1, N2]]), - ?line {[{hej,_,N1},{hej,_,N2}],[]} = - rpc:multicall([N1, N2], ?MODULE, f, []), - ?line Msgs = flush([]), - ?line [] = Msgs, - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2), - ?t:timetrap_cancel(Timetrap), + {ok, N1} = test_server:start_node('3_rpc_SUITE_multicall', slave, + [{args, "-pa " ++ PA}]), + {ok, N2} = test_server:start_node('1_rcp_SUITE_multicall', slave, + [{args, "-pa " ++ PA}]), + ok = io:format("~p~n", [[N1, N2]]), + {[{hej,_,N1},{hej,_,N2}],[]} = + rpc:multicall([N1, N2], ?MODULE, f, []), + Msgs = flush([]), + [] = Msgs, + test_server:stop_node(N1), + test_server:stop_node(N2), ok. multicall_timeout(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(30)), - ?line PA = filename:dirname(code:which(?MODULE)), + PA = filename:dirname(code:which(?MODULE)), %% Note. First part of nodename sets response delay in seconds - ?line {ok, N1} = ?t:start_node('11_rpc_SUITE_multicall', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N2} = ?t:start_node('8_rpc_SUITE_multicall', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N3} = ?t:start_node('5_rpc_SUITE_multicall', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N4} = ?t:start_node('2_rcp_SUITE_multicall', slave, - [{args, "-pa " ++ PA}]), - ?line ok = io:format("~p~n", [[N1, N2]]), - ?line {[{hej,_,N3},{hej,_,N4}],[N1, N2]} = - rpc:multicall([N3, N1, N2, N4], ?MODULE, f, [], ?t:seconds(6)), - ?t:sleep(?t:seconds(8)), %% Wait for late answers - ?line Msgs = flush([]), - ?line [] = Msgs, - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2), - ?line ?t:stop_node(N3), - ?line ?t:stop_node(N4), - ?t:timetrap_cancel(Timetrap), + {ok, N1} = test_server:start_node('11_rpc_SUITE_multicall', slave, + [{args, "-pa " ++ PA}]), + {ok, N2} = test_server:start_node('8_rpc_SUITE_multicall', slave, + [{args, "-pa " ++ PA}]), + {ok, N3} = test_server:start_node('5_rpc_SUITE_multicall', slave, + [{args, "-pa " ++ PA}]), + {ok, N4} = test_server:start_node('2_rcp_SUITE_multicall', slave, + [{args, "-pa " ++ PA}]), + ok = io:format("~p~n", [[N1, N2]]), + {[{hej,_,N3},{hej,_,N4}],[N1, N2]} = + rpc:multicall([N3, N1, N2, N4], ?MODULE, f, [], 6000), + ct:sleep({seconds,8}), %Wait for late answers + Msgs = flush([]), + [] = Msgs, + test_server:stop_node(N1), + test_server:stop_node(N2), + test_server:stop_node(N3), + test_server:stop_node(N4), ok. multicall_dies(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(30)), - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, N1} = ?t:start_node('rpc_SUITE_multicall_dies_1', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N2} = ?t:start_node('rcp_SUITE_multicall_dies_2', slave, - [{args, "-pa " ++ PA}]), - ?line Nodes = [N1, N2], + PA = filename:dirname(code:which(?MODULE)), + {ok, N1} = test_server:start_node('rpc_SUITE_multicall_dies_1', slave, + [{args, "-pa " ++ PA}]), + {ok, N2} = test_server:start_node('rcp_SUITE_multicall_dies_2', slave, + [{args, "-pa " ++ PA}]), + Nodes = [N1, N2], %% - ?line {[{badrpc, {'EXIT', normal}}, {badrpc, {'EXIT', normal}}], []} = + {[{badrpc, {'EXIT', normal}}, {badrpc, {'EXIT', normal}}], []} = do_multicall(Nodes, erlang, exit, [normal]), - ?line {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} = + {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} = do_multicall(Nodes, erlang, exit, [abnormal]), - ?line {[{badrpc, {'EXIT', {badarith, _}}}, - {badrpc, {'EXIT', {badarith, _}}}], - []} = + {[{badrpc, {'EXIT', {badarith, _}}}, + {badrpc, {'EXIT', {badarith, _}}}], + []} = do_multicall(Nodes, erlang, 'div', [1, 0]), - ?line {[{badrpc, {'EXIT', {badarg, _}}}, - {badrpc, {'EXIT', {badarg, _}}}], - []} = + {[{badrpc, {'EXIT', {badarg, _}}}, + {badrpc, {'EXIT', {badarg, _}}}], + []} = do_multicall(Nodes, erlang, atom_to_list, [1]), - ?line {[{badrpc, {'EXIT', {undef, _}}}, - {badrpc, {'EXIT', {undef, _}}}], - []} = + {[{badrpc, {'EXIT', {undef, _}}}, + {badrpc, {'EXIT', {undef, _}}}], + []} = do_multicall(Nodes, ?MODULE, suicide, []), - ?line {[timeout, timeout], []} = + {[timeout, timeout], []} = do_multicall(Nodes, ?MODULE, suicide, [link, normal]), - ?line {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} = + {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} = do_multicall(Nodes, ?MODULE, suicide, [link, abnormal]), - ?line {[timeout, timeout], []} = + {[timeout, timeout], []} = do_multicall(Nodes, ?MODULE, suicide, [exit, normal]), - ?line {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} = + {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} = do_multicall(Nodes, ?MODULE, suicide, [exit, abnormal]), - ?line {[{badrpc, {'EXIT', killed}}, {badrpc, {'EXIT', killed}}], []} = + {[{badrpc, {'EXIT', killed}}, {badrpc, {'EXIT', killed}}], []} = do_multicall(Nodes, ?MODULE, suicide, [exit, kill]), %% - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2), - ?t:timetrap_cancel(Timetrap), + test_server:stop_node(N1), + test_server:stop_node(N2), ok. do_multicall(Nodes, Mod, Func, Args) -> - ?line ok = io:format("~p:~p~p~n", [Mod, Func, Args]), - ?line Result = rpc:multicall(Nodes, Mod, Func, Args), - ?line Msgs = flush([]), - ?line [] = Msgs, + ok = io:format("~p:~p~p~n", [Mod, Func, Args]), + Result = rpc:multicall(Nodes, Mod, Func, Args), + Msgs = flush([]), + [] = Msgs, Result. -multicall_node_dies(doc) -> - ""; multicall_node_dies(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(60)), - %% do_multicall_2_nodes_dies(?MODULE, suicide, [erlang, halt, []]), do_multicall_2_nodes_dies(?MODULE, suicide, [init, stop, []]), do_multicall_2_nodes_dies(?MODULE, suicide, [rpc, stop, []]), - %% - ?t:timetrap_cancel(Timetrap), ok. do_multicall_2_nodes_dies(Mod, Func, Args) -> - ?line ok = io:format("~p:~p~p~n", [Mod, Func, Args]), - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, N1} = ?t:start_node('rpc_SUITE_multicall_node_dies_1', slave, - [{args, "-pa " ++ PA}]), - ?line {ok, N2} = ?t:start_node('rcp_SUITE_multicall_node_dies_2', slave, - [{args, "-pa " ++ PA}]), - ?line Nodes = [N1, N2], - ?line {[], Nodes} = rpc:multicall(Nodes, Mod, Func, Args), - ?line Msgs = flush([]), - ?line [] = Msgs, + ok = io:format("~p:~p~p~n", [Mod, Func, Args]), + PA = filename:dirname(code:which(?MODULE)), + {ok, N1} = test_server:start_node('rpc_SUITE_multicall_node_dies_1', slave, + [{args, "-pa " ++ PA}]), + {ok, N2} = test_server:start_node('rcp_SUITE_multicall_node_dies_2', slave, + [{args, "-pa " ++ PA}]), + Nodes = [N1, N2], + {[], Nodes} = rpc:multicall(Nodes, Mod, Func, Args), + Msgs = flush([]), + [] = Msgs, ok. -called_dies(doc) -> - "OTP-3766"; +%% OTP-3766. called_dies(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(210)), - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, N} = ?t:start_node(rpc_SUITE_called_dies, slave, - [{args, "-pa " ++ PA}]), + PA = filename:dirname(code:which(?MODULE)), + {ok, N} = test_server:start_node(rpc_SUITE_called_dies, slave, + [{args, "-pa " ++ PA}]), %% - ?line rep(fun (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',normal}}} = - {Tag,apply(rpc, Call, Args)} - end, N, erlang, exit, [normal]), - ?line rep(fun (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',abnormal}}} = - {Tag,apply(rpc, Call, Args)} - end, N, erlang, exit, [abnormal]), - ?line rep(fun (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',{badarith,_}}}} = - {Tag,apply(rpc, Call, Args)} - end, N, erlang, 'div', [1,0]), - ?line rep(fun (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',{badarg,_}}}} = - {Tag,apply(rpc, Call, Args)} - end, N, erlang, atom_to_list, [1]), - ?line rep(fun (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',{undef,_}}}} = - {Tag,apply(rpc, Call, Args)} - end, N, ?MODULE, suicide, []), + rep(fun (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',normal}}} = + {Tag,apply(rpc, Call, Args)} + end, N, erlang, exit, [normal]), + rep(fun (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',abnormal}}} = + {Tag,apply(rpc, Call, Args)} + end, N, erlang, exit, [abnormal]), + rep(fun (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',{badarith,_}}}} = + {Tag,apply(rpc, Call, Args)} + end, N, erlang, 'div', [1,0]), + rep(fun (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',{badarg,_}}}} = + {Tag,apply(rpc, Call, Args)} + end, N, erlang, atom_to_list, [1]), + rep(fun (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',{undef,_}}}} = + {Tag,apply(rpc, Call, Args)} + end, N, ?MODULE, suicide, []), %% TrapExit = process_flag(trap_exit, true), %% - ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> - {Tag,timeout} = - {Tag,apply(rpc, Call, Args)}, - {Tag,flush,[{'EXIT',_,normal}]} = - {Tag,flush,flush([])}; - (Tag, Call, Args) -> - {Tag,timeout} = - {Tag,apply(rpc, Call, Args)} - end, N, ?MODULE, suicide, [link,normal]), - ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> - {Tag,timeout} = - {Tag,apply(rpc, Call, Args)}, - {Tag,flush,[{'EXIT',_,abnormal}]} = - {Tag,flush,flush([])}; - (Tag, block_call, Args) -> - {Tag,timeout} = - {Tag,apply(rpc, block_call, Args)}; - (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',abnormal}}} = - {Tag,apply(rpc, Call, Args)} - end, N, ?MODULE, suicide, [link,abnormal]), - ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> - {Tag,timeout} = - {Tag,apply(rpc, Call, Args)}, - {Tag,flush,[{'EXIT',_,normal}]} = - {Tag,flush,flush([])}; - (Tag, Call, Args) -> - {Tag,timeout} = - {Tag,apply(rpc, Call, Args)} - end, N, ?MODULE, suicide, [exit,normal]), - ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> - {Tag,timeout} = - {Tag,apply(rpc, Call, Args)}, - {Tag,flush,[{'EXIT',_,abnormal}]} = - {Tag,flush,flush([])}; - (Tag, block_call, Args) -> - {Tag,timeout} = - {Tag,apply(rpc, block_call, Args)}; - (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',abnormal}}} = - {Tag,apply(rpc, Call, Args)} - end, N, ?MODULE, suicide, [exit,abnormal]), + rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> + {Tag,timeout} = + {Tag,apply(rpc, Call, Args)}, + {Tag,flush,[{'EXIT',_,normal}]} = + {Tag,flush,flush([])}; + (Tag, Call, Args) -> + {Tag,timeout} = + {Tag,apply(rpc, Call, Args)} + end, N, ?MODULE, suicide, [link,normal]), + rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> + {Tag,timeout} = + {Tag,apply(rpc, Call, Args)}, + {Tag,flush,[{'EXIT',_,abnormal}]} = + {Tag,flush,flush([])}; + (Tag, block_call, Args) -> + {Tag,timeout} = + {Tag,apply(rpc, block_call, Args)}; + (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',abnormal}}} = + {Tag,apply(rpc, Call, Args)} + end, N, ?MODULE, suicide, [link,abnormal]), + rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> + {Tag,timeout} = + {Tag,apply(rpc, Call, Args)}, + {Tag,flush,[{'EXIT',_,normal}]} = + {Tag,flush,flush([])}; + (Tag, Call, Args) -> + {Tag,timeout} = + {Tag,apply(rpc, Call, Args)} + end, N, ?MODULE, suicide, [exit,normal]), + rep(fun (Tag, Call, Args=[Node|_]) when Node == node() -> + {Tag,timeout} = + {Tag,apply(rpc, Call, Args)}, + {Tag,flush,[{'EXIT',_,abnormal}]} = + {Tag,flush,flush([])}; + (Tag, block_call, Args) -> + {Tag,timeout} = + {Tag,apply(rpc, block_call, Args)}; + (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',abnormal}}} = + {Tag,apply(rpc, Call, Args)} + end, N, ?MODULE, suicide, [exit,abnormal]), %% process_flag(trap_exit, TrapExit), %% - ?line rep(fun %% A local [exit,kill] would kill the test case process - (_Tag, _Call, [Node|_]) when Node == node() -> - ok; - %% A block_call [exit,kill] would kill the rpc server - (_Tag, block_call, _Args) -> ok; - (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',killed}}} = - {Tag,apply(rpc, Call, Args)} - end, N, ?MODULE, suicide, [exit,kill]), + rep(fun %% A local [exit,kill] would kill the test case process + (_Tag, _Call, [Node|_]) when Node == node() -> + ok; + %% A block_call [exit,kill] would kill the rpc server + (_Tag, block_call, _Args) -> ok; + (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',killed}}} = + {Tag,apply(rpc, Call, Args)} + end, N, ?MODULE, suicide, [exit,kill]), %% - ?line [] = flush([]), - ?line ?t:stop_node(N), - ?t:timetrap_cancel(Timetrap), + [] = flush([]), + test_server:stop_node(N), ok. rep(Fun, N, M, F, A) -> @@ -335,7 +325,7 @@ rep(Fun, N, M, F, A) -> Fun(9, block_call, [N, M, F, A, infinity]), Fun(10, block_call, [N, M, F, A, 3000]), ok. - + suicide(link, Reason) -> spawn_link( @@ -364,109 +354,83 @@ suicide(Mod, Func, Args) -> -called_node_dies(doc) -> - ""; -called_node_dies(suite) -> []; called_node_dies(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:minutes(2)), - ?line PA = filename:dirname(code:which(?MODULE)), - %% - ?line node_rep( - fun (Tag, Call, Args) -> - {Tag,{badrpc,nodedown}} = - {Tag,apply(rpc, Call, Args)} - end, "rpc_SUITE_called_node_dies_1", - PA, ?MODULE, suicide, [erlang,halt,[]]), - ?line node_rep( - fun (Tag, Call, Args) -> - {Tag,{badrpc,nodedown}} = - {Tag,apply(rpc, Call, Args)} - end, "rpc_SUITE_called_node_dies_2", - PA, ?MODULE, suicide, [init,stop,[]]), - ?line node_rep( - fun (Tag, Call, Args=[_|_]) -> - {Tag,{'EXIT',{killed,_}}} = - {Tag,catch {noexit,apply(rpc, Call, Args)}} - end, "rpc_SUITE_called_node_dies_3", - PA, ?MODULE, suicide, [erlang,exit,[rex,kill]]), - ?line node_rep( - fun %% Cannot block call rpc - will hang - (_Tag, block_call, _Args) -> ok; - (Tag, Call, Args=[_|_]) -> - {Tag,{'EXIT',{normal,_}}} = - {Tag,catch {noexit,apply(rpc, Call, Args)}} - end, "rpc_SUITE_called_node_dies_4", - PA, ?MODULE, suicide, [rpc,stop,[]]), - %% - ?t:timetrap_cancel(Timetrap), + PA = filename:dirname(code:which(?MODULE)), + + node_rep( + fun (Call, Args) -> + {badrpc,nodedown} = apply(rpc, Call, Args) + end, "rpc_SUITE_called_node_dies_1", + PA, ?MODULE, suicide, [erlang,halt,[]]), + + node_rep( + fun (Call, Args) -> + {badrpc,nodedown} = apply(rpc, Call, Args) + end, "rpc_SUITE_called_node_dies_2", + PA, ?MODULE, suicide, [init,stop,[]]), + + node_rep( + fun (Call, Args=[_|_]) -> + {badrpc,{'EXIT',{killed,_}}} = apply(rpc, Call, Args) + end, "rpc_SUITE_called_node_dies_3", + PA, ?MODULE, suicide, [erlang,exit,[rex,kill]]), + + node_rep( + fun (block_call, _Args) -> + %% Cannot block call rpc - will hang + ok; + (Call, Args=[_|_]) -> + {badrpc,{'EXIT',{normal,_}}} = apply(rpc, Call, Args) + end, "rpc_SUITE_called_node_dies_4", + PA, ?MODULE, suicide, [rpc,stop,[]]), + ok. node_rep(Fun, Name, PA, M, F, A) -> - {ok, Na} = ?t:start_node(list_to_atom(Name++"_a"), slave, - [{args, "-pa " ++ PA}]), - Fun(a, call, [Na, M, F, A]), - catch ?t:stop_node(Na), - {ok, Nb} = ?t:start_node(list_to_atom(Name++"_b"), slave, - [{args, "-pa " ++ PA}]), - Fun(b, call, [Nb, M, F, A, infinity]), - catch ?t:stop_node(Nb), - {ok, Nc} = ?t:start_node(list_to_atom(Name++"_c"), slave, - [{args, "-pa " ++ PA}]), - Fun(c, call, [Nc, M, F, A, infinity]), - catch ?t:stop_node(Nc), - %% - {ok, Nd} = ?t:start_node(list_to_atom(Name++"_d"), slave, - [{args, "-pa " ++ PA}]), - Fun(d, block_call, [Nd, M, F, A]), - catch ?t:stop_node(Nd), - {ok, Ne} = ?t:start_node(list_to_atom(Name++"_e"), slave, - [{args, "-pa " ++ PA}]), - Fun(e, block_call, [Ne, M, F, A, infinity]), - catch ?t:stop_node(Ne), - {ok, Nf} = ?t:start_node(list_to_atom(Name++"_f"), slave, - [{args, "-pa " ++ PA}]), - Fun(f, block_call, [Nf, M, F, A, infinity]), - catch ?t:stop_node(Nf), + node_rep_call(a, call, [M,F,A], Fun, Name, PA), + node_rep_call(b, call, [M,F,A,infinity], Fun, Name, PA), + node_rep_call(c, block_call, [M,F,A], Fun, Name, PA), + node_rep_call(d, block_call, [M,F,A,infinity], Fun, Name, PA). + +node_rep_call(Tag, Call, Args, Fun, Name0, PA) -> + Name = list_to_atom(Name0 ++ "_" ++ atom_to_list(Tag)), + {ok, N} = test_server:start_node(Name, slave, + [{args, "-pa " ++ PA}]), + Fun(Call, [N|Args]), + catch test_server:stop_node(N), ok. - - -called_throws(doc) -> - "OTP-3766"; +%% OTP-3766. called_throws(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(10)), - ?line PA = filename:dirname(code:which(?MODULE)), + PA = filename:dirname(code:which(?MODULE)), %% - ?line {ok, N} = ?t:start_node(rpc_SUITE_called_throws, slave, - [{args, "-pa " ++ PA}]), + {ok, N} = test_server:start_node(rpc_SUITE_called_throws, slave, + [{args, "-pa " ++ PA}]), %% - ?line rep(fun (Tag, Call, Args) -> - {Tag,up} = - {Tag,apply(rpc, Call, Args)} - end, N, erlang, throw, [up]), - ?line rep(fun (Tag, Call, Args) -> - {Tag,{badrpc,{'EXIT',reason}}} = - {Tag,apply(rpc, Call, Args)} - end, N, erlang, throw, [{'EXIT',reason}]), + rep(fun (Tag, Call, Args) -> + {Tag,up} = + {Tag,apply(rpc, Call, Args)} + end, N, erlang, throw, [up]), + rep(fun (Tag, Call, Args) -> + {Tag,{badrpc,{'EXIT',reason}}} = + {Tag,apply(rpc, Call, Args)} + end, N, erlang, throw, [{'EXIT',reason}]), %% - ?line ?t:stop_node(N), - ?t:timetrap_cancel(Timetrap), + test_server:stop_node(N), ok. call_benchmark(Config) when is_list(Config) -> - Timetrap = ?t:timetrap(?t:seconds(120)), PA = filename:dirname(code:which(?MODULE)), - {ok, Node} = ?t:start_node(rpc_SUITE_call_benchmark, slave, - [{args, "-pa " ++ PA}]), + {ok, Node} = test_server:start_node(rpc_SUITE_call_benchmark, slave, + [{args, "-pa " ++ PA}]), Iter = case erlang:system_info(modified_timing_level) of undefined -> 10000; _ -> 500 %Modified timing - spawn is slower end, Res = do_call_benchmark(Node, Iter), - ?t:stop_node(Node), - ?t:timetrap_cancel(Timetrap), + test_server:stop_node(Node), Res. do_call_benchmark(Node, M) when is_integer(M), M > 0 -> @@ -486,31 +450,28 @@ do_call_benchmark(Node, I, M) -> do_call_benchmark(Node, I+1, M). async_call(Config) when is_list(Config) -> - Dog = ?t:timetrap(?t:seconds(120)), - %% Note: First part of nodename sets response delay in seconds. - ?line PA = filename:dirname(code:which(?MODULE)), - ?line NodeArgs = [{args,"-pa "++ PA}], - ?line {ok,Node1} = ?t:start_node('1_rpc_SUITE_call', slave, NodeArgs), - ?line {ok,Node2} = ?t:start_node('10_rpc_SUITE_call', slave, NodeArgs), - ?line {ok,Node3} = ?t:start_node('20_rpc_SUITE_call', slave, NodeArgs), - ?line Promise1 = rpc:async_call(Node1, ?MODULE, f, []), - ?line Promise2 = rpc:async_call(Node2, ?MODULE, f, []), - ?line Promise3 = rpc:async_call(Node3, ?MODULE, f, []), + PA = filename:dirname(code:which(?MODULE)), + NodeArgs = [{args,"-pa "++ PA}], + {ok,Node1} = test_server:start_node('1_rpc_SUITE_call', slave, NodeArgs), + {ok,Node2} = test_server:start_node('10_rpc_SUITE_call', slave, NodeArgs), + {ok,Node3} = test_server:start_node('20_rpc_SUITE_call', slave, NodeArgs), + Promise1 = rpc:async_call(Node1, ?MODULE, f, []), + Promise2 = rpc:async_call(Node2, ?MODULE, f, []), + Promise3 = rpc:async_call(Node3, ?MODULE, f, []), %% Test fast timeouts. - ?line timeout = rpc:nb_yield(Promise2), - ?line timeout = rpc:nb_yield(Promise2, 10), + timeout = rpc:nb_yield(Promise2), + timeout = rpc:nb_yield(Promise2, 10), %% Let Node1 finish its work before yielding. - ?t:sleep(?t:seconds(2)), - ?line {hej,_,Node1} = rpc:yield(Promise1), + ct:sleep({seconds,2}), + {hej,_,Node1} = rpc:yield(Promise1), %% Wait for the Node2 and Node3. - ?line {value,{hej,_,Node2}} = rpc:nb_yield(Promise2, infinity), - ?line {hej,_,Node3} = rpc:yield(Promise3), + {value,{hej,_,Node2}} = rpc:nb_yield(Promise2, infinity), + {hej,_,Node3} = rpc:yield(Promise3), - ?t:timetrap_cancel(Dog), ok. %%% diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index a82b9c5fcd..bfa564c32c 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2012. All Rights Reserved. +%% Copyright Ericsson AB 2011-2017. 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. @@ -53,7 +53,7 @@ init_per_suite(Config) -> {{unix,sunos}, {5,8,_}} -> {skip, "Solaris 8 not supported for now"}; _ -> - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), SFilename = filename:join(Priv, "sendfile_small.html"), {ok, DS} = file:open(SFilename,[write,raw]), file:write(DS,"yo baby yo"), @@ -100,13 +100,13 @@ init_per_testcase(TC,Config) when TC == t_sendfile_recvduring; %% Check if sendfile is supported on this platform case catch sendfile_send(Send) of ok -> - Config; + init_per_testcase(t_sendfile, Config); Error -> ct:log("Error: ~p",[Error]), {skip,"Not supported"} end; init_per_testcase(_Tc,Config) -> - Config. + Config ++ [{sendfile_opts,[{use_threads,false}]}]. t_sendfile_small(Config) when is_list(Config) -> diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl index 7df0bc3d2f..be23a1933f 100644 --- a/lib/kernel/test/seq_trace_SUITE.erl +++ b/lib/kernel/test/seq_trace_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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,17 +27,21 @@ trace_exit/1, distributed_exit/1, call/1, port/1, match_set_seq_token/1, gc_seq_token/1]). -% internal exports +%% internal exports -export([simple_tracer/2, one_time_receiver/0, one_time_receiver/1, start_tracer/0, stop_tracer/1, do_match_set_seq_token/1, do_gc_seq_token/1, countdown_start/2]). - %-define(line_trace, 1). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). --define(default_timeout, ?t:minutes(1)). +-define(TIMESTAMP_MODES, [no_timestamp, + timestamp, + monotonic_timestamp, + strict_monotonic_timestamp]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [token_set_get, tracer_set_get, print, send, @@ -62,343 +66,373 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Case, Config) -> - ?line Dog = test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. %% Verifies that the set_token and get_token functions work as expected -token_set_get(doc) -> []; -token_set_get(suite) -> []; token_set_get(Config) when is_list(Config) -> - ?line Self = self(), - ?line seq_trace:reset_trace(), + do_token_set_get(timestamp), + do_token_set_get(monotonic_timestamp), + do_token_set_get(strict_monotonic_timestamp). + +do_token_set_get(TsType) -> + io:format("Testing ~p~n", [TsType]), + Flags = case TsType of + timestamp -> 15; + strict_monotonic_timestamp -> 23; + monotonic_timestamp -> 39 + end, + Self = self(), + seq_trace:reset_trace(), %% Test that initial seq_trace is disabled - ?line [] = seq_trace:get_token(), + [] = seq_trace:get_token(), %% Test setting and reading the different fields - ?line 0 = seq_trace:set_token(label,17), - ?line {label,17} = seq_trace:get_token(label), - ?line false = seq_trace:set_token(print,true), - ?line {print,true} = seq_trace:get_token(print), - ?line false = seq_trace:set_token(send,true), - ?line {send,true} = seq_trace:get_token(send), - ?line false = seq_trace:set_token('receive',true), - ?line {'receive',true} = seq_trace:get_token('receive'), - ?line false = seq_trace:set_token(timestamp,true), - ?line {timestamp,true} = seq_trace:get_token(timestamp), + 0 = seq_trace:set_token(label,17), + {label,17} = seq_trace:get_token(label), + false = seq_trace:set_token(print,true), + {print,true} = seq_trace:get_token(print), + false = seq_trace:set_token(send,true), + {send,true} = seq_trace:get_token(send), + false = seq_trace:set_token('receive',true), + {'receive',true} = seq_trace:get_token('receive'), + false = seq_trace:set_token(TsType,true), + {TsType,true} = seq_trace:get_token(TsType), %% Check the whole token - ?line {15,17,0,Self,0} = seq_trace:get_token(), % all flags are set + {Flags,17,0,Self,0} = seq_trace:get_token(), % all flags are set %% Test setting and reading the 'serial' field - ?line {0,0} = seq_trace:set_token(serial,{3,5}), - ?line {serial,{3,5}} = seq_trace:get_token(serial), + {0,0} = seq_trace:set_token(serial,{3,5}), + {serial,{3,5}} = seq_trace:get_token(serial), %% Check the whole token, test that a whole token can be set and get - ?line {15,17,5,Self,3} = seq_trace:get_token(), - ?line seq_trace:set_token({15,19,7,Self,5}), - ?line {15,19,7,Self,5} = seq_trace:get_token(), + {Flags,17,5,Self,3} = seq_trace:get_token(), + seq_trace:set_token({Flags,19,7,Self,5}), + {Flags,19,7,Self,5} = seq_trace:get_token(), %% Check that receive timeout does not reset token - ?line receive after 0 -> ok end, - ?line {15,19,7,Self,5} = seq_trace:get_token(), + receive after 0 -> ok end, + {Flags,19,7,Self,5} = seq_trace:get_token(), %% Check that token can be unset - ?line {15,19,7,Self,5} = seq_trace:set_token([]), - ?line [] = seq_trace:get_token(), + {Flags,19,7,Self,5} = seq_trace:set_token([]), + [] = seq_trace:get_token(), %% Check that Previous serial counter survived unset token - ?line 0 = seq_trace:set_token(label, 17), - ?line {0,17,0,Self,5} = seq_trace:get_token(), + 0 = seq_trace:set_token(label, 17), + {0,17,0,Self,5} = seq_trace:get_token(), %% Check that reset_trace resets the token and clears %% the Previous serial counter - ?line seq_trace:reset_trace(), - ?line [] = seq_trace:get_token(), - ?line 0 = seq_trace:set_token(label, 19), - ?line {0,19,0,Self,0} = seq_trace:get_token(), + seq_trace:reset_trace(), + [] = seq_trace:get_token(), + 0 = seq_trace:set_token(label, 19), + {0,19,0,Self,0} = seq_trace:get_token(), %% Cleanup - ?line seq_trace:reset_trace(), + seq_trace:reset_trace(), ok. -tracer_set_get(doc) -> []; -tracer_set_get(suite) -> []; tracer_set_get(Config) when is_list(Config) -> - ?line Self = self(), - ?line seq_trace:set_system_tracer(self()), - ?line Self = seq_trace:get_system_tracer(), - ?line Self = seq_trace:set_system_tracer(false), - ?line false = seq_trace:get_system_tracer(), + Self = self(), + seq_trace:set_system_tracer(self()), + Self = seq_trace:get_system_tracer(), + Self = seq_trace:set_system_tracer(false), + false = seq_trace:get_system_tracer(), %% Set the system tracer to a port. - ?line Port = load_tracer(Config), - ?line seq_trace:set_system_tracer(Port), - ?line Port = seq_trace:get_system_tracer(), - ?line Port = seq_trace:set_system_tracer(false), - ?line false = seq_trace:get_system_tracer(), + Port = load_tracer(Config), + seq_trace:set_system_tracer(Port), + Port = seq_trace:get_system_tracer(), + Port = seq_trace:set_system_tracer(false), + false = seq_trace:get_system_tracer(), ok. -print(doc) -> []; -print(suite) -> []; print(Config) when is_list(Config) -> - ?line start_tracer(), - ?line seq_trace:set_token(print,true), - ?line seq_trace:print(0,print1), - ?line seq_trace:print(1,print2), - ?line seq_trace:print(print3), - ?line seq_trace:reset_trace(), - ?line [{0,{print,_,_,[],print1}}, - {0,{print,_,_,[],print3}}] = stop_tracer(2). + lists:foreach(fun do_print/1, ?TIMESTAMP_MODES). + +do_print(TsType) -> + start_tracer(), + set_token_flags([print, TsType]), + seq_trace:print(0,print1), + seq_trace:print(1,print2), + seq_trace:print(print3), + seq_trace:reset_trace(), + [{0,{print,_,_,[],print1}, Ts0}, + {0,{print,_,_,[],print3}, Ts1}] = stop_tracer(2), + check_ts(TsType, Ts0), + check_ts(TsType, Ts1). -send(doc) -> []; -send(suite) -> []; send(Config) when is_list(Config) -> - ?line seq_trace:reset_trace(), - ?line start_tracer(), - ?line Receiver = spawn(?MODULE,one_time_receiver,[]), - ?line seq_trace:set_token(send,true), - ?line Receiver ! send, - ?line Self = self(), - ?line seq_trace:reset_trace(), - ?line [{0,{send,_,Self,Receiver,send}}] = stop_tracer(1). - -distributed_send(doc) -> []; -distributed_send(suite) -> []; + lists:foreach(fun do_send/1, ?TIMESTAMP_MODES). + +do_send(TsType) -> + seq_trace:reset_trace(), + start_tracer(), + Receiver = spawn(?MODULE,one_time_receiver,[]), + set_token_flags([send, TsType]), + Receiver ! send, + Self = self(), + seq_trace:reset_trace(), + [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1), + check_ts(TsType, Ts). + distributed_send(Config) when is_list(Config) -> - ?line {ok,Node} = start_node(seq_trace_other,[]), - ?line {_,Dir} = code:is_loaded(?MODULE), - ?line Mdir = filename:dirname(Dir), - ?line true = rpc:call(Node,code,add_patha,[Mdir]), - ?line seq_trace:reset_trace(), - ?line start_tracer(), - ?line Receiver = spawn(Node,?MODULE,one_time_receiver,[]), - ?line seq_trace:set_token(send,true), - ?line Receiver ! send, - ?line Self = self(), - ?line seq_trace:reset_trace(), - ?line stop_node(Node), - ?line [{0,{send,_,Self,Receiver,send}}] = stop_tracer(1). - -recv(doc) -> []; -recv(suite) -> []; + lists:foreach(fun do_distributed_send/1, ?TIMESTAMP_MODES). + +do_distributed_send(TsType) -> + {ok,Node} = start_node(seq_trace_other,[]), + {_,Dir} = code:is_loaded(?MODULE), + Mdir = filename:dirname(Dir), + true = rpc:call(Node,code,add_patha,[Mdir]), + seq_trace:reset_trace(), + start_tracer(), + Receiver = spawn(Node,?MODULE,one_time_receiver,[]), + set_token_flags([send,TsType]), + Receiver ! send, + Self = self(), + seq_trace:reset_trace(), + stop_node(Node), + [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1), + check_ts(TsType, Ts). + + recv(Config) when is_list(Config) -> - ?line seq_trace:reset_trace(), - ?line start_tracer(), - ?line Receiver = spawn(?MODULE,one_time_receiver,[]), - ?line seq_trace:set_token('receive',true), - ?line Receiver ! 'receive', + lists:foreach(fun do_recv/1, ?TIMESTAMP_MODES). + +do_recv(TsType) -> + seq_trace:reset_trace(), + start_tracer(), + Receiver = spawn(?MODULE,one_time_receiver,[]), + set_token_flags(['receive',TsType]), + Receiver ! 'receive', %% let the other process receive the message: - ?line receive after 1 -> ok end, - ?line Self = self(), - ?line seq_trace:reset_trace(), - ?line [{0,{'receive',_,Self,Receiver,'receive'}}] = stop_tracer(1). + receive after 1 -> ok end, + Self = self(), + seq_trace:reset_trace(), + [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = stop_tracer(1), + check_ts(TsType, Ts). -distributed_recv(doc) -> []; -distributed_recv(suite) -> []; distributed_recv(Config) when is_list(Config) -> - ?line {ok,Node} = start_node(seq_trace_other,[]), - ?line {_,Dir} = code:is_loaded(?MODULE), - ?line Mdir = filename:dirname(Dir), - ?line true = rpc:call(Node,code,add_patha,[Mdir]), - ?line seq_trace:reset_trace(), - ?line rpc:call(Node,?MODULE,start_tracer,[]), - ?line Receiver = spawn(Node,?MODULE,one_time_receiver,[]), - ?line seq_trace:set_token('receive',true), - ?line Receiver ! 'receive', + lists:foreach(fun do_distributed_recv/1, ?TIMESTAMP_MODES). + +do_distributed_recv(TsType) -> + {ok,Node} = start_node(seq_trace_other,[]), + {_,Dir} = code:is_loaded(?MODULE), + Mdir = filename:dirname(Dir), + true = rpc:call(Node,code,add_patha,[Mdir]), + seq_trace:reset_trace(), + rpc:call(Node,?MODULE,start_tracer,[]), + Receiver = spawn(Node,?MODULE,one_time_receiver,[]), + set_token_flags(['receive',TsType]), + Receiver ! 'receive', %% let the other process receive the message: - ?line receive after 1 -> ok end, - ?line Self = self(), - ?line seq_trace:reset_trace(), - ?line Result = rpc:call(Node,?MODULE,stop_tracer,[1]), - ?line stop_node(Node), - ?line ok = io:format("~p~n",[Result]), - ?line [{0,{'receive',_,Self,Receiver,'receive'}}] = Result. - -trace_exit(doc) -> []; -trace_exit(suite) -> []; + receive after 1 -> ok end, + Self = self(), + seq_trace:reset_trace(), + Result = rpc:call(Node,?MODULE,stop_tracer,[1]), + stop_node(Node), + ok = io:format("~p~n",[Result]), + [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = Result, + check_ts(TsType, Ts). + trace_exit(Config) when is_list(Config) -> - ?line seq_trace:reset_trace(), - ?line start_tracer(), - ?line Receiver = spawn_link(?MODULE, one_time_receiver, [exit]), - ?line process_flag(trap_exit, true), - ?line seq_trace:set_token(send,true), - ?line Receiver ! {before, exit}, + lists:foreach(fun do_trace_exit/1, ?TIMESTAMP_MODES). + +do_trace_exit(TsType) -> + seq_trace:reset_trace(), + start_tracer(), + Receiver = spawn_link(?MODULE, one_time_receiver, [exit]), + process_flag(trap_exit, true), + set_token_flags([send, TsType]), + Receiver ! {before, exit}, %% let the other process receive the message: - ?line receive + receive {'EXIT', Receiver, {exit, {before, exit}}} -> seq_trace:set_token([]); Other -> seq_trace:set_token([]), - ?t:fail({received, Other}) + ct:fail({received, Other}) end, - ?line Self = self(), - ?line Result = stop_tracer(2), - ?line seq_trace:reset_trace(), - ?line ok = io:format("~p~n", [Result]), - ?line [{0, {send, {0,1}, Self, Receiver, {before, exit}}}, + Self = self(), + Result = stop_tracer(2), + seq_trace:reset_trace(), + ok = io:format("~p~n", [Result]), + [{0, {send, {0,1}, Self, Receiver, {before, exit}}, Ts0}, {0, {send, {1,2}, Receiver, Self, - {'EXIT', Receiver, {exit, {before, exit}}}}}] = Result. + {'EXIT', Receiver, {exit, {before, exit}}}}, Ts1}] = Result, + check_ts(TsType, Ts0), + check_ts(TsType, Ts1). -distributed_exit(doc) -> []; -distributed_exit(suite) -> []; distributed_exit(Config) when is_list(Config) -> - ?line {ok, Node} = start_node(seq_trace_other, []), - ?line {_, Dir} = code:is_loaded(?MODULE), - ?line Mdir = filename:dirname(Dir), - ?line true = rpc:call(Node, code, add_patha, [Mdir]), - ?line seq_trace:reset_trace(), - ?line rpc:call(Node, ?MODULE, start_tracer,[]), - ?line Receiver = spawn_link(Node, ?MODULE, one_time_receiver, [exit]), - ?line process_flag(trap_exit, true), - ?line seq_trace:set_token(send, true), - ?line Receiver ! {before, exit}, + lists:foreach(fun do_distributed_exit/1, ?TIMESTAMP_MODES). + +do_distributed_exit(TsType) -> + {ok, Node} = start_node(seq_trace_other, []), + {_, Dir} = code:is_loaded(?MODULE), + Mdir = filename:dirname(Dir), + true = rpc:call(Node, code, add_patha, [Mdir]), + seq_trace:reset_trace(), + rpc:call(Node, ?MODULE, start_tracer,[]), + Receiver = spawn_link(Node, ?MODULE, one_time_receiver, [exit]), + process_flag(trap_exit, true), + set_token_flags([send, TsType]), + Receiver ! {before, exit}, %% let the other process receive the message: - ?line receive + receive {'EXIT', Receiver, {exit, {before, exit}}} -> seq_trace:set_token([]); Other -> seq_trace:set_token([]), - ?t:fail({received, Other}) + ct:fail({received, Other}) end, - ?line Self = self(), - ?line Result = rpc:call(Node, ?MODULE, stop_tracer, [1]), - ?line seq_trace:reset_trace(), - ?line stop_node(Node), - ?line ok = io:format("~p~n", [Result]), - ?line [{0, {send, {1, 2}, Receiver, Self, - {'EXIT', Receiver, {exit, {before, exit}}}}}] = Result. + Self = self(), + Result = rpc:call(Node, ?MODULE, stop_tracer, [1]), + seq_trace:reset_trace(), + stop_node(Node), + ok = io:format("~p~n", [Result]), + [{0, {send, {1, 2}, Receiver, Self, + {'EXIT', Receiver, {exit, {before, exit}}}}, Ts}] = Result, + check_ts(TsType, Ts). call(doc) -> "Tests special forms {is_seq_trace} and {get_seq_token} " "in trace match specs."; -call(suite) -> - []; call(Config) when is_list(Config) -> - ?line Self = self(), - ?line seq_trace:reset_trace(), - ?line TrA = transparent_tracer(), - ?line 1 = + Self = self(), + seq_trace:reset_trace(), + TrA = transparent_tracer(), + 1 = erlang:trace(Self, true, [call, set_on_spawn, {tracer, TrA(pid)}]), - ?line 1 = + 1 = erlang:trace_pattern({?MODULE, call_tracee_1, 1}, [{'_', [], [{message, {{{self}, {get_seq_token}}}}]}], [local]), - ?line 1 = + 1 = erlang:trace_pattern({?MODULE, call_tracee_2, 1}, [{'_', [{is_seq_trace}], [{message, {{{self}, {get_seq_token}}}}]}], [local]), - ?line RefA = make_ref(), - ?line Pid2A = spawn_link( + RefA = make_ref(), + Pid2A = spawn_link( fun() -> receive {_, msg, RefA} -> ok end, RefA = call_tracee_2(RefA), Self ! {self(), msg, RefA} end), - ?line Pid1A = spawn_link( + Pid1A = spawn_link( fun() -> receive {_, msg, RefA} -> ok end, RefA = call_tracee_1(RefA), Pid2A ! {self(), msg, RefA} end), - ?line Pid1A ! {Self, msg, RefA}, + Pid1A ! {Self, msg, RefA}, %% The message is passed Self -> Pid1B -> Pid2B -> Self. %% Traced functions are called in Pid1B and Pid2B. - ?line receive {Pid2A, msg, RefA} -> ok end, + receive {Pid2A, msg, RefA} -> ok end, %% Only call_tracee1 will be traced since the guard for %% call_tracee2 requires a sequential trace. The trace %% token is undefined. - ?line Token2A = [], - ?line {ok, [{trace, Pid1A, call, + Token2A = [], + {ok, [{trace, Pid1A, call, {?MODULE, call_tracee_1, [RefA]}, {Pid1A, Token2A}}]} = TrA({stop, 1}), - ?line seq_trace:reset_trace(), + seq_trace:reset_trace(), - ?line TrB = transparent_tracer(), - ?line 1 = + TrB = transparent_tracer(), + 1 = erlang:trace(Self, true, [call, set_on_spawn, {tracer, TrB(pid)}]), - ?line Label = 17, - ?line seq_trace:set_token(label, Label), % Token enters here!! - ?line RefB = make_ref(), - ?line Pid2B = spawn_link( + Label = 17, + seq_trace:set_token(label, Label), % Token enters here!! + RefB = make_ref(), + Pid2B = spawn_link( fun() -> receive {_, msg, RefB} -> ok end, RefB = call_tracee_2(RefB), Self ! {self(), msg, RefB} end), - ?line Pid1B = spawn_link( + Pid1B = spawn_link( fun() -> receive {_, msg, RefB} -> ok end, RefB = call_tracee_1(RefB), Pid2B ! {self(), msg, RefB} end), - ?line Pid1B ! {Self, msg, RefB}, + Pid1B ! {Self, msg, RefB}, %% The message is passed Self -> Pid1B -> Pid2B -> Self, and the %% seq_trace token follows invisibly. Traced functions are %% called in Pid1B and Pid2B. Seq_trace flags == 0 so no %% seq_trace messages are generated. - ?line receive {Pid2B, msg, RefB} -> ok end, + receive {Pid2B, msg, RefB} -> ok end, %% The values of these counters {.., 1, _, 0}, {.., 2, _, 1} %% depend on that seq_trace has been reset just before this test. - ?line Token1B = {0, Label, 1, Self, 0}, - ?line Token2B = {0, Label, 2, Pid1B, 1}, - ?line {ok, [{trace, Pid1B, call, + Token1B = {0, Label, 1, Self, 0}, + Token2B = {0, Label, 2, Pid1B, 1}, + {ok, [{trace, Pid1B, call, {?MODULE, call_tracee_1, [RefB]}, {Pid1B, Token1B}}, {trace, Pid2B, call, {?MODULE, call_tracee_2, [RefB]}, {Pid2B, Token2B}}]} = TrB({stop,2}), - ?line seq_trace:reset_trace(), + seq_trace:reset_trace(), ok. -port(doc) -> - "Send trace messages to a port."; -port(suite) -> []; +%% Send trace messages to a port. port(Config) when is_list(Config) -> - ?line Port = load_tracer(Config), - ?line seq_trace:set_system_tracer(Port), - - ?line seq_trace:set_token(print, true), - ?line Small = [small,term], - ?line seq_trace:print(0, Small), - ?line case get_port_message(Port) of - {seq_trace,0,{print,_,_,[],Small}} -> + lists:foreach(fun (TsType) -> do_port(TsType, Config) end, + ?TIMESTAMP_MODES). + +do_port(TsType, Config) -> + io:format("Testing ~p~n",[TsType]), + Port = load_tracer(Config), + seq_trace:set_system_tracer(Port), + + set_token_flags([print, TsType]), + Small = [small,term], + seq_trace:print(0, Small), + case get_port_message(Port) of + {seq_trace,0,{print,_,_,[],Small}} when TsType == no_timestamp -> + ok; + {seq_trace,0,{print,_,_,[],Small},Ts0} when TsType /= no_timestamp -> + check_ts(TsType, Ts0), ok; Other -> - ?line seq_trace:reset_trace(), - ?line ?t:fail({unexpected,Other}) + seq_trace:reset_trace(), + ct:fail({unexpected,Other}) end, %% OTP-4218 Messages from ports should not affect seq trace token. %% %% Check if trace token still is active on this process after %% the get_port_message/1 above that receives from a port. - ?line OtherSmall = [other | Small], - ?line seq_trace:print(0, OtherSmall), - ?line seq_trace:reset_trace(), - ?line case get_port_message(Port) of - {seq_trace,0,{print,_,_,[],OtherSmall}} -> + OtherSmall = [other | Small], + seq_trace:print(0, OtherSmall), + seq_trace:reset_trace(), + case get_port_message(Port) of + {seq_trace,0,{print,_,_,[],OtherSmall}} when TsType == no_timestamp -> + ok; + {seq_trace,0,{print,_,_,[],OtherSmall}, Ts1} when TsType /= no_timestamp -> + check_ts(TsType, Ts1), ok; Other1 -> - ?line ?t:fail({unexpected,Other1}) + ct:fail({unexpected,Other1}) end, - ?line seq_trace:set_token(print, true), - ?line Huge = huge_data(), - ?line seq_trace:print(0, Huge), - ?line seq_trace:reset_trace(), - ?line case get_port_message(Port) of + seq_trace:set_token(print, true), + Huge = huge_data(), + seq_trace:print(0, Huge), + seq_trace:reset_trace(), + case get_port_message(Port) of {seq_trace,0,{print,_,_,[],Huge}} -> ok; Other2 -> - ?line ?t:fail({unexpected,Other2}) + ct:fail({unexpected,Other2}) end, + unlink(Port), + exit(Port,kill), ok. get_port_message(Port) -> @@ -406,21 +440,19 @@ get_port_message(Port) -> {Port,{data,Bin}} when is_binary(Bin) -> binary_to_term(Bin); Other -> - ?t:fail({unexpected,Other}) + ct:fail({unexpected,Other}) after 5000 -> - ?t:fail(timeout) + ct:fail(timeout) end. -match_set_seq_token(suite) -> - []; match_set_seq_token(doc) -> ["Tests that match spec function set_seq_token does not " "corrupt the heap"]; match_set_seq_token(Config) when is_list(Config) -> - ?line Parent = self(), - ?line Timetrap = test_server:timetrap(test_server:seconds(20)), + Parent = self(), + %% OTP-4222 Match spec 'set_seq_token' corrupts heap %% %% This test crashes the emulator if the bug in question is present, @@ -428,13 +460,13 @@ match_set_seq_token(Config) when is_list(Config) -> %% %% All the timeout stuff is here to get decent accuracy of the error %% return value, instead of just 'timeout'. - % - ?line {ok, Sandbox} = start_node(seq_trace_other, []), - ?line true = rpc:call(Sandbox, code, add_patha, + %% + {ok, Sandbox} = start_node(seq_trace_other, []), + true = rpc:call(Sandbox, code, add_patha, [filename:dirname(code:which(?MODULE))]), - ?line Lbl = 4711, + Lbl = 4711, %% Do the possibly crashing test - ?line P1 = + P1 = spawn( fun () -> Parent ! {self(), @@ -442,16 +474,16 @@ match_set_seq_token(Config) when is_list(Config) -> ?MODULE, do_match_set_seq_token, [Lbl])} end), %% Probe the node with a simple rpc request, to see if it is alive. - ?line P2 = + P2 = spawn( fun () -> receive after 4000 -> ok end, Parent ! {self(), rpc:call(Sandbox, erlang, abs, [-1])} end), %% If the test node hangs completely, this timer expires. - ?line R3 = erlang:start_timer(8000, self(), void), + R3 = erlang:start_timer(8000, self(), void), %% - ?line {ok, Log} = + {ok, Log} = receive {P1, Result} -> exit(P2, done), @@ -466,10 +498,15 @@ match_set_seq_token(Config) when is_list(Config) -> exit(P2, timeout), {error, "Test node hung"} end, - ?line ok = check_match_set_seq_token_log(Lbl, Log), + + %% Sort the log on Pid, as events from different processes + %% are not guaranteed to arrive in a certain order to the + %% tracer + SortedLog = lists:keysort(2, Log), + + ok = check_match_set_seq_token_log(Lbl, SortedLog), %% - ?line stop_node(Sandbox), - ?line test_server:timetrap_cancel(Timetrap), + stop_node(Sandbox), ok. %% OTP-4222 Match spec 'set_seq_token' corrupts heap @@ -520,13 +557,13 @@ do_match_set_seq_token(Label) -> check_match_set_seq_token_log( Label, - [{trace,C,call,{?MODULE,countdown,[B,Ref]}, {0,Label,0,C,0}}, + [{trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,2,B,1}}, + {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,4,B,3}}, + {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,6,B,5}}, + {trace,C,call,{?MODULE,countdown,[B,Ref]}, {0,Label,0,C,0}}, {trace,C,call,{?MODULE,countdown,[B,Ref,3]},{0,Label,0,C,0}}, - {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,2,B,1}}, {trace,C,call,{?MODULE,countdown,[B,Ref,2]},{0,Label,2,B,1}}, - {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,4,B,3}}, {trace,C,call,{?MODULE,countdown,[B,Ref,1]},{0,Label,4,B,3}}, - {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,6,B,5}}, {trace,C,call,{?MODULE,countdown,[B,Ref,0]},{0,Label,6,B,5}} ]) -> ok; @@ -561,14 +598,12 @@ bounce(Ref) -> -gc_seq_token(suite) -> - []; gc_seq_token(doc) -> ["Tests that a seq_trace token on a message in the inqueue ", "can be garbage collected."]; gc_seq_token(Config) when is_list(Config) -> - ?line Parent = self(), - ?line Timetrap = test_server:timetrap(test_server:seconds(20)), + Parent = self(), + %% OTP-4555 Seq trace token causes free mem read in gc %% %% This test crashes the emulator if the bug in question is present, @@ -576,13 +611,13 @@ gc_seq_token(Config) when is_list(Config) -> %% %% All the timeout stuff is here to get decent accuracy of the error %% return value, instead of just 'timeout'. - % - ?line {ok, Sandbox} = start_node(seq_trace_other, []), - ?line true = rpc:call(Sandbox, code, add_patha, + %% + {ok, Sandbox} = start_node(seq_trace_other, []), + true = rpc:call(Sandbox, code, add_patha, [filename:dirname(code:which(?MODULE))]), - ?line Label = 4711, + Label = 4711, %% Do the possibly crashing test - ?line P1 = + P1 = spawn( fun () -> Parent ! {self(), @@ -590,16 +625,16 @@ gc_seq_token(Config) when is_list(Config) -> ?MODULE, do_gc_seq_token, [Label])} end), %% Probe the node with a simple rpc request, to see if it is alive. - ?line P2 = + P2 = spawn( fun () -> receive after 4000 -> ok end, Parent ! {self(), rpc:call(Sandbox, erlang, abs, [-1])} end), %% If the test node hangs completely, this timer expires. - ?line R3 = erlang:start_timer(8000, self(), void), + R3 = erlang:start_timer(8000, self(), void), %% - ?line ok = + ok = receive {P1, Result} -> exit(P2, done), @@ -615,8 +650,7 @@ gc_seq_token(Config) when is_list(Config) -> {error, "Test node hung"} end, %% - ?line stop_node(Sandbox), - ?line test_server:timetrap_cancel(Timetrap), + stop_node(Sandbox), ok. do_gc_seq_token(Label) -> @@ -734,7 +768,7 @@ simple_tracer(Data, DN) -> {seq_trace,Label,Info,Ts} -> simple_tracer([{Label,Info,Ts}|Data], DN+1); {seq_trace,Label,Info} -> - simple_tracer([{Label,Info}|Data], DN+1); + simple_tracer([{Label,Info, no_timestamp}|Data], DN+1); {stop,N,From} when DN >= N -> From ! {tracerlog,lists:reverse(Data)} end. @@ -759,8 +793,55 @@ start_tracer() -> seq_trace:set_system_tracer(Pid), Pid. - - +set_token_flags([]) -> + ok; +set_token_flags([no_timestamp|Flags]) -> + seq_trace:set_token(timestamp, false), + seq_trace:set_token(monotonic_timestamp, false), + seq_trace:set_token(strict_monotonic_timestamp, false), + set_token_flags(Flags); +set_token_flags([Flag|Flags]) -> + seq_trace:set_token(Flag, true), + set_token_flags(Flags). + +check_ts(no_timestamp, Ts) -> + try + no_timestamp = Ts + catch + _ : _ -> + ct:fail({unexpected_timestamp, Ts}) + end, + ok; +check_ts(timestamp, Ts) -> + try + {Ms,S,Us} = Ts, + true = is_integer(Ms), + true = is_integer(S), + true = is_integer(Us) + catch + _ : _ -> + ct:fail({unexpected_timestamp, Ts}) + end, + ok; +check_ts(monotonic_timestamp, Ts) -> + try + true = is_integer(Ts) + catch + _ : _ -> + ct:fail({unexpected_timestamp, Ts}) + end, + ok; +check_ts(strict_monotonic_timestamp, Ts) -> + try + {MT, UMI} = Ts, + true = is_integer(MT), + true = is_integer(UMI) + catch + _ : _ -> + ct:fail({unexpected_timestamp, Ts}) + end, + ok. + start_node(Name, Param) -> test_server:start_node(Name, slave, [{args, Param}]). @@ -768,7 +849,7 @@ stop_node(Node) -> test_server:stop_node(Node). load_tracer(Config) -> - Path = ?config(data_dir, Config), + Path = proplists:get_value(data_dir, Config), ok = erl_ddll:load_driver(Path, echo_drv), open_port({spawn,echo_drv}, [eof,binary]). diff --git a/lib/kernel/test/standard_error_SUITE.erl b/lib/kernel/test/standard_error_SUITE.erl index e8917bbd47..1d9026dc58 100644 --- a/lib/kernel/test/standard_error_SUITE.erl +++ b/lib/kernel/test/standard_error_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2014. All Rights Reserved. +%% Copyright Ericsson AB 2014-2016. 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,13 +21,13 @@ -module(standard_error_SUITE). -export([all/0,suite/0]). --export([badarg/1,getopts/1]). +-export([badarg/1,getopts/1,output/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [badarg,getopts]. + [badarg,getopts,output]. badarg(Config) when is_list(Config) -> {'EXIT',{badarg,_}} = (catch io:put_chars(standard_error, [oops])), @@ -37,3 +37,30 @@ badarg(Config) when is_list(Config) -> getopts(Config) when is_list(Config) -> [{encoding,latin1}] = io:getopts(standard_error), ok. + +%% Test that writing a lot of output to standard_error does not cause the +%% processes handling it to terminate like this: +%% +%% =ERROR REPORT==== 9-Aug-2015::23:19:23 === +%% ** Generic server standard_error_sup terminating +%% ** Last message in was {'EXIT',<0.28.0>,eagain} +%% ** When Server state == {state,standard_error,undefined,<0.28.0>, +%% {local,standard_error_sup}} +%% ** Reason for termination == +%% ** eagain +%% +%% This problem, observed with Erlang 18.0.2, was fixed in fd_driver by +%% properly handling EAGAIN if it arises on file descriptor writes. +%% +output(Config) when is_list(Config) -> + Ref = monitor(process, standard_error_sup), + Chars = [ [["1234567890" || _ <- lists:seq(1,10)], $\s, + integer_to_list(L), $\r, $\n] || L <- lists:seq(1, 100) ], + ok = io:put_chars(standard_error, Chars), + receive + {'DOWN', Ref, process, _, _} -> + error(standard_error_noproc) + after + 500 -> + ok + end. diff --git a/lib/kernel/test/topApp.erl b/lib/kernel/test/topApp.erl index 597268a5a2..6ea957fdc1 100644 --- a/lib/kernel/test/topApp.erl +++ b/lib/kernel/test/topApp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/topApp2.erl b/lib/kernel/test/topApp2.erl index 69d5c047be..aeb024f7a7 100644 --- a/lib/kernel/test/topApp2.erl +++ b/lib/kernel/test/topApp2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/topApp3.erl b/lib/kernel/test/topApp3.erl index e892aadcd0..917da3dad4 100644 --- a/lib/kernel/test/topApp3.erl +++ b/lib/kernel/test/topApp3.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl index 9a93b9037f..40a016aed0 100644 --- a/lib/kernel/test/wrap_log_reader_SUITE.erl +++ b/lib/kernel/test/wrap_log_reader_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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,7 +20,7 @@ -module(wrap_log_reader_SUITE). -%-define(debug, true). +%%-define(debug, true). -ifdef(debug). -define(format(S, A), io:format(S, A)). @@ -29,9 +29,9 @@ -define(config(X,Y), foo). -define(t,test_server). -else. --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(format(S, A), ok). --define(privdir(Conf), ?config(priv_dir, Conf)). +-define(privdir(Conf), proplists:get_value(priv_dir, Conf)). -endif. -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -47,7 +47,9 @@ -export([init_per_testcase/2, end_per_testcase/2]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [no_file, {group, one}, {group, two}, {group, four}, @@ -71,75 +73,70 @@ end_per_group(_GroupName, Config) -> Config. -init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog=?t:timetrap(?t:seconds(60)), - [{watchdog, Dog} | Config]. +init_per_testcase(Func, Config) -> + Config. end_per_testcase(_Func, _Config) -> - Dog=?config(watchdog, _Config), - ?t:timetrap_cancel(Dog). + ok. -no_file(suite) -> []; -no_file(doc) -> ["No log file exists"]; +%% No log file exists. no_file(Conf) when is_list(Conf) -> - ?line code:add_path(?config(data_dir,Conf)), + code:add_path(proplists:get_value(data_dir,Conf)), Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), wlt ! {open, self(), File}, - ?line rec({error, {index_file_not_found, File}}, ?LINE), + rec({error, {index_file_not_found, File}}, ?LINE), wlt ! {open, self(), File, 1}, - ?line rec({error, {index_file_not_found, File}}, ?LINE), + rec({error, {index_file_not_found, File}}, ?LINE), wlt ! {open, self(), File, 4}, - ?line rec({error, {index_file_not_found, File}}, ?LINE), + rec({error, {index_file_not_found, File}}, ?LINE), stop(), delete_files(File), ok. -one_empty(suite) -> []; -one_empty(doc) -> ["One empty index file"]; +%% One empty index file. one_empty(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), - ?line open(sune, File, ?LINE), + open(sune, File, ?LINE), %% open - ?line do_chunk([{open,File}, eof], wlt, ?LINE), - ?line do_chunk([{open,File,1}, eof], wlt, ?LINE), + do_chunk([{open,File}, eof], wlt, ?LINE), + do_chunk([{open,File,1}, eof], wlt, ?LINE), wlt ! {open, self(), File, 2}, - ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), - ?line close(sune), + rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), + close(sune), %% closed - ?line do_chunk([{open,File}, eof], wlt, ?LINE), - ?line do_chunk([{open,File,1}, eof], wlt, ?LINE), + do_chunk([{open,File}, eof], wlt, ?LINE), + do_chunk([{open,File,1}, eof], wlt, ?LINE), wlt ! {open, self(), File, 2}, - ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), + rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), stop(), delete_files(File), ok. -one_filled(suite) -> []; -one_filled(doc) -> ["One filled index file"]; +%% One filled index file. one_filled(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), - ?line open(sune, File, ?LINE), - ?line log_terms(sune, ["first round, one", "first round, two"]), - ?line sync(sune), + open(sune, File, ?LINE), + log_terms(sune, ["first round, one", "first round, two"]), + sync(sune), %% open test_one(File), - ?line close(sune), + close(sune), %% closed test_one(File), @@ -148,34 +145,33 @@ one_filled(Conf) when is_list(Conf) -> ok. test_one(File) -> - ?line do_chunk([{open,File}, - {chunk, ["first round, one", "first round, two"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,1}, - {chunk, ["first round, one", "first round, two"]}, - eof], wlt, ?LINE), + do_chunk([{open,File}, + {chunk, ["first round, one", "first round, two"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,1}, + {chunk, ["first round, one", "first round, two"]}, + eof], wlt, ?LINE), wlt ! {open, self(), File, 2}, - ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), - ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, one"]}, - {chunk, 1, ["first round, two"]}, eof], wlt, ?LINE), + rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), + do_chunk([{open,File,1}, {chunk, 1, ["first round, one"]}, + {chunk, 1, ["first round, two"]}, eof], wlt, ?LINE), ok. -two_filled(suite) -> []; -two_filled(doc) -> ["Two filled index files"]; +%% Two filled index files. two_filled(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = list_to_atom(join(Dir, "sune.LOG")), delete_files(File), start(), - ?line open(sune, File, ?LINE), - ?line log_terms(sune, ["first round, 11", "first round, 12"]), - ?line log_terms(sune, ["first round, 21", "first round, 22"]), - ?line sync(sune), + open(sune, File, ?LINE), + log_terms(sune, ["first round, 11", "first round, 12"]), + log_terms(sune, ["first round, 21", "first round, 22"]), + sync(sune), %% open test_two(File), - ?line close(sune), + close(sune), %% closed test_two(File), @@ -184,37 +180,36 @@ two_filled(Conf) when is_list(Conf) -> ok. test_two(File) -> - ?line do_chunk([{open,File}, - {chunk, infinity, ["first round, 11", "first round, 12"]}, - {chunk, ["first round, 21", "first round, 22"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,1}, - {chunk, ["first round, 11", "first round, 12"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,2}, - {chunk, ["first round, 21", "first round, 22"]}, - eof], wlt, ?LINE), + do_chunk([{open,File}, + {chunk, infinity, ["first round, 11", "first round, 12"]}, + {chunk, ["first round, 21", "first round, 22"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,1}, + {chunk, ["first round, 11", "first round, 12"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,2}, + {chunk, ["first round, 21", "first round, 22"]}, + eof], wlt, ?LINE), wlt ! {open, self(), File, 3}, - ?line rec({error, {file_not_found, add_ext(File, 3)}}, ?LINE), - ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]}, - {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE), + rec({error, {file_not_found, add_ext(File, 3)}}, ?LINE), + do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]}, + {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE), ok. -four_filled(suite) -> []; -four_filled(doc) -> ["Four filled index files"]; +%% Four filled index files. four_filled(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), - ?line open(sune, File, ?LINE), - ?line init_files(0), - ?line sync(sune), + open(sune, File, ?LINE), + init_files(0), + sync(sune), %% open test_four(File), - ?line close(sune), + close(sune), %% closed test_four(File), @@ -223,42 +218,41 @@ four_filled(Conf) when is_list(Conf) -> ok. test_four(File) -> - ?line do_chunk([{open,File}, - {chunk, ["first round, 11", "first round, 12"]}, - {chunk, ["first round, 21", "first round, 22"]}, - {chunk, ["first round, 31", "first round, 32"]}, - {chunk, ["first round, 41", "first round, 42"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,1}, - {chunk, ["first round, 11", "first round, 12"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,4}, - {chunk, ["first round, 41", "first round, 42"]}, - eof], wlt, ?LINE), + do_chunk([{open,File}, + {chunk, ["first round, 11", "first round, 12"]}, + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,1}, + {chunk, ["first round, 11", "first round, 12"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,4}, + {chunk, ["first round, 41", "first round, 42"]}, + eof], wlt, ?LINE), wlt ! {open, self(), File, 5}, - ?line rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE), - ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]}, - {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE), - ?line do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]}, - {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE), + rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE), + do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]}, + {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE), + do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]}, + {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE), ok. -wrap_filled(suite) -> []; -wrap_filled(doc) -> ["First wrap, open, filled index file"]; +%% First wrap, open, filled index file. wrap_filled(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), - ?line open(sune, File, ?LINE), - ?line init_files(0), - ?line log_terms(sune, ["second round, 11", "second round, 12"]), - ?line sync(sune), + open(sune, File, ?LINE), + init_files(0), + log_terms(sune, ["second round, 11", "second round, 12"]), + sync(sune), %% open test_wrap(File), - ?line close(sune), + close(sune), %% closed test_wrap(File), @@ -267,103 +261,100 @@ wrap_filled(Conf) when is_list(Conf) -> ok. test_wrap(File) -> - ?line do_chunk([{open,File}, - {chunk, ["first round, 21", "first round, 22"]}, - {chunk, ["first round, 31", "first round, 32"]}, - {chunk, ["first round, 41", "first round, 42"]}, - {chunk, ["second round, 11", "second round, 12"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,1}, - {chunk, ["second round, 11", "second round, 12"]}, - eof], wlt, ?LINE), - ?line do_chunk([{open,File,2}, - {chunk, ["first round, 21", "first round, 22"]}, - eof], wlt, ?LINE), + do_chunk([{open,File}, + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, + {chunk, ["second round, 11", "second round, 12"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,1}, + {chunk, ["second round, 11", "second round, 12"]}, + eof], wlt, ?LINE), + do_chunk([{open,File,2}, + {chunk, ["first round, 21", "first round, 22"]}, + eof], wlt, ?LINE), wlt ! {open, self(), File, 5}, - ?line rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE), - ?line do_chunk([{open,File,1}, {chunk, 1, ["second round, 11"]}, - {chunk, 2, ["second round, 12"]}, eof], wlt, ?LINE), - ?line do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]}, - {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE), + rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE), + do_chunk([{open,File,1}, {chunk, 1, ["second round, 11"]}, + {chunk, 2, ["second round, 12"]}, eof], wlt, ?LINE), + do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]}, + {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE), ok. -wrapping(suite) -> []; -wrapping(doc) -> ["Wrapping at the same time as reading"]; +%% Wrapping at the same time as reading. wrapping(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), - ?line open(sune, File, ?LINE), - ?line init_files(1100), - ?line sync(sune), - ?line C1 = + open(sune, File, ?LINE), + init_files(1100), + sync(sune), + C1 = do_chunk([{open,File}, {chunk, 1, ["first round, 11"]}], wlt, ?LINE), - ?line log_terms(sune, ["second round, 11", "second round, 12"]), - ?line sync(sune), - ?line do_chunk([{chunk, 1, ["first round, 12"]}, - %% Here two bad bytes are found. - {chunk, ["first round, 21", "first round, 22"]}, - {chunk, ["first round, 31", "first round, 32"]}, - {chunk, ["first round, 41", "first round, 42"]}, eof], - wlt, ?LINE, C1), + log_terms(sune, ["second round, 11", "second round, 12"]), + sync(sune), + do_chunk([{chunk, 1, ["first round, 12"]}, + %% Here two bad bytes are found. + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, eof], + wlt, ?LINE, C1), start(), delete_files(File), - ?line open(sune, File, ?LINE), - ?line init_files(1100), - ?line sync(sune), - ?line C2 = + open(sune, File, ?LINE), + init_files(1100), + sync(sune), + C2 = do_chunk([{open,File}, {chunk, 1, ["first round, 11"]}], wlt, ?LINE), - ?line log_terms(sune, ["second round, 11", "second round, 12"]), - ?line close(sune), - ?line do_chunk([{chunk, 1, ["first round, 12"]}, - %% Here two bad bytes are found. - {chunk, ["first round, 21", "first round, 22"]}, - {chunk, ["first round, 31", "first round, 32"]}, - {chunk, ["first round, 41", "first round, 42"]}, eof], - wlt, ?LINE, C2), + log_terms(sune, ["second round, 11", "second round, 12"]), + close(sune), + do_chunk([{chunk, 1, ["first round, 12"]}, + %% Here two bad bytes are found. + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, eof], + wlt, ?LINE, C2), start(), delete_files(File), - ?line open(sune, File, ?LINE), - ?line init_files(1100), - ?line sync(sune), - ?line C3 = do_chunk([{open,File}], wlt, ?LINE), - ?line log_terms(sune, ["second round, 11"]), - ?line sync(sune), - ?line do_chunk([{chunk, 1, ["second round, 11"]}, - {chunk, 1, ["first round, 21"]}, - {chunk, 1, ["first round, 22"]}, - {chunk, ["first round, 31", "first round, 32"]}, - {chunk, ["first round, 41", "first round, 42"]}, eof], - wlt, ?LINE, C3), + open(sune, File, ?LINE), + init_files(1100), + sync(sune), + C3 = do_chunk([{open,File}], wlt, ?LINE), + log_terms(sune, ["second round, 11"]), + sync(sune), + do_chunk([{chunk, 1, ["second round, 11"]}, + {chunk, 1, ["first round, 21"]}, + {chunk, 1, ["first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, eof], + wlt, ?LINE, C3), stop(), delete_files(File), ok. -external(suite) -> []; -external(doc) -> ["External format"]; +%% External format. external(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), delete_files(File), start(), - ?line open_ext(sune, File, ?FILE), - ?line init_files_ext(0), - ?line close(sune), + open_ext(sune, File, ?FILE), + init_files_ext(0), + close(sune), P0 = pps(), wlt ! {open, self(), File}, - ?line rec({error, {not_a_log_file, add_ext(File, 1)}}, ?LINE), - ?line true = (P0 == pps()), + rec({error, {not_a_log_file, add_ext(File, 1)}}, ?LINE), + true = (P0 == pps()), stop(), delete_files(File), ok. -error(suite) -> []; -error(doc) -> ["Error situations"]; +%% Error situations. error(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), File = join(Dir, "sune.LOG"), @@ -372,69 +363,69 @@ error(Conf) when is_list(Conf) -> P0 = pps(), wlt ! {open, self(), File, 1}, - ?line rec({error, {index_file_not_found, File}}, ?LINE), + rec({error, {index_file_not_found, File}}, ?LINE), wlt ! {open, self(), File}, - ?line rec({error, {index_file_not_found, File}}, ?LINE), - ?line true = (P0 == pps()), + rec({error, {index_file_not_found, File}}, ?LINE), + true = (P0 == pps()), - ?line open(sune, File, ?LINE), - ?line close(sune), + open(sune, File, ?LINE), + close(sune), P1 = pps(), - ?line First = add_ext(File, 1), - ?line ok = file:delete(First), + First = add_ext(File, 1), + ok = file:delete(First), wlt ! {open, self(), File}, - ?line rec({error, {not_a_log_file, First}}, ?LINE), - ?line true = (P1 == pps()), + rec({error, {not_a_log_file, First}}, ?LINE), + true = (P1 == pps()), delete_files(File), - ?line open(sune, File, ?LINE), - ?line init_files(0), - ?line close(sune), + open(sune, File, ?LINE), + init_files(0), + close(sune), P2 = pps(), - ?line C = do_chunk([{open,File}, - {chunk, ["first round, 11", "first round, 12"]}], - wlt, ?LINE), - ?line Second = add_ext(File, 2), - ?line ok = file:delete(Second), + C = do_chunk([{open,File}, + {chunk, ["first round, 11", "first round, 12"]}], + wlt, ?LINE), + Second = add_ext(File, 2), + ok = file:delete(Second), wlt ! {chunk, self(), C}, - ?line rec({error, {file_error, Second, {error, enoent}}}, ?LINE), - ?line ok = file:write_file(Second, <<17:(3*8)>>), % three bytes + rec({error, {file_error, Second, {error, enoent}}}, ?LINE), + ok = file:write_file(Second, <<17:(3*8)>>), % three bytes wlt ! {chunk, self(), C}, - ?line rec({error, {not_a_log_file, Second}}, ?LINE), - ?line do_chunk([close], wlt, ?LINE, C), - ?line true = (P2 == pps()), + rec({error, {not_a_log_file, Second}}, ?LINE), + do_chunk([close], wlt, ?LINE, C), + true = (P2 == pps()), delete_files(File), - ?line open(sune, File, ?LINE), - ?line init_files(0), - ?line close(sune), + open(sune, File, ?LINE), + init_files(0), + close(sune), P3 = pps(), timer:sleep(1100), Now = calendar:local_time(), - ?line ok = file:change_time(First, Now), - ?line C2 = do_chunk([{open,File}, - {chunk, ["first round, 11", "first round, 12"]}], - wlt, ?LINE), + ok = file:change_time(First, Now), + C2 = do_chunk([{open,File}, + {chunk, ["first round, 11", "first round, 12"]}], + wlt, ?LINE), wlt ! {chunk, self(), C2}, - ?line rec({error,{is_wrapped,First}}, ?LINE), - ?line do_chunk([close], wlt, ?LINE, C2), + rec({error,{is_wrapped,First}}, ?LINE), + do_chunk([close], wlt, ?LINE, C2), IndexFile = add_ext(File, idx), - ?line ok = file:write_file(IndexFile, <<17:(3*8)>>), + ok = file:write_file(IndexFile, <<17:(3*8)>>), wlt ! {open, self(), File, 1}, - ?line rec({error, {index_file_not_found, File}}, ?LINE), - ?line true = (P3 == pps()), + rec({error, {index_file_not_found, File}}, ?LINE), + true = (P3 == pps()), stop(), delete_files(File), ok. start() -> - ?line ok = wrap_log_test:stop(), + ok = wrap_log_test:stop(), dl_wait(), - ?line ok = wrap_log_test:init(). + ok = wrap_log_test:init(). stop() -> - ?line ok = wrap_log_test:stop(), + ok = wrap_log_test:stop(), dl_wait(). %% Give disk logs opened by 'logger' and 'wlt' time to close after @@ -458,24 +449,24 @@ delete_files(File) -> ok. init_files(Delay) -> - ?line log_terms(sune, ["first round, 11", "first round, 12"]), + log_terms(sune, ["first round, 11", "first round, 12"]), timer:sleep(Delay), - ?line log_terms(sune, ["first round, 21", "first round, 22"]), + log_terms(sune, ["first round, 21", "first round, 22"]), timer:sleep(Delay), - ?line log_terms(sune, ["first round, 31", "first round, 32"]), + log_terms(sune, ["first round, 31", "first round, 32"]), timer:sleep(Delay), - ?line log_terms(sune, ["first round, 41", "first round, 42"]), + log_terms(sune, ["first round, 41", "first round, 42"]), timer:sleep(Delay), ok. init_files_ext(Delay) -> - ?line blog_terms(sune, ["first round, 11", "first round, 12"]), + blog_terms(sune, ["first round, 11", "first round, 12"]), timer:sleep(Delay), - ?line blog_terms(sune, ["first round, 21", "first round, 22"]), + blog_terms(sune, ["first round, 21", "first round, 22"]), timer:sleep(Delay), - ?line blog_terms(sune, ["first round, 31", "first round, 32"]), + blog_terms(sune, ["first round, 31", "first round, 32"]), timer:sleep(Delay), - ?line blog_terms(sune, ["first round, 41", "first round, 42"]), + blog_terms(sune, ["first round, 41", "first round, 42"]), timer:sleep(Delay), ok. @@ -487,27 +478,27 @@ do_chunk(Commands, Server, Where) -> do_chunk([{open, File, One} | Cs], S, W, _C) -> S ! {open, self(), File, One}, - ?line NC = rec1(ok, {W,?LINE}), + NC = rec1(ok, {W,?LINE}), do_chunk(Cs, S, W, NC); do_chunk([{open, File} | Cs], S, W, _C) -> S ! {open, self(), File}, - ?line NC = rec1(ok, {W,?LINE}), + NC = rec1(ok, {W,?LINE}), do_chunk(Cs, S, W, NC); do_chunk([{chunk, Terms} | Cs], S, W, C) -> S ! {chunk, self(), C}, - ?line NC = rec2(Terms, {W,?LINE}), + NC = rec2(Terms, {W,?LINE}), do_chunk(Cs, S, W, NC); do_chunk([{chunk, N, Terms} | Cs], S, W, C) -> S ! {chunk, self(), C, N}, - ?line NC = rec2(Terms, {W,?LINE}), + NC = rec2(Terms, {W,?LINE}), do_chunk(Cs, S, W, NC); do_chunk([eof], S, W, C) -> S ! {chunk, self(), C}, - ?line C1 = rec2(eof, {W,?LINE}), + C1 = rec2(eof, {W,?LINE}), do_chunk([close], S, W, C1); do_chunk([close], S, W, C) -> S ! {close, self(), C}, - ?line rec(ok, {W,?LINE}); + rec(ok, {W,?LINE}); do_chunk([], _S, _W, C) -> C. @@ -542,24 +533,24 @@ blog_terms(File, Terms) -> rec1(M, Where) -> receive {M, C} -> C; - Else -> test_server:fail({error, {Where, Else}}) - after 1000 -> test_server:fail({error, {Where, time_out}}) + Else -> ct:fail({error, {Where, Else}}) + after 1000 -> ct:fail({error, {Where, time_out}}) end. rec2(M, Where) -> receive {C, M} -> C; - Else -> test_server:fail({error, {Where, Else}}) - after 1000 -> test_server:fail({error, {Where, time_out}}) + Else -> ct:fail({error, {Where, Else}}) + after 1000 -> ct:fail({error, {Where, time_out}}) end. rec(M, Where) -> receive M -> ok; - Else -> ?t:fail({error, {Where, Else}}) - after 5000 -> ?t:fail({error, {Where, time_out}}) + Else -> ct:fail({error, {Where, Else}}) + after 5000 -> ct:fail({error, {Where, time_out}}) end. - + pps() -> {erlang:ports(), lists:filter(fun erlang:is_process_alive/1, processes())}. diff --git a/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl b/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl index 1cd1a4b0a4..38449b6bb3 100644 --- a/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl +++ b/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. 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/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index 6aaa024a82..26602bdcda 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2016. 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,60 +20,57 @@ -module(zlib_SUITE). --include_lib("test_server/include/test_server.hrl"). - --compile(export_all). - --define(error(Format,Args), - put(test_server_loc,{?MODULE,?LINE}), - error(Format,Args,?MODULE,?LINE)). - -%% Learn erts team how to really write tests ;-) --define(m(ExpectedRes,Expr), - fun() -> - ACtual1 = (catch (Expr)), - try case ACtual1 of - ExpectedRes -> ACtual1 - end - catch - error:{case_clause,ACtuAl} -> - ?error("Not Matching Actual result was:~n ~p ~n", - [ACtuAl]), - ACtuAl - end - end()). - --define(BARG, {'EXIT',{badarg,[{zlib,_,_,_}|_]}}). --define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_,_}|_]}}). - -init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(60)), - [{watchdog, Dog}|Config]. -end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog). - -error(Format, Args, File, Line) -> - io:format("~p:~p: ERROR: " ++ Format, [File,Line|Args]), - group_leader() ! {failed, File, Line}. - -%% Hopefully I don't need this to get it to work with the testserver.. -%% Fail = #'REASON'{file = filename:basename(File), -%% line = Line, -%% desc = Args}, -%% case global:whereis_name(mnesia_test_case_sup) of -%% undefined -> -%% ignore; -%% Pid -> -%% Pid ! Fail -%% %% global:send(mnesia_test_case_sup, Fail), -%% end, -%% log("<>ERROR<>~n" ++ Format, Args, File, Line). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-export([suite/0, all/0, groups/0]). + +%% API group +-export([api_open_close/1]). +-export([api_deflateInit/1, api_deflateSetDictionary/1, api_deflateReset/1, + api_deflateParams/1, api_deflate/1, api_deflateEnd/1]). +-export([api_inflateInit/1, api_inflateReset/1, api_inflate2/1, api_inflate3/1, + api_inflateChunk/1, api_safeInflate/1, api_inflateEnd/1]). +-export([api_inflateSetDictionary/1, api_inflateGetDictionary/1]). +-export([api_crc32/1, api_adler32/1]). +-export([api_un_compress/1, api_un_zip/1, api_g_un_zip/1]). + +%% Examples group +-export([intro/1]). + +%% Usage group +-export([zip_usage/1, gz_usage/1, gz_usage2/1, compress_usage/1, + dictionary_usage/1, large_deflate/1, crc/1, adler/1, + only_allow_owner/1, sub_heap_binaries/1]). + +%% Bench group +-export([inflate_bench_zeroed/1, inflate_bench_rand/1, + deflate_bench_zeroed/1, deflate_bench_rand/1, + chunk_bench_zeroed/1, chunk_bench_rand/1]). + +%% Others +-export([smp/1, otp_9981/1, otp_7359/1]). + +-define(m(Guard, Expression), + fun() -> + Actual = (catch (Expression)), + case Actual of + Guard -> Actual; + _Other -> + ct:fail("Failed to match ~p, actual result was ~p", + [??Guard, Actual]) + end + end()). + +-define(EXIT(Reason), {'EXIT',{Reason,[{_,_,_,_}|_]}}). + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> - [{group, api}, {group, examples}, {group, func}, smp, + [{group, api}, {group, examples}, {group, func}, + {group, bench}, smp, otp_9981, otp_7359]. @@ -82,149 +79,184 @@ groups() -> [api_open_close, api_deflateInit, api_deflateSetDictionary, api_deflateReset, api_deflateParams, api_deflate, api_deflateEnd, - api_inflateInit, api_inflateSetDictionary, - api_inflateSync, api_inflateReset, api_inflate, api_inflateChunk, - api_inflateEnd, api_setBufsz, api_getBufsz, api_crc32, - api_adler32, api_getQSize, api_un_compress, api_un_zip, + api_inflateInit, api_inflateSetDictionary, api_inflateGetDictionary, + api_inflateReset, api_inflate2, api_inflate3, api_inflateChunk, + api_safeInflate, api_inflateEnd, api_crc32, + api_adler32, api_un_compress, api_un_zip, api_g_un_zip]}, {examples, [], [intro]}, {func, [], [zip_usage, gz_usage, gz_usage2, compress_usage, - dictionary_usage, large_deflate, crc, adler]}]. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - - -api_open_close(doc) -> "Test open/0 and close/1"; -api_open_close(suite) -> []; + dictionary_usage, large_deflate, crc, adler, + only_allow_owner, sub_heap_binaries]}, + {bench, + [inflate_bench_zeroed, inflate_bench_rand, + deflate_bench_zeroed, deflate_bench_rand, + chunk_bench_zeroed, chunk_bench_rand]}]. + +%% Test open/0 and close/1. api_open_close(Config) when is_list(Config) -> - ?line Fd1 = zlib:open(), - ?line Fd2 = zlib:open(), + Fd1 = zlib:open(), + Fd2 = zlib:open(), ?m(false,Fd1 == Fd2), ?m(ok,zlib:close(Fd1)), - ?m(?BARG, zlib:close(Fd1)), + ?m(?EXIT(not_initialized), zlib:close(Fd1)), ?m(ok,zlib:close(Fd2)), - + %% Make sure that we don't get any EXIT messages if trap_exit is enabled. - ?line process_flag(trap_exit, true), - ?line Fd3 = zlib:open(), + process_flag(trap_exit, true), + Fd3 = zlib:open(), ?m(ok,zlib:close(Fd3)), receive - Any -> ?line ?t:fail({unexpected_message,Any}) + Any -> ct:fail({unexpected_message,Any}) after 10 -> ok end. -api_deflateInit(doc) -> "Test deflateInit/2 and /6"; -api_deflateInit(suite) -> []; +%% Test deflateInit/2 and /6. api_deflateInit(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), - ?m(?BARG, zlib:deflateInit(gurka, none)), - ?m(?BARG, zlib:deflateInit(gurka, gurka)), - ?m(?BARG, zlib:deflateInit(Z1, gurka)), + Z1 = zlib:open(), + + ?m(?EXIT(badarg), zlib:deflateInit(gurka, none)), + + ?m(?EXIT(bad_compression_level), zlib:deflateInit(gurka, gurka)), + ?m(?EXIT(bad_compression_level), zlib:deflateInit(Z1, gurka)), Levels = [none, default, best_speed, best_compression] ++ lists:seq(0,9), lists:foreach(fun(Level) -> - ?line Z = zlib:open(), + Z = zlib:open(), ?m(ok, zlib:deflateInit(Z, Level)), ?m(ok,zlib:close(Z)) end, Levels), %% /6 - ?m(?BARG, zlib:deflateInit(Z1,gurka,deflated,-15,8,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,undefined,-15,8,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,48,8,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-20,8,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-7,8,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,7,8,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,0,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,10,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,0)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,undefined)), - + ?m(?EXIT(bad_compression_level), + zlib:deflateInit(Z1,gurka,deflated,-15,8,default)), + + ?m(?EXIT(bad_compression_method), + zlib:deflateInit(Z1,default,undefined,-15,8,default)), + + ?m(?EXIT(bad_compression_strategy), + zlib:deflateInit(Z1,default,deflated,-15,8,0)), + ?m(?EXIT(bad_compression_strategy), + zlib:deflateInit(Z1,default,deflated,-15,8,undefined)), + + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,48,8,default)), + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,-20,8,default)), + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,-7,8,default)), + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,7,8,default)), + + ?m(?EXIT(bad_memlevel), + zlib:deflateInit(Z1,default,deflated,-15,0,default)), + ?m(?EXIT(bad_memlevel), + zlib:deflateInit(Z1,default,deflated,-15,10,default)), + lists:foreach(fun(Level) -> - ?line Z = zlib:open(), + Z = zlib:open(), ?m(ok, zlib:deflateInit(Z, Level, deflated, -15, 8, default)), ?m(ok,zlib:close(Z)) end, Levels), - + lists:foreach(fun(Wbits) -> - ?line Z11 = zlib:open(), + Z11 = zlib:open(), ?m(ok, zlib:deflateInit(Z11,best_compression,deflated, Wbits,8,default)), - ?line Z12 = zlib:open(), + Z12 = zlib:open(), ?m(ok, zlib:deflateInit(Z12,default,deflated,-Wbits,8,default)), ?m(ok,zlib:close(Z11)), ?m(ok,zlib:close(Z12)) - end, lists:seq(8, 15)), - + end, lists:seq(9, 15)), + lists:foreach(fun(MemLevel) -> - ?line Z = zlib:open(), + Z = zlib:open(), ?m(ok, zlib:deflateInit(Z,default,deflated,-15, MemLevel,default)), ?m(ok,zlib:close(Z)) end, lists:seq(1,8)), - + Strategies = [filtered,huffman_only,rle,default], lists:foreach(fun(Strategy) -> - ?line Z = zlib:open(), + Z = zlib:open(), ?m(ok, zlib:deflateInit(Z,best_speed,deflated,-15,8,Strategy)), ?m(ok,zlib:close(Z)) end, Strategies), ?m(ok, zlib:deflateInit(Z1,default,deflated,-15,8,default)), - ?m({'EXIT',_}, zlib:deflateInit(Z1,none,deflated,-15,8,default)), %% ?? + + %% Let it crash for any reason; we don't care about the order in which the + %% parameters are checked. + ?m(?EXIT(_), zlib:deflateInit(Z1,none,deflated,-15,8,default)), + ?m(ok, zlib:close(Z1)). -api_deflateSetDictionary(doc) -> "Test deflateSetDictionary"; -api_deflateSetDictionary(suite) -> []; +%% Test deflateSetDictionary. api_deflateSetDictionary(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), ?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, <<1,1,2,3,4,5,1>>)), ?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, [1,1,2,3,4,5,1])), - ?m(?BARG, zlib:deflateSetDictionary(Z1, gurka)), - ?m(?BARG, zlib:deflateSetDictionary(Z1, 128)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), - ?m({'EXIT',{stream_error,_}},zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)), + ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, gurka)), + ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, 128)), + ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), + ?m(?EXIT(stream_error), zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)), ?m(ok, zlib:close(Z1)). -api_deflateReset(doc) -> "Test deflateReset"; -api_deflateReset(suite) -> []; +%% Test deflateReset. api_deflateReset(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), + ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), ?m(ok, zlib:deflateReset(Z1)), ?m(ok, zlib:deflateReset(Z1)), %% FIXME how do I make this go wrong?? ?m(ok, zlib:close(Z1)). -api_deflateParams(doc) -> "Test deflateParams"; -api_deflateParams(suite) -> []; +%% Test deflateParams. api_deflateParams(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Levels = [none, default, best_speed, best_compression] ++ lists:seq(0, 9), + Strategies = [filtered, huffman_only, rle, default], + + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), - ?m(ok, zlib:deflateParams(Z1, best_compression, huffman_only)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)), - ?m(ok, zlib:close(Z1)). -api_deflate(doc) -> "Test deflate"; -api_deflate(suite) -> []; + ApiTest = + fun(Level, Strategy) -> + ?m(ok, zlib:deflateParams(Z1, Level, Strategy)), + ?m(ok, zlib:deflateReset(Z1)) + end, + + [ ApiTest(Level, Strategy) || Level <- Levels, Strategy <- Strategies ], + + ?m(ok, zlib:close(Z1)), + + FlushTest = + fun FlushTest(Size, Level, Strategy) -> + Z = zlib:open(), + ok = zlib:deflateInit(Z, default), + Data = gen_determ_rand_bytes(Size), + case zlib:deflate(Z, Data, none) of + [<<120, 156>>] -> + %% All data is present in the internal zlib state, and will + %% be flushed on deflateParams. + + ok = zlib:deflateParams(Z, Level, Strategy), + Compressed = [<<120, 156>>, zlib:deflate(Z, <<>>, finish)], + Data = zlib:uncompress(Compressed), + zlib:close(Z), + + FlushTest(Size + (1 bsl 10), Level, Strategy); + _Other -> + ok + end + end, + + [ FlushTest(1, Level, Strategy) || Level <- Levels, Strategy <- Strategies ], + + ok. + +%% Test deflate. api_deflate(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), ?m([B] when is_binary(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, finish)), ?m(ok, zlib:deflateReset(Z1)), @@ -235,324 +267,435 @@ api_deflate(Config) when is_list(Config) -> ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)), ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, full)), ?m(B when is_list(B), zlib:deflate(Z1, <<>>, finish)), - - ?m(?BARG, zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)), - ?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)), - ?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)), + + ?m(?EXIT(badarg), zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)), + + ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)), + ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)), + %% Causes problems ERROR REPORT - ?m(?BARG, zlib:deflate(Z1, [asdj,asd], none)), - + ?m(?EXIT(badarg), zlib:deflate(Z1, [asdj,asd], none)), + ?m(ok, zlib:close(Z1)). -api_deflateEnd(doc) -> "Test deflateEnd"; -api_deflateEnd(suite) -> []; +%% Test deflateEnd. api_deflateEnd(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), ?m(ok, zlib:deflateEnd(Z1)), - ?m({'EXIT', {einval,_}}, zlib:deflateEnd(Z1)), %% ?? - ?m(?BARG, zlib:deflateEnd(gurka)), + ?m(?EXIT(not_initialized), zlib:deflateEnd(Z1)), + ?m(?EXIT(badarg), zlib:deflateEnd(gurka)), ?m(ok, zlib:deflateInit(Z1, default)), ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)), - ?m({'EXIT', {data_error,_}}, zlib:deflateEnd(Z1)), + ?m(?EXIT(data_error), zlib:deflateEnd(Z1)), ?m(ok, zlib:deflateInit(Z1, default)), ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)), ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>, finish)), ?m(ok, zlib:deflateEnd(Z1)), - + ?m(ok, zlib:close(Z1)). -api_inflateInit(doc) -> "Test inflateInit /1 and /2"; -api_inflateInit(suite) -> []; +%% Test inflateInit /1 and /2. api_inflateInit(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), - ?m(?BARG, zlib:inflateInit(gurka)), + Z1 = zlib:open(), + ?m(?EXIT(badarg), zlib:inflateInit(gurka)), ?m(ok, zlib:inflateInit(Z1)), - ?m({'EXIT',{einval,_}}, zlib:inflateInit(Z1, 15)), %% ?? + ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 15)), lists:foreach(fun(Wbits) -> - ?line Z11 = zlib:open(), + Z11 = zlib:open(), ?m(ok, zlib:inflateInit(Z11,Wbits)), - ?line Z12 = zlib:open(), + Z12 = zlib:open(), ?m(ok, zlib:inflateInit(Z12,-Wbits)), ?m(ok,zlib:close(Z11)), ?m(ok,zlib:close(Z12)) end, lists:seq(8,15)), - ?m(?BARG, zlib:inflateInit(gurka, -15)), - ?m(?BARG, zlib:inflateInit(Z1, 7)), - ?m(?BARG, zlib:inflateInit(Z1, -7)), - ?m(?BARG, zlib:inflateInit(Z1, 48)), - ?m(?BARG, zlib:inflateInit(Z1, -16)), + ?m(?EXIT(badarg), zlib:inflateInit(gurka, -15)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 7)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -7)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 48)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -16)), ?m(ok, zlib:close(Z1)). -api_inflateSetDictionary(doc) -> "Test inflateSetDictionary"; -api_inflateSetDictionary(suite) -> []; +%% Test inflateSetDictionary. api_inflateSetDictionary(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)), - ?m(?BARG, zlib:inflateSetDictionary(Z1,102)), - ?m(?BARG, zlib:inflateSetDictionary(Z1,gurka)), + ?m(?EXIT(badarg), zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)), + ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,102)), + ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,gurka)), Dict = <<1,1,1,1,1>>, - ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z1,Dict)), + ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z1,Dict)), ?m(ok, zlib:close(Z1)). -api_inflateSync(doc) -> "Test inflateSync"; -api_inflateSync(suite) -> []; -api_inflateSync(Config) when is_list(Config) -> - {skip,"inflateSync/1 sucks"}. -%% ?line Z1 = zlib:open(), -%% ?m(ok, zlib:deflateInit(Z1)), -%% ?line B1list0 = zlib:deflate(Z1, "gurkan gurra ger galna tunnor", full), -%% ?line B2 = zlib:deflate(Z1, "grodan boll", finish), -%% io:format("~p\n", [B1list0]), -%% io:format("~p\n", [B2]), -%% ?m(ok, zlib:deflateEnd(Z1)), -%% ?line B1 = clobber(14, list_to_binary(B1list0)), -%% ?line Compressed = list_to_binary([B1,B2]), -%% ?line io:format("~p\n", [Compressed]), - -%% ?m(ok, zlib:inflateInit(Z1)), -%% ?m(?BARG, zlib:inflateSync(gurka)), -%% ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, Compressed)), -%% ?m(ok, zlib:inflateSync(Z1)), -%% ?line Ubs = zlib:inflate(Z1, []), -%% ?line <<"grodan boll">> = list_to_binary(Ubs), -%% ?m(ok, zlib:close(Z1)). - -clobber(N, Bin) when is_binary(Bin) -> - T = list_to_tuple(binary_to_list(Bin)), - Byte = case element(N, T) of - 255 -> 254; - B -> B+1 - end, - list_to_binary(tuple_to_list(setelement(N, T, Byte))). +%% Test inflateGetDictionary. +api_inflateGetDictionary(Config) when is_list(Config) -> + Z1 = zlib:open(), + zlib:inflateInit(Z1), + IsOperationSupported = + case catch zlib:inflateGetDictionary(Z1) of + ?EXIT(not_supported) -> false; + _ -> true + end, + zlib:close(Z1), + api_inflateGetDictionary_if_supported(IsOperationSupported). + +api_inflateGetDictionary_if_supported(false) -> + {skip, "inflateGetDictionary/1 unsupported in current setup"}; +api_inflateGetDictionary_if_supported(true) -> + % Compress payload using custom dictionary + Z1 = zlib:open(), + ?m(ok, zlib:deflateInit(Z1)), + Dict = <<"foobar barfoo foo bar far boo">>, + Checksum = zlib:deflateSetDictionary(Z1, Dict), + Payload = <<"foobarbarbar">>, + Compressed = zlib:deflate(Z1, Payload, finish), + ?m(ok, zlib:close(Z1)), + + % Decompress and test dictionary extraction with inflate/2 + Z2 = zlib:open(), + ?m(ok, zlib:inflateInit(Z2)), + ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z2))), + ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z2, Dict)), + ?m(?EXIT({need_dictionary,Checksum}), zlib:inflate(Z2, Compressed)), + ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), + ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z2))), + Payload = iolist_to_binary(zlib:inflate(Z2, [])), + ?m(ok, zlib:close(Z2)), + ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z2, Dict)), + + %% ... And do the same for inflate/3 + Z3 = zlib:open(), + ?m(ok, zlib:inflateInit(Z3)), + ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z3))), + ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z3, Dict)), + + {need_dictionary, Checksum, _Output = []} = + zlib:inflate(Z3, Compressed, [{exception_on_need_dict, false}]), + + ?m(ok, zlib:inflateSetDictionary(Z3, Dict)), + ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z3))), + + Payload = iolist_to_binary( + zlib:inflate(Z3, [], [{exception_on_need_dict, false}])), -api_inflateReset(doc) -> "Test inflateReset"; -api_inflateReset(suite) -> []; + ?m(ok, zlib:close(Z3)), + ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z3, Dict)), + + ok. + +%% Test inflateReset. api_inflateReset(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateReset(gurka)), + ?m(?EXIT(badarg), zlib:inflateReset(gurka)), ?m(ok, zlib:inflateReset(Z1)), ?m(ok, zlib:close(Z1)). -api_inflate(doc) -> "Test inflate"; -api_inflate(suite) -> []; -api_inflate(Config) when is_list(Config) -> +%% Test inflate/2 +api_inflate2(Config) when is_list(Config) -> Data = [<<1,2,2,3,3,3,4,4,4,4>>], - ?line Compressed = zlib:compress(Data), - ?line Z1 = zlib:open(), + Compressed = zlib:compress(Data), + Z1 = zlib:open(), ?m(ok, zlib:inflateInit(Z1)), ?m([], zlib:inflate(Z1, <<>>)), ?m(Data, zlib:inflate(Z1, Compressed)), ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), ?m(Data, zlib:inflate(Z1, Compressed)), - ?m(?BARG, zlib:inflate(gurka, Compressed)), - ?m(?BARG, zlib:inflate(Z1, 4384)), - ?m(?BARG, zlib:inflate(Z1, [atom_list])), + ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed)), + ?m(?EXIT(badarg), zlib:inflate(Z1, 4384)), + ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list])), + ?m(ok, zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>)), + ?m(ok, zlib:close(Z1)). + +%% Test inflate/3; same as inflate/2 but with the default options inverted. +api_inflate3(Config) when is_list(Config) -> + Data = [<<1,2,2,3,3,3,4,4,4,4>>], + Options = [{exception_on_need_dict, false}], + Compressed = zlib:compress(Data), + Z1 = zlib:open(), + ?m(ok, zlib:inflateInit(Z1)), + ?m([], zlib:inflate(Z1, <<>>, Options)), + ?m(Data, zlib:inflate(Z1, Compressed)), + ?m(ok, zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(Data, zlib:inflate(Z1, Compressed, Options)), + ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed, Options)), + ?m(?EXIT(badarg), zlib:inflate(Z1, 4384, Options)), + ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list], Options)), ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), - ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, <<2,1,2,1,2>>)), + ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>, Options)), ?m(ok, zlib:close(Z1)). -api_inflateChunk(doc) -> "Test inflateChunk"; -api_inflateChunk(suite) -> []; +%% Test inflateChunk. api_inflateChunk(Config) when is_list(Config) -> ChunkSize = 1024, Data = << <<(I rem 150)>> || I <- lists:seq(1, 3 * ChunkSize) >>, Part1 = binary:part(Data, 0, ChunkSize), Part2 = binary:part(Data, ChunkSize, ChunkSize), Part3 = binary:part(Data, ChunkSize * 2, ChunkSize), - ?line Compressed = zlib:compress(Data), - ?line Z1 = zlib:open(), - ?line zlib:setBufSize(Z1, ChunkSize), + + Compressed = zlib:compress(Data), + Z1 = zlib:open(), + + zlib:setBufSize(Z1, ChunkSize), + ?m(ok, zlib:inflateInit(Z1)), - ?m([], zlib:inflateChunk(Z1, <<>>)), - ?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)), - ?m({more, Part2}, zlib:inflateChunk(Z1)), - ?m(Part3, zlib:inflateChunk(Z1)), - ?m(ok, zlib:inflateEnd(Z1)), + 0 = iolist_size(zlib:inflateChunk(Z1, <<>>)), + + {more, Part1AsIOList} = zlib:inflateChunk(Z1, Compressed), + {more, Part2AsIOList} = zlib:inflateChunk(Z1), + {more, Part3AsIOList} = zlib:inflateChunk(Z1), + + [] = zlib:inflateChunk(Z1), + [] = zlib:inflateChunk(Z1), + [] = zlib:inflateChunk(Z1), + + ?m(Part1, iolist_to_binary(Part1AsIOList)), + ?m(Part2, iolist_to_binary(Part2AsIOList)), + ?m(Part3, iolist_to_binary(Part3AsIOList)), + + ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), - ?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)), + + ?m({more, Part1AsIOList}, zlib:inflateChunk(Z1, Compressed)), ?m(ok, zlib:inflateReset(Z1)), - ?line zlib:setBufSize(Z1, size(Data)), - ?m(Data, zlib:inflateChunk(Z1, Compressed)), - ?m(ok, zlib:inflateEnd(Z1)), + zlib:setBufSize(Z1, byte_size(Data) + 1), + + DataAsIOList = zlib:inflateChunk(Z1, Compressed), + ?m(Data, iolist_to_binary(DataAsIOList)), + ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateChunk(gurka, Compressed)), - ?m(?BARG, zlib:inflateChunk(Z1, 4384)), - ?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)), + + ?m(?EXIT(badarg), zlib:inflateChunk(gurka, Compressed)), + ?m(?EXIT(badarg), zlib:inflateChunk(Z1, 4384)), + + ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), + ?m(ok, zlib:close(Z1)). -api_inflateEnd(doc) -> "Test inflateEnd"; -api_inflateEnd(suite) -> []; -api_inflateEnd(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), - ?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)), - ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateEnd(gurka)), - ?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)), - ?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)), +%% Test safeInflate as a mirror of inflateChunk, but ignore the stuff about +%% exact chunk sizes. +api_safeInflate(Config) when is_list(Config) -> + Data = << <<(I rem 150)>> || I <- lists:seq(1, 20 bsl 10) >>, + Compressed = zlib:compress(Data), + Z1 = zlib:open(), + ?m(ok, zlib:inflateInit(Z1)), - ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))), + + SafeInflateLoop = + fun + Loop({continue, Chunk}, Output) -> + Loop(zlib:safeInflate(Z1, []), [Output, Chunk]); + Loop({finished, Chunk}, Output) -> + [Output, Chunk] + end, + + Decompressed = SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), + Data = iolist_to_binary(Decompressed), + ?m(ok, zlib:inflateEnd(Z1)), - ?m(ok, zlib:close(Z1)). + ?m(ok, zlib:inflateInit(Z1)), -api_getBufsz(doc) -> "Test getBufsz"; -api_getBufsz(suite) -> []; -api_getBufsz(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), - ?m(Val when is_integer(Val), zlib:getBufSize(Z1)), - ?m(?BARG, zlib:getBufSize(gurka)), - ?m(ok, zlib:close(Z1)). + {continue, Partial} = zlib:safeInflate(Z1, Compressed), + PBin = iolist_to_binary(Partial), + PSize = byte_size(PBin), + <<PBin:PSize/binary, Rest/binary>> = Data, + + ?m(ok, zlib:inflateReset(Z1)), -api_setBufsz(doc) -> "Test setBufsz"; -api_setBufsz(suite) -> []; -api_setBufsz(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), - ?m(?BARG, zlib:setBufSize(Z1, gurka)), - ?m(?BARG, zlib:setBufSize(gurka, 1232330)), - Sz = ?m( Val when is_integer(Val), zlib:getBufSize(Z1)), - ?m(ok, zlib:setBufSize(Z1, Sz*2)), - DSz = Sz*2, - ?m(DSz, zlib:getBufSize(Z1)), + {continue, Partial} = zlib:safeInflate(Z1, Compressed), + PBin = iolist_to_binary(Partial), + PSize = byte_size(PBin), + <<PBin:PSize/binary, Rest/binary>> = Data, + + ?m(ok, zlib:inflateReset(Z1)), + + SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), + + ?m({finished, []}, zlib:safeInflate(Z1, Compressed)), + ?m({finished, []}, zlib:safeInflate(Z1, Compressed)), + + ?m(ok, zlib:inflateReset(Z1)), + ?m(?EXIT(badarg), zlib:safeInflate(gurka, Compressed)), + ?m(?EXIT(badarg), zlib:safeInflate(Z1, 4384)), + ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), ?m(ok, zlib:close(Z1)). -%%% Debug function ?? -api_getQSize(doc) -> "Test getQSize"; -api_getQSize(suite) -> []; -api_getQSize(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), - Q = ?m(Val when is_integer(Val), zlib:getQSize(Z1)), - io:format("QSize ~p ~n", [Q]), - ?m(?BARG, zlib:getQSize(gurka)), +%% Test inflateEnd. +api_inflateEnd(Config) when is_list(Config) -> + Z1 = zlib:open(), + ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(?EXIT(badarg), zlib:inflateEnd(gurka)), + ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), + ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))), + ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:close(Z1)). -api_crc32(doc) -> "Test crc32"; -api_crc32(suite) -> []; +%% Test crc32. api_crc32(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)), Bin = <<1,1,1,1,1,1,1,1,1>>, - Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)), - Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)), + Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)), + Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)), Compressed = list_to_binary(Compressed1 ++ Compressed2), - CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)), + CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)), ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)), ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,binary_to_list(Bin))), ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)), CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)), ?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)), - ?m(?BARG, zlib:crc32(gurka)), - ?m(?BARG, zlib:crc32(Z1, not_a_binary)), - ?m(?BARG, zlib:crc32(gurka, <<1,1,2,4,4>>)), - ?m(?BARG, zlib:crc32(Z1, 2298929, not_a_binary)), - ?m(?BARG, zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)), - ?m(?BARG, zlib:crc32_combine(Z1, not_an_int, 123123, 123)), - ?m(?BARG, zlib:crc32_combine(Z1, noint, 123123, 123)), - ?m(?BARG, zlib:crc32_combine(Z1, 123123, noint, 123)), - ?m(?BARG, zlib:crc32_combine(Z1, 123123, 123, noint)), + ?m(?EXIT(badarg), zlib:crc32(gurka)), + ?m(?EXIT(badarg), zlib:crc32(Z1, not_a_binary)), + ?m(?EXIT(badarg), zlib:crc32(gurka, <<1,1,2,4,4>>)), + ?m(?EXIT(badarg), zlib:crc32(Z1, 2298929, not_a_binary)), + ?m(?EXIT(badarg), zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, not_an_int, 123123, 123)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, noint, 123123, 123)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, noint, 123)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, 123, noint)), ?m(ok, zlib:deflateEnd(Z1)), ?m(ok, zlib:close(Z1)). -api_adler32(doc) -> "Test adler32"; -api_adler32(suite) -> []; +%% Test adler32. api_adler32(Config) when is_list(Config) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)), Bin = <<1,1,1,1,1,1,1,1,1>>, - Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)), - Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)), + Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)), + Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)), Compressed = list_to_binary(Compressed1 ++ Compressed2), ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)), ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))), ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)), ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)), ?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)), - ?m(?BARG, zlib:adler32(Z1, not_a_binary)), - ?m(?BARG, zlib:adler32(gurka, <<1,1,2,4,4>>)), - ?m(?BARG, zlib:adler32(Z1, 2298929, not_a_binary)), - ?m(?BARG, zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)), - ?m(?BARG, zlib:adler32_combine(Z1, noint, 123123, 123)), - ?m(?BARG, zlib:adler32_combine(Z1, 123123, noint, 123)), - ?m(?BARG, zlib:adler32_combine(Z1, 123123, 123, noint)), + ?m(?EXIT(badarg), zlib:adler32(Z1, not_a_binary)), + ?m(?EXIT(badarg), zlib:adler32(gurka, <<1,1,2,4,4>>)), + ?m(?EXIT(badarg), zlib:adler32(Z1, 2298929, not_a_binary)), + ?m(?EXIT(badarg), zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)), + ?m(?EXIT(badarg), zlib:adler32_combine(Z1, noint, 123123, 123)), + ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, noint, 123)), + ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, 123, noint)), ?m(ok, zlib:deflateEnd(Z1)), ?m(ok, zlib:close(Z1)). -api_un_compress(doc) -> "Test compress"; -api_un_compress(suite) -> []; +%% Test compress. api_un_compress(Config) when is_list(Config) -> - ?m(?BARG,zlib:compress(not_a_binary)), + ?m(?EXIT(badarg),zlib:compress(not_a_binary)), Bin = <<1,11,1,23,45>>, - ?line Comp = zlib:compress(Bin), - ?m(?BARG,zlib:uncompress(not_a_binary)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<171,171,171,171,171>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3,0>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<0,156,3,0,0,0,0,1>>)), + Comp = zlib:compress(Bin), + ?m(?EXIT(badarg),zlib:uncompress(not_a_binary)), + ?m(?EXIT(data_error), zlib:uncompress(<<171,171,171,171,171>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120,156>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3,0>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<0,156,3,0,0,0,0,1>>)), ?m(Bin, zlib:uncompress(binary_to_list(Comp))), ?m(Bin, zlib:uncompress(Comp)). -api_un_zip(doc) -> "Test zip"; -api_un_zip(suite) -> []; +%% Test zip. api_un_zip(Config) when is_list(Config) -> - ?m(?BARG,zlib:zip(not_a_binary)), + ?m(?EXIT(badarg),zlib:zip(not_a_binary)), Bin = <<1,11,1,23,45>>, - ?line Comp = zlib:zip(Bin), + Comp = zlib:zip(Bin), ?m(Comp, zlib:zip(binary_to_list(Bin))), - ?m(?BARG,zlib:unzip(not_a_binary)), - ?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)), - ?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)), + ?m(?EXIT(badarg),zlib:unzip(not_a_binary)), + ?m(?EXIT(data_error), zlib:unzip(<<171,171,171,171,171>>)), + ?m(?EXIT(data_error), zlib:unzip(<<>>)), ?m(Bin, zlib:unzip(Comp)), ?m(Bin, zlib:unzip(binary_to_list(Comp))), - + %% OTP-6396 - B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>, + B = + <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97, + 1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2, + 10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97, + 116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113, + 107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197, + 31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73, + 64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10 + ,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97, + 112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4, + 103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101, + 104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112, + 114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101, + 100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100, + 100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101, + 102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100, + 101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100, + 100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100, + 101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181, + 107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100, + 0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102, + 105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97, + 16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11, + 97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97, + 11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7, + 214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57, + 57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4, + 10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105, + 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125, + 248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203, + 251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0, + 200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94, + 13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120, + 5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198, + 118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0, + 108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104, + 12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64, + 104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0, + 33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101, + 114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99, + 50,52,48,4,103,112,114,115,8,0,106>>, + Z = zlib:zip(B), ?m(B, zlib:unzip(Z)). -%% api_g_un_zip_file(doc) -> "Test gunzip_file"; -%% api_g_un_zip_file(suite) -> []; -%% api_g_un_zip_file(Config) when is_list(Config) -> -%% ?line Out = conf(data_dir,Config), -%% io:format("Using OutDir ~p ~n", [Out]), -%% F = filename:join(Out,"testing1"), -%% Data = <<1,1,255,255,255,1,1>>, -%% ?m(ok, file:write_file(F,Data)), -%% ?line Compressed = zlib:gzip_file(F), -%% ?m(ok, file:write_file(F++".gz",Compressed)), -%% ?m(Data, zlib:gunzip_file(F++".gz")), -%% ?m({error,enoent}, zlib:gunzip_file(gurka)), -%% ?m({error,enoent}, zlib:gzip_file(gurka)), -%% ?m({error,what}, zlib:gunzip_file(F)), -%% ?line ok. - -api_g_un_zip(doc) -> "Test gunzip"; -api_g_un_zip(suite) -> []; +%% Test gunzip. api_g_un_zip(Config) when is_list(Config) -> - ?m(?BARG,zlib:gzip(not_a_binary)), + ?m(?EXIT(badarg),zlib:gzip(not_a_binary)), Bin = <<1,11,1,23,45>>, - ?line Comp = zlib:gzip(Bin), + Comp = zlib:gzip(Bin), + ?m(Comp, zlib:gzip(binary_to_list(Bin))), - ?m(?BARG, zlib:gunzip(not_a_binary)), - ?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)), - ?m(?DATA_ERROR, zlib:gunzip(<<>>)), + ?m(?EXIT(badarg), zlib:gunzip(not_a_binary)), + ?m(?EXIT(data_error), zlib:gunzip(<<171,171,171,171,171>>)), + ?m(?EXIT(data_error), zlib:gunzip(<<>>)), ?m(Bin, zlib:gunzip(Comp)), ?m(Bin, zlib:gunzip(binary_to_list(Comp))), - + + %% RFC 1952: + %% + %% "A gzip file consists of a series of "members" (compressed data + %% sets). [...] The members simply appear one after another in the file, + %% with no additional information before, between, or after them." + Concatenated = <<Bin/binary, Bin/binary>>, + ?m(Concatenated, zlib:gunzip([Comp, Comp])), + + %% Don't explode if the uncompressed size is a perfect multiple of the + %% internal inflate chunk size. + ChunkSizedData = <<0:16384/unit:8>>, + ?m(ChunkSizedData, zlib:gunzip(zlib:gzip(ChunkSizedData))), + %% Bad CRC; bad length. BadCrc = bad_crc_data(), - ?line ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadCrc))), + ?m(?EXIT(data_error),(catch zlib:gunzip(BadCrc))), BadLen = bad_len_data(), - ?line ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadLen))), + ?m(?EXIT(data_error),(catch zlib:gunzip(BadLen))), ok. bad_crc_data() -> @@ -564,76 +707,57 @@ bad_len_data() -> <<31,139,8,0,0,0,0,0,0,3,211,2,0,91,38,185,9,2,0,0,0>>. -intro(suite) -> []; -intro(doc) -> ""; intro(Config) when is_list(Config) -> D = <<"This is a binary">>, [put({ex, N}, <<"This is a binary">>) || N <- [0,1,2,3,4]], put({ex, 5}, end_of_data), put(ex,0), - ?line Read = fun() -> - N = get(ex), - put(ex,N+1), - get({ex,N}) - end, - - ?line Z = zlib:open(), - ?line ok = zlib:deflateInit(Z,default), - - ?line Compress = fun(end_of_data, _Cont) -> []; - (Data, Cont) -> - [zlib:deflate(Z, Data)|Cont(Read(),Cont)] - end, - ?line Compressed = Compress(Read(),Compress), - ?line Last = zlib:deflate(Z, [], finish), - ?line ok = zlib:deflateEnd(Z), - ?line zlib:close(Z), - ?line Res = list_to_binary([Compressed|Last]), + Read = fun() -> + N = get(ex), + put(ex,N+1), + get({ex,N}) + end, + + Z = zlib:open(), + ok = zlib:deflateInit(Z,default), + + Compress = fun(end_of_data, _Cont) -> []; + (Data, Cont) -> + [zlib:deflate(Z, Data)|Cont(Read(),Cont)] + end, + Compressed = Compress(Read(),Compress), + Last = zlib:deflate(Z, [], finish), + ok = zlib:deflateEnd(Z), + zlib:close(Z), + Res = list_to_binary([Compressed|Last]), Orig = list_to_binary(lists:duplicate(5, D)), ?m(Orig, zlib:uncompress(Res)). -large_deflate(doc) -> "Test deflate large file, which had a bug reported on erlang-bugs"; -large_deflate(suite) -> []; +%% Test deflate large file, which had a bug reported on erlang-bugs. large_deflate(Config) when is_list(Config) -> large_deflate_do(). large_deflate_do() -> - ?line Z = zlib:open(), - ?line Plain = rand_bytes(zlib:getBufSize(Z)*5), - ?line ok = zlib:deflateInit(Z), - ?line _ZlibHeader = zlib:deflate(Z, [], full), - ?line Deflated = zlib:deflate(Z, Plain, full), - ?m(ok, zlib:close(Z)), - ?m(Plain, zlib:unzip(list_to_binary([Deflated, 3, 0]))). - -rand_bytes(Sz) -> - L = <<8,2,3,6,1,2,3,2,3,4,8,7,3,7,2,3,4,7,5,8,9,3>>, - rand_bytes(erlang:md5(L),Sz). - -rand_bytes(Bin, Sz) when byte_size(Bin) >= Sz -> - <<Res:Sz/binary, _/binary>> = Bin, - Res; -rand_bytes(Bin, Sz) -> - rand_bytes(<<(erlang:md5(Bin))/binary, Bin/binary>>, Sz). - - -zip_usage(doc) -> "Test a standard compressed zip file"; -zip_usage(suite) -> []; + Plain = gen_determ_rand_bytes(64 bsl 10), + Deflated = zlib:zip(Plain), + ?m(Plain, zlib:unzip(Deflated)). + +%% Test a standard compressed zip file. zip_usage(Config) when is_list(Config) -> zip_usage(zip_usage({get_arg,Config})); zip_usage({get_arg,Config}) -> - ?line Out = conf(data_dir,Config), - ?line {ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")), - ?line {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), + Out = get_data_dir(Config), + {ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")), + {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), {run,ZIP,ORIG}; zip_usage({run,ZIP,ORIG}) -> - ?line <<_:14/binary, CRC:32/little, - CompSz:32/little, UnCompSz:32/little,_:31/binary, - Compressed:CompSz/binary, _/binary>> = ZIP, - + <<_:14/binary, CRC:32/little, + CompSz:32/little, UnCompSz:32/little,_:31/binary, + Compressed:CompSz/binary, _/binary>> = ZIP, + %%io:format("CRC ~p CSz ~p UnCSz ~p ~n", [CRC,CompSz,UnCompSz]), - ?line Split = split_bin(Compressed,[]), - ?line Z = zlib:open(), + Split = split_bin(Compressed,[]), + Z = zlib:open(), ?m(ok, zlib:inflateInit(Z, -15)), Bs = [zlib:inflate(Z, Part) || Part <- Split], @@ -643,86 +767,84 @@ zip_usage({run,ZIP,ORIG}) -> ?m(true, zlib:crc32(Z,UC0) == zlib:crc32(Z,ORIG)), ?m(ok, zlib:inflateEnd(Z)), - ?line UC1 = zlib:unzip(Compressed), + UC1 = zlib:unzip(Compressed), ?m(UnCompSz, byte_size(UC1)), ?m(true, zlib:crc32(Z,UC1) == zlib:crc32(Z,ORIG)), - + ?m(ok, zlib:inflateInit(Z, -15)), - ?line UC2 = zlib:inflate(Z, Compressed), + UC2 = zlib:inflate(Z, Compressed), ?m(UnCompSz, byte_size(list_to_binary(UC2))), ?m(CRC, zlib:crc32(Z)), ?m(true, zlib:crc32(Z,UC2) == zlib:crc32(Z,ORIG)), ?m(ok, zlib:inflateEnd(Z)), - + ?m(ok, zlib:inflateInit(Z, -15)), - ?line UC3 = zlib:inflate(Z, Split), % Test multivec. + UC3 = zlib:inflate(Z, Split), % Test multivec. ?m(UnCompSz, byte_size(list_to_binary(UC3))), ?m(true, zlib:crc32(Z,UC3) == zlib:crc32(Z,ORIG)), ?m(CRC, zlib:crc32(Z)), ?m(ok, zlib:inflateEnd(Z)), - + ?m(ok, zlib:inflateInit(Z, -15)), ?m(ok, zlib:setBufSize(Z, UnCompSz *2)), - ?line UC4 = zlib:inflate(Z, Compressed), + UC4 = zlib:inflate(Z, Compressed), ?m(UnCompSz, byte_size(list_to_binary(UC4))), ?m(CRC, zlib:crc32(Z)), ?m(CRC, zlib:crc32(Z,UC4)), ?m(true, zlib:crc32(Z,UC4) == zlib:crc32(Z,ORIG)), ?m(ok, zlib:inflateEnd(Z)), - - ?line C1 = zlib:zip(ORIG), - ?line UC5 = zlib:unzip(C1), + + C1 = zlib:zip(ORIG), + UC5 = zlib:unzip(C1), ?m(CRC, zlib:crc32(Z,UC5)), ?m(true,zlib:crc32(Z,UC5) == zlib:crc32(Z,ORIG)), - + ?m(ok, zlib:deflateInit(Z, default, deflated, -15, 8, default)), - ?line C2 = zlib:deflate(Z, ORIG, finish), - ?m(true, C1 == list_to_binary(C2)), + C2 = zlib:deflate(Z, ORIG, finish), + ?m(ORIG, zlib:unzip(C2)), ?m(ok, zlib:deflateEnd(Z)), - + ?m(ok, zlib:deflateInit(Z, none, deflated, -15, 8, filtered)), ?m(ok, zlib:deflateParams(Z, default, default)), - ?line C3 = zlib:deflate(Z, ORIG, finish), - ?m(true, C1 == list_to_binary(C3)), + C3 = zlib:deflate(Z, ORIG, finish), + ?m(ORIG, zlib:unzip(C3)), ?m(ok, zlib:deflateEnd(Z)), - ?line ok = zlib:close(Z), - ?line ok. + ok = zlib:close(Z), + ok. -gz_usage(doc) -> "Test a standard compressed gzipped file"; -gz_usage(suite) -> []; +%% Test a standard compressed gzipped file. gz_usage(Config) when is_list(Config) -> gz_usage(gz_usage({get_arg,Config})); gz_usage({get_arg,Config}) -> - ?line Out = conf(data_dir,Config), - ?line {ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")), - ?line {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), - ?line {ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")), + Out = get_data_dir(Config), + {ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")), + {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), + {ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")), {run,GZIP,ORIG,GZIP2}; gz_usage({run,GZIP,ORIG,GZIP2}) -> - ?line Z = zlib:open(), - ?line UC1 = zlib:gunzip(GZIP), + Z = zlib:open(), + UC1 = zlib:gunzip(GZIP), ?m(true,zlib:crc32(Z,UC1) == zlib:crc32(Z,ORIG)), - ?line UC3 = zlib:gunzip(GZIP2), + UC3 = zlib:gunzip(GZIP2), ?m(true,zlib:crc32(Z,UC3) == zlib:crc32(Z,ORIG)), - ?line Compressed = zlib:gzip(ORIG), - ?line UC5 = zlib:gunzip(Compressed), + Compressed = zlib:gzip(ORIG), + UC5 = zlib:gunzip(Compressed), ?m(true,zlib:crc32(Z,UC5) == zlib:crc32(Z,ORIG)), - ?line ok = zlib:close(Z). + ok = zlib:close(Z). -gz_usage2(doc) -> "Test more of a standard compressed gzipped file"; -gz_usage2(suite) -> []; +%% Test more of a standard compressed gzipped file. gz_usage2(Config) -> case os:find_executable("gzip") of Name when is_list(Name) -> - ?line Z = zlib:open(), - ?line Out = conf(data_dir,Config), - ?line {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), - ?line Compressed = zlib:gzip(ORIG), + Z = zlib:open(), + Out = get_data_dir(Config), + {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), + Compressed = zlib:gzip(ORIG), GzOutFile = filename:join(Out,"out.gz"), OutFile = filename:join(Out,"out.txt"), ?m(ok, file:write_file(GzOutFile,Compressed)), - ?line os:cmd("gzip -c -d " ++ GzOutFile ++ " > " ++ OutFile), + os:cmd("gzip -c -d " ++ GzOutFile ++ " > " ++ OutFile), case file:read_file(OutFile) of {ok,ExtDecompressed} -> ?m(true, @@ -731,83 +853,80 @@ gz_usage2(Config) -> io:format("Couldn't test external decompressor ~p\n", [Error]) end, - ?line ok = zlib:close(Z), + ok = zlib:close(Z), ok; false -> {skipped,"No gzip in path"} end. - -compress_usage(doc) -> - "Test that (de)compress funcs work with" - " standard tools, for example a chunk from a png file"; -compress_usage(suite) -> []; + +%% Test that (de)compress funcs work with standard tools, for example +%% a chunk from a png file. compress_usage(Config) when is_list(Config) -> compress_usage(compress_usage({get_arg,Config})); compress_usage({get_arg,Config}) -> - ?line Out = conf(data_dir,Config), - ?line {ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")), + Out = get_data_dir(Config), + {ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")), {run,C1}; compress_usage({run,C1}) -> - ?line Z = zlib:open(), + Z = zlib:open(), %% See that we can uncompress a file generated with external prog. - ?line UC1 = zlib:uncompress(C1), + UC1 = zlib:uncompress(C1), %% Check that the crc are correct. ?m(4125865008,zlib:crc32(Z,UC1)), - ?line C2 = zlib:compress(UC1), - ?line UC2 = zlib:uncompress(C2), + C2 = zlib:compress(UC1), + UC2 = zlib:uncompress(C2), %% Check that the crc are correct. ?m(4125865008,zlib:crc32(Z,UC2)), - - ?line ok = zlib:close(Z), + + ok = zlib:close(Z), D = [<<"We tests some partial">>, <<"data, sent over">>, <<"the stream">>, <<"we check that we can unpack">>, <<"every message we get">>], - - ?line ZC = zlib:open(), - ?line ZU = zlib:open(), + + ZC = zlib:open(), + ZU = zlib:open(), Test = fun(finish, {_,Tot}) -> - ?line Compressed = zlib:deflate(ZC, <<>>, finish), + Compressed = zlib:deflate(ZC, <<>>, finish), Data = zlib:inflate(ZU, Compressed), [Tot|Data]; (Data, {Op,Tot}) -> - ?line Compressed = zlib:deflate(ZC, Data, Op), + Compressed = zlib:deflate(ZC, Data, Op), Res1 = ?m([Data],zlib:inflate(ZU, Compressed)), {Op, [Tot|Res1]} end, - ?line zlib:deflateInit(ZC), - ?line zlib:inflateInit(ZU), - ?line T1 = lists:foldl(Test,{sync,[]},D++[finish]), + zlib:deflateInit(ZC), + zlib:inflateInit(ZU), + T1 = lists:foldl(Test,{sync,[]},D++[finish]), ?m(true, list_to_binary(D) == list_to_binary(T1)), - ?line zlib:deflateEnd(ZC), - ?line zlib:inflateEnd(ZU), - - ?line zlib:deflateInit(ZC), - ?line zlib:inflateInit(ZU), - ?line T2 = lists:foldl(Test,{full,[]},D++[finish]), + zlib:deflateEnd(ZC), + zlib:inflateEnd(ZU), + + zlib:deflateInit(ZC), + zlib:inflateInit(ZU), + T2 = lists:foldl(Test,{full,[]},D++[finish]), ?m(true, list_to_binary(D) == list_to_binary(T2)), - ?line zlib:deflateEnd(ZC), - ?line zlib:inflateEnd(ZU), - - ?line ok = zlib:close(ZC), - ?line ok = zlib:close(ZU). + zlib:deflateEnd(ZC), + zlib:inflateEnd(ZU), + ok = zlib:close(ZC), + ok = zlib:close(ZU). -crc(doc) -> "Check that crc works as expected"; -crc(suite) -> []; + +%% Check that crc works as expected. crc(Config) when is_list(Config) -> crc(crc({get_arg,Config})); crc({get_arg,Config}) -> - ?line Out = conf(data_dir,Config), - ?line {ok,C1} = file:read_file(filename:join(Out,"zipdoc")), + Out = get_data_dir(Config), + {ok,C1} = file:read_file(filename:join(Out,"zipdoc")), {run,C1}; crc({run,C1}) -> - ?line Z = zlib:open(), - ?line Crc = zlib:crc32(Z, C1), + Z = zlib:open(), + Crc = zlib:crc32(Z, C1), Bins = split_bin(C1,[]), %%io:format("Length ~p ~p ~n", [length(Bins), [size(Bin) || Bin <- Bins]]), Last = lists:last(Bins), @@ -817,29 +936,28 @@ crc({run,C1}) -> Crc1 end, 0, Bins), ?m(Crc,SCrc), - ?line [First|Rest] = Bins, + [First|Rest] = Bins, Combine = fun(Bin, CS1) -> CS2 = zlib:crc32(Z, Bin), S2 = byte_size(Bin), zlib:crc32_combine(Z,CS1,CS2,S2) end, - ?line Comb = lists:foldl(Combine, zlib:crc32(Z, First), Rest), + Comb = lists:foldl(Combine, zlib:crc32(Z, First), Rest), ?m(Crc,Comb), - ?line ok = zlib:close(Z). + ok = zlib:close(Z). -adler(doc) -> "Check that adler works as expected"; -adler(suite) -> []; +%% Check that adler works as expected. adler(Config) when is_list(Config) -> adler(adler({get_arg,Config})); adler({get_arg,Config}) -> - ?line Out = conf(data_dir,Config), + Out = get_data_dir(Config), File1 = filename:join(Out,"zipdoc"), - ?line {ok,C1} = file:read_file(File1), + {ok,C1} = file:read_file(File1), {run,C1}; adler({run,C1}) -> - ?line Z = zlib:open(), + Z = zlib:open(), ?m(1, zlib:adler32(Z,<<>>)), - ?line Crc = zlib:adler32(Z, C1), + Crc = zlib:adler32(Z, C1), Bins = split_bin(C1,[]), Last = lists:last(Bins), SCrc = lists:foldl(fun(Bin,Crc0) -> @@ -848,43 +966,46 @@ adler({run,C1}) -> Crc1 end, zlib:adler32(Z,<<>>), Bins), ?m(Crc,SCrc), - ?line [First|Rest] = Bins, + [First|Rest] = Bins, Combine = fun(Bin, CS1) -> CS2 = zlib:adler32(Z, Bin), S2 = byte_size(Bin), zlib:adler32_combine(Z,CS1,CS2,S2) end, - ?line Comb = lists:foldl(Combine, zlib:adler32(Z, First), Rest), + Comb = lists:foldl(Combine, zlib:adler32(Z, First), Rest), ?m(Crc,Comb), - ?line ok = zlib:close(Z). + ok = zlib:close(Z). -dictionary_usage(doc) -> "Test dictionary usage"; -dictionary_usage(suite) -> []; +%% Test dictionary usage. dictionary_usage(Config) when is_list(Config) -> dictionary_usage(dictionary_usage({get_arg,Config})); dictionary_usage({get_arg,_Config}) -> {run}; % no args dictionary_usage({run}) -> - ?line Z1 = zlib:open(), + Z1 = zlib:open(), Dict = <<"Anka">>, Data = <<"Kalle Anka">>, ?m(ok, zlib:deflateInit(Z1)), - ?line DictID = zlib:deflateSetDictionary(Z1, Dict), - %% ?line io:format("DictID = ~p\n", [DictID]), - ?line B1 = zlib:deflate(Z1, Data), - ?line B2 = zlib:deflate(Z1, <<>>, finish), + DictID = zlib:deflateSetDictionary(Z1, Dict), + %% io:format("DictID = ~p\n", [DictID]), + B1 = zlib:deflate(Z1, Data), + B2 = zlib:deflate(Z1, <<>>, finish), ?m(ok, zlib:deflateEnd(Z1)), ?m(ok, zlib:close(Z1)), Compressed = list_to_binary([B1,B2]), %% io:format("~p\n", [Compressed]), %% Now uncompress. - ?line Z2 = zlib:open(), + Z2 = zlib:open(), ?m(ok, zlib:inflateInit(Z2)), - ?line {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)), + + ?m(?EXIT({need_dictionary, DictID}), zlib:inflate(Z2, Compressed)), + ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), ?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))), - ?line Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])), + + Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])), + ?m(ok, zlib:inflateEnd(Z2)), ?m(ok, zlib:close(Z2)), ?m(Data, list_to_binary(Uncompressed)). @@ -894,38 +1015,82 @@ split_bin(<<Part:1997/binary,Rest/binary>>, Acc) -> split_bin(Last,Acc) -> lists:reverse([Last|Acc]). +only_allow_owner(Config) when is_list(Config) -> + Z = zlib:open(), + Owner = self(), + + ?m(ok, zlib:inflateInit(Z)), + ?m(ok, zlib:inflateReset(Z)), + + {Pid, Ref} = spawn_monitor( + fun() -> + ?m(?EXIT(not_on_controlling_process), zlib:inflateReset(Z)), + Owner ! '$transfer_ownership', + receive + '$ownership_transferred' -> + ?m(ok, zlib:inflateReset(Z)) + after 200 -> + ct:fail("Never received transfer signal.") + end + end), + ownership_transfer_check(Z, Pid, Ref). + +ownership_transfer_check(Z, WorkerPid, Ref) -> + receive + '$transfer_ownership' -> + zlib:set_controlling_process(Z, WorkerPid), + WorkerPid ! '$ownership_transferred', + ownership_transfer_check(Z, WorkerPid, Ref); + {'DOWN', Ref, process, WorkerPid, normal} -> + ok; + {'DOWN', Ref, process, WorkerPid, Reason} -> + ct:fail("Spawned worker crashed with reason ~p.", [Reason]) + after 200 -> + ct:fail("Spawned worker timed out.") + end. -smp(doc) -> "Check concurrent access to zlib driver"; -smp(suite) -> []; -smp(Config) -> - case erlang:system_info(smp_support) of - true -> - NumOfProcs = lists:min([8,erlang:system_info(schedulers)]), - io:format("smp starting ~p workers\n",[NumOfProcs]), - - %% Tests to run in parallel. - Funcs = [zip_usage, gz_usage, compress_usage, dictionary_usage, - crc, adler], +sub_heap_binaries(Config) when is_list(Config) -> + Compressed = zlib:compress(<<"gurka">>), + ConfLen = erlang:length(Config), - %% We get all function arguments here to avoid repeated parallel - %% file read access. - FnAList = lists:map(fun(F) -> {F,?MODULE:F({get_arg,Config})} - end, Funcs), + HeapBin = <<ConfLen:8/integer, Compressed/binary>>, + <<_:8/integer, SubHeapBin/binary>> = HeapBin, - Pids = [spawn_link(?MODULE, worker, [random:uniform(9999), - list_to_tuple(FnAList), - self()]) - || _ <- lists:seq(1,NumOfProcs)], - wait_pids(Pids); + ?m(<<"gurka">>, zlib:uncompress(SubHeapBin)), + ok. - false -> - {skipped,"No smp support"} +%% Check concurrent access to zlib driver. +smp(Config) -> + case erlang:system_info(smp_support) of + true -> + NumOfProcs = lists:min([8,erlang:system_info(schedulers)]), + io:format("smp starting ~p workers\n",[NumOfProcs]), + + %% Tests to run in parallel. + Funcs = + [zip_usage, gz_usage, compress_usage, dictionary_usage, + crc, adler], + + %% We get all function arguments here to avoid repeated parallel + %% file read access. + UsageArgs = + list_to_tuple([{F, ?MODULE:F({get_arg,Config})} || F <- Funcs]), + Parent = self(), + + WorkerFun = + fun() -> + worker(rand:uniform(9999), UsageArgs, Parent) + end, + + Pids = [spawn_link(WorkerFun) || _ <- lists:seq(1, NumOfProcs)], + wait_pids(Pids); + false -> + {skipped,"No smp support"} end. - worker(Seed, FnATpl, Parent) -> io:format("smp worker ~p, seed=~p~n",[self(),Seed]), - random:seed(Seed,Seed,Seed), + rand:seed(exsplus, {Seed,Seed,Seed}), worker_loop(100, FnATpl), Parent ! self(). @@ -933,33 +1098,32 @@ worker_loop(0, _FnATpl) -> large_deflate_do(), % the time consuming one as finale ok; worker_loop(N, FnATpl) -> - {F,A} = element(random:uniform(size(FnATpl)),FnATpl), + {F,A} = element(rand:uniform(tuple_size(FnATpl)), FnATpl), ?MODULE:F(A), worker_loop(N-1, FnATpl). - + wait_pids([]) -> ok; wait_pids(Pids) -> receive Pid -> - ?line true = lists:member(Pid,Pids), + true = lists:member(Pid,Pids), Others = lists:delete(Pid,Pids), io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]), wait_pids(Others) end. -otp_7359(doc) -> "Deflate/inflate data with size close to multiple of internal buffer size"; -otp_7359(suite) -> []; +%% Deflate/inflate data with size close to multiple of internal buffer size. otp_7359(_Config) -> %% Find compressed size ZTry = zlib:open(), ok = zlib:deflateInit(ZTry), ISize = zlib:getBufSize(ZTry), IData = list_to_binary([Byte band 255 || Byte <- lists:seq(1,ISize)]), - ?line ISize = byte_size(IData), + ISize = byte_size(IData), - ?line DSize = iolist_size(zlib:deflate(ZTry, IData, sync)), + DSize = iolist_size(zlib:deflate(ZTry, IData, sync)), zlib:close(ZTry), io:format("Deflated try ~p -> ~p bytes~n", [ISize, DSize]), @@ -981,19 +1145,19 @@ otp_7359(_Config) -> otp_7359_def_inf(Data,{DefSize,InfSize}) -> %%io:format("Try: DefSize=~p InfSize=~p~n", [DefSize,InfSize]), - ?line ZDef = zlib:open(), - ?line ok = zlib:deflateInit(ZDef), - ?line ok = zlib:setBufSize(ZDef,DefSize), - ?line DefData = iolist_to_binary(zlib:deflate(ZDef, Data, sync)), + ZDef = zlib:open(), + ok = zlib:deflateInit(ZDef), + ok = zlib:setBufSize(ZDef,DefSize), + DefData = iolist_to_binary(zlib:deflate(ZDef, Data, sync)), %%io:format("Deflated ~p(~p) -> ~p(~p) bytes~n", %% [byte_size(Data), InfSize, byte_size(DefData), DefSize]), - ?line ok = zlib:close(ZDef), + ok = zlib:close(ZDef), - ?line ZInf = zlib:open(), - ?line ok = zlib:inflateInit(ZInf), - ?line ok = zlib:setBufSize(ZInf,InfSize), - ?line Data = iolist_to_binary(zlib:inflate(ZInf, DefData)), - ?line ok = zlib:close(ZInf), + ZInf = zlib:open(), + ok = zlib:inflateInit(ZInf), + ok = zlib:setBufSize(ZInf,InfSize), + Data = iolist_to_binary(zlib:inflate(ZInf, DefData)), + ok = zlib:close(ZInf), ok. otp_9981(Config) when is_list(Config) -> @@ -1013,43 +1177,98 @@ otp_9981(Config) when is_list(Config) -> Ports = lists:sort(erlang:ports()), ok. - +-define(BENCH_SIZE, (16 bsl 20)). + +-define(DECOMPRESS_BENCH(Name, What, Data), + Name(Config) when is_list(Config) -> + Uncompressed = Data, + Compressed = zlib:compress(Uncompressed), + What(Compressed, byte_size(Uncompressed))). + +-define(COMPRESS_BENCH(Name, What, Data), + Name(Config) when is_list(Config) -> + Compressed = Data, + What(Compressed, byte_size(Compressed))). + +?DECOMPRESS_BENCH(inflate_bench_zeroed, throughput_bench_inflate, + <<0:(8 * ?BENCH_SIZE)>>). +?DECOMPRESS_BENCH(inflate_bench_rand, throughput_bench_inflate, + gen_determ_rand_bytes(?BENCH_SIZE)). + +?DECOMPRESS_BENCH(chunk_bench_zeroed, throughput_bench_chunk, + <<0:(8 * ?BENCH_SIZE)>>). +?DECOMPRESS_BENCH(chunk_bench_rand, throughput_bench_chunk, + gen_determ_rand_bytes(?BENCH_SIZE)). + +?COMPRESS_BENCH(deflate_bench_zeroed, throughput_bench_deflate, + <<0:(8 * ?BENCH_SIZE)>>). +?COMPRESS_BENCH(deflate_bench_rand, throughput_bench_deflate, + gen_determ_rand_bytes(?BENCH_SIZE)). + +throughput_bench_inflate(Compressed, Size) -> + Z = zlib:open(), + zlib:inflateInit(Z), + + submit_throughput_results(Size, + fun() -> + zlib:inflate(Z, Compressed) + end). + +throughput_bench_deflate(Uncompressed, Size) -> + Z = zlib:open(), + zlib:deflateInit(Z), + + submit_throughput_results(Size, + fun() -> + zlib:deflate(Z, Uncompressed, finish) + end). + +throughput_bench_chunk(Compressed, Size) -> + Z = zlib:open(), + zlib:inflateInit(Z), + + ChunkLoop = + fun + Loop({more, _}) -> Loop(zlib:inflateChunk(Z)); + Loop(_) -> ok + end, + + submit_throughput_results(Size, + fun() -> + ChunkLoop(zlib:inflateChunk(Z, Compressed)) + end). + +submit_throughput_results(Size, Fun) -> + TimeTaken = measure_perf_counter(Fun, millisecond), + + KBPS = trunc((Size bsr 10) / (TimeTaken / 1000)), + ct_event:notify(#event{ name = benchmark_data, data = [{value,KBPS}] }), + {comment, io_lib:format("~p ms, ~p KBPS", [TimeTaken, KBPS])}. + +measure_perf_counter(Fun, Unit) -> + Start = os:perf_counter(Unit), + Fun(), + os:perf_counter(Unit) - Start. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Helps with testing directly %%%%%%%%%%%%% -conf(What,Config) -> - try ?config(What,Config) of - undefined -> - "./zlib_SUITE_data"; - Dir -> - Dir +get_data_dir(Config) -> + try proplists:get_value(data_dir,Config) of + undefined -> + "./zlib_SUITE_data"; + Dir -> + Dir catch - _:_ -> "./zlib_SUITE_data" + _:_ -> "./zlib_SUITE_data" end. -t() -> t([all]). - -t(What) when not is_list(What) -> - t([What]); -t(What) -> - lists:foreach(fun(T) -> - try ?MODULE:T([]) - catch _E:_R -> - Line = get(test_server_loc), - io:format("Failed ~p:~p ~p ~p ~p~n", - [T,Line,_E,_R, erlang:get_stacktrace()]) - end - end, expand(What)). - -expand(All) -> - lists:reverse(expand(All,[])). -expand([H|T], Acc) -> - case ?MODULE:H(suite) of - [] -> expand(T,[H|Acc]); - Cs -> - R = expand(Cs, Acc), - expand(T, R) - end; -expand([], Acc) -> Acc. - +%% Generates a bunch of statistically random bytes using the size as seed. +gen_determ_rand_bytes(Size) -> + gen_determ_rand_bytes(Size, erlang:md5_init(), <<>>). +gen_determ_rand_bytes(Size, _Context, Acc) when Size =< 0 -> + Acc; +gen_determ_rand_bytes(Size, Context0, Acc) when Size > 0 -> + Context = erlang:md5_update(Context0, <<Size/integer>>), + Checksum = erlang:md5_final(Context), + gen_determ_rand_bytes(Size - 16, Context, <<Acc/binary, Checksum/binary>>). |