diff options
Diffstat (limited to 'lib/kernel/test')
37 files changed, 3305 insertions, 2048 deletions
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 8eca37029d..cb11d4e899 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2012. All Rights Reserved. +# Copyright Ericsson AB 1997-2013. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -48,6 +48,7 @@ MODULES= \ erl_distribution_SUITE \ erl_distribution_wb_SUITE \ erl_prim_loader_SUITE \ + error_handler_SUITE \ error_logger_SUITE \ error_logger_warn_SUITE \ file_SUITE \ @@ -73,6 +74,7 @@ MODULES= \ seq_trace_SUITE \ wrap_log_reader_SUITE \ cleanup \ + ignore_cores \ zlib_SUITE \ loose_node \ sendfile_SUITE diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index f469a0af98..1ff291be54 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,18 +21,21 @@ -include_lib("test_server/include/test_server.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - failover/1, failover_comp/1, permissions/1, load/1, + init_per_group/2,end_per_group/2 + ]). + +-export([failover/1, failover_comp/1, permissions/1, load/1, load_use_cache/1, otp_1586/1, otp_2078/1, otp_2012/1, otp_2718/1, otp_2973/1, otp_3002/1, otp_3184/1, otp_4066/1, otp_4227/1, otp_5363/1, otp_5606/1, - start_phases/1, get_key/1, + start_phases/1, get_key/1, get_env/1, permit_false_start_local/1, permit_false_start_dist/1, script_start/1, nodedown_start/1, init2973/0, loop2973/0, loop5606/1]). -export([config_change/1, distr_changed_tc1/1, distr_changed_tc2/1, + ensure_started/1, shutdown_func/1, do_shutdown/1, shutdown_timeout/1]). -define(TESTCASE, testcase_name). @@ -47,9 +50,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [failover, failover_comp, permissions, load, - load_use_cache, {group, reported_bugs}, start_phases, + load_use_cache, ensure_started, {group, reported_bugs}, start_phases, script_start, nodedown_start, permit_false_start_local, - permit_false_start_dist, get_key, + permit_false_start_dist, get_key, get_env, {group, distr_changed}, config_change, shutdown_func, shutdown_timeout]. groups() -> @@ -76,10 +79,10 @@ end_per_group(_GroupName, Config) -> init_per_testcase(otp_2973=Case, Config) -> code:add_path(?config(data_dir,Config)), - ?line Dog = test_server:timetrap(?default_timeout), + Dog = test_server:timetrap(?default_timeout), [{?TESTCASE, Case}, {watchdog, Dog}|Config]; init_per_testcase(Case, Config) -> - ?line Dog = test_server:timetrap(?default_timeout), + Dog = test_server:timetrap(?default_timeout), [{?TESTCASE, Case}, {watchdog, Dog}|Config]. end_per_testcase(otp_2973, Config) -> @@ -121,92 +124,92 @@ failover(doc) -> failover(Conf) when is_list(Conf) -> %% start a help process to check the start type StPid = spawn_link(?MODULE, start_type, []), - ?line yes = global:register_name(st_type, StPid), + yes = global:register_name(st_type, StPid), NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config_fo(NodeNames)), WithSyncTime = config_fun(config_fo(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), + {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], - ?line wait_for_ready_net(), + wait_for_ready_net(), % Start app1 and make sure cp1 starts it - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app1, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app1, Cp1)), + false = is_started(app1, Cp2), + ok = get_start_type(#st{normal = 3}), % Stop cp1 and make sure cp2 starts app1 stop_node_nice(Cp1), - ?line ?UNTIL(is_started(app1, Cp2)), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app1, Cp2)), + ok = get_start_type(#st{normal = 3}), % Restart cp1 and make sure it restarts app1 - ?line {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp1_2, application, load, [app1()]), - ?line ok = rpc:call(Cp1_2, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line ?UNTIL(not is_started(app1, Cp2)), - ?line ok = get_start_type(#st{takeover = 3}), + {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), + global:sync(), + ok = rpc:call(Cp1_2, application, load, [app1()]), + ok = rpc:call(Cp1_2, application, start, [app1, permanent]), + ?UNTIL(is_started(app1, Cp1)), + ?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) - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1_2, Cp2, Cp3], application, load, [app_sp()]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1_2, Cp2, Cp3], application, start,[app_sp,permanent]), - ?line ?UNTIL(is_started(app_sp, Cp2)), - ?line false = is_started(app_sp, Cp1), - ?line false = is_started(app_sp, Cp3), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app_sp, Cp2)), + false = is_started(app_sp, Cp1), + false = is_started(app_sp, Cp3), + ok = get_start_type(#st{normal = 3}), % Stop cp2 and make sure cp1 starts app_sp stop_node_nice(Cp2), - ?line ?UNTIL(is_started(app_sp, Cp1_2)), - ?line ok = get_start_type(#st{failover = 3}), + ?UNTIL(is_started(app_sp, Cp1_2)), + ok = get_start_type(#st{failover = 3}), % Stop cp1 and make sure cp3 starts app_sp stop_node_nice(Cp1_2), - ?line ?UNTIL(is_started(app_sp, Cp3)), - ?line ok = get_start_type(#st{normal = 3, failover = 3}), + ?UNTIL(is_started(app_sp, Cp3)), + ok = get_start_type(#st{normal = 3, failover = 3}), % Restart cp2 and make sure it restarts app_sp - ?line {ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp2_2, application, load, [app_sp()]), - ?line ok = rpc:call(Cp2_2, application, start, [app_sp, permanent]), - ?line ?UNTIL(is_started(app_sp, Cp2_2)), - ?line ?UNTIL(not is_started(app_sp, Cp3)), - ?line ok = get_start_type(#st{takeover = 3}), + {ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf), + global:sync(), + ok = rpc:call(Cp2_2, application, load, [app_sp()]), + ok = rpc:call(Cp2_2, application, start, [app_sp, permanent]), + ?UNTIL(is_started(app_sp, Cp2_2)), + ?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 - ?line {ok, Cp1_3} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp1_3, application, load, [app_sp()]), - ?line ok = rpc:call(Cp1_3, application, start, [app_sp, permanent]), + {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), - ?line false = is_started(app_sp, Cp1_3), - ?line true = is_started(app_sp, Cp2_2), + false = is_started(app_sp, Cp1_3), + true = is_started(app_sp, Cp2_2), % Force takeover to cp1 - ?line ok = rpc:call(Cp1_3, application, takeover, [app_sp, permanent]), - ?line ?UNTIL(is_started(app_sp, Cp1_3)), - ?line ?UNTIL(not is_started(app_sp, Cp2_2)), - ?line ok = get_start_type(#st{takeover = 3}), + 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)), + ok = get_start_type(#st{takeover = 3}), %% Kill one child process and see that it is started with type local PP = global:whereis_name({ch,3}), exit(PP, kill), - ?line ok = get_start_type(#st{local = 1}), + ok = get_start_type(#st{local = 1}), global:send(st_type, kill), @@ -227,96 +230,96 @@ failover_comp(doc) -> failover_comp(Conf) when is_list(Conf) -> %% start a help process to check the start type StPid = spawn_link(?MODULE, start_type, []), - ?line yes = global:register_name(st_type, StPid), + yes = global:register_name(st_type, StPid), NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config(NodeNames)), WithSyncTime = config_fun(config(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), + {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], - ?line wait_for_ready_net(), + wait_for_ready_net(), % Start app1 and make sure cp1 starts it - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app1, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app1, Cp1)), + false = is_started(app1, Cp2), + ok = get_start_type(#st{normal = 3}), % Stop cp1 and make sure cp2 starts app1 stop_node_nice(Cp1), - ?line ?UNTIL(is_started(app1, Cp2)), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app1, Cp2)), + ok = get_start_type(#st{normal = 3}), % Restart cp1 and make sure it restarts app1 - ?line {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp1_2, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cp1_2)), - ?line ok = rpc:call(Cp1_2, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1_2)), - ?line ?UNTIL(not is_started(app1, Cp2)), - ?line ok = get_start_type(#st{takeover = 3}), + {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), + global:sync(), + ok = rpc:call(Cp1_2, application, load, [app1()]), + ?UNTIL(is_loaded(app1, Cp1_2)), + ok = rpc:call(Cp1_2, application, start, [app1, permanent]), + ?UNTIL(is_started(app1, Cp1_2)), + ?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) - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1_2, Cp2, Cp3], application, load, [app3()]), - ?line ?UNTIL(is_loaded(app3, [Cp1_2, Cp2, Cp3])), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app3, [Cp1_2, Cp2, Cp3])), + {[ok,ok,ok],[]} = rpc:multicall([Cp1_2, Cp2, Cp3], application, start,[app3,permanent]), - ?line ?UNTIL(is_started(app3, Cp2)), - ?line false = is_started(app3, Cp1), - ?line false = is_started(app3, Cp3), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app3, Cp2)), + false = is_started(app3, Cp1), + false = is_started(app3, Cp3), + ok = get_start_type(#st{normal = 3}), % Stop cp2 and make sure cp1 starts app3 stop_node_nice(Cp2), - ?line ?UNTIL(is_started(app3, Cp1_2)), - ?line ok = get_start_type(#st{normal = 3}), + ?UNTIL(is_started(app3, Cp1_2)), + ok = get_start_type(#st{normal = 3}), % Stop cp1 and make sure cp3 starts app3 stop_node_nice(Cp1_2), - ?line ?UNTIL(is_started(app3, Cp3)), - ?line ok = get_start_type(#st{normal = 6}), + ?UNTIL(is_started(app3, Cp3)), + ok = get_start_type(#st{normal = 6}), % Restart cp2 and make sure it restarts app3 - ?line {ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp2_2, application, load, [app3()]), - ?line ?UNTIL(is_loaded(app3, Cp2_2)), - ?line ok = rpc:call(Cp2_2, application, start, [app3, permanent]), - ?line ?UNTIL(is_started(app3, Cp2_2)), - ?line ?UNTIL(not is_started(app3, Cp3)), - ?line ok = get_start_type(#st{takeover = 3}), + {ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf), + global:sync(), + ok = rpc:call(Cp2_2, application, load, [app3()]), + ?UNTIL(is_loaded(app3, Cp2_2)), + ok = rpc:call(Cp2_2, application, start, [app3, permanent]), + ?UNTIL(is_started(app3, Cp2_2)), + ?UNTIL(not is_started(app3, Cp3)), + ok = get_start_type(#st{takeover = 3}), % Restart cp1 and make sure it doesn't restart app3 - ?line {ok, Cp1_3} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp1_3, application, load, [app3()]), - ?line true = is_loaded(app3, Cp1_3), - ?line ok = rpc:call(Cp1_3, application, start, [app3, permanent]), + {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), - ?line false = is_started(app3, Cp1_3), - ?line true = is_started(app3, Cp2_2), + false = is_started(app3, Cp1_3), + true = is_started(app3, Cp2_2), % Force takeover to cp1 - ?line ok = rpc:call(Cp1_3, application, takeover, [app3, permanent]), - ?line ?UNTIL(is_started(app3, Cp1_3)), - ?line ?UNTIL(not is_started(app3, Cp2_2)), - ?line ok = get_start_type(#st{takeover = 3}), + ok = rpc:call(Cp1_3, application, takeover, [app3, permanent]), + ?UNTIL(is_started(app3, Cp1_3)), + ?UNTIL(not is_started(app3, Cp2_2)), + ok = get_start_type(#st{takeover = 3}), %% Kill one child process and see that it is started with type local PP = global:whereis_name({ch,3}), exit(PP, kill), - ?line ok = get_start_type(#st{local = 1}), + ok = get_start_type(#st{local = 1}), global:send(st_type, kill), @@ -339,67 +342,67 @@ permissions(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config2(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), + {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], - ?line wait_for_ready_net(), + wait_for_ready_net(), % Start app1 and make sure cp1 starts it - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app1, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), + ?UNTIL(is_started(app1, Cp1)), + false = is_started(app1, Cp2), % Unpermit app1 on cp1, make sure cp2 starts it - ?line ok = rpc:call(Cp1, application, permit, [app1, false]), - ?line false = is_started(app1, Cp1), - ?line true = is_started(app1, Cp2), + 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 - ?line ok = rpc:call(Cp2, application, permit, [app1, false]), - ?line false = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), - ?line true = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp2, application, permit, [app1, true]), - ?line false = is_started(app1, Cp1), - ?line false = is_started(app1, Cp3), - ?line true = is_started(app1, Cp2), + 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 - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app3()]), - ?line ?UNTIL(is_loaded(app3, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app3, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app3, permanent]), test_server:sleep(1000), - ?line false = is_started(app3, Cp1), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + false = is_started(app3, Cp1), + false = is_started(app3, Cp2), + false = is_started(app3, Cp3), % Permit app3 on Cp3 - ?line ok = rpc:call(Cp3, application, permit, [app3, true]), - ?line true = is_started(app3, Cp3), + ok = rpc:call(Cp3, application, permit, [app3, true]), + true = is_started(app3, Cp3), % Permit app3 on Cp2, make sure it starts it - ?line ok = rpc:call(Cp2, application, permit, [app3, true]), - ?line true = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app3, true]), - ?line false = is_started(app3, Cp1), - ?line true = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + 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_node_nice(Cp2), - ?line ?UNTIL(is_started(app3, Cp1)), + ?UNTIL(is_started(app3, Cp1)), stop_node_nice(Cp1), stop_node_nice(Cp3), @@ -418,25 +421,25 @@ load(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config3(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), + {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], - ?line wait_for_ready_net(), + wait_for_ready_net(), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1(), d1(NodeNames)]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app1, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + ?UNTIL(is_started(app1, Cp1)), + false = is_started(app1, Cp2), + false = is_started(app1, Cp3), % Load app1 with different specs and make sure we get an error - ?line {[{error,_},{error,_}],[]} = + {[{error,_},{error,_}],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1(), d1(NodeNames)]), - ?line {error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]), + {error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]), stop_node_nice(Cp1), stop_node_nice(Cp2), @@ -455,24 +458,24 @@ load_use_cache(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config3(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_with_cache(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_with_cache(Ncp2, NoSyncTime, Conf), - ?line {ok, Cp3} = start_node_with_cache(Ncp3, WithSyncTime, Conf), + {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), Cps = [Cp1, Cp2, Cp3], - ?line wait_for_ready_net(), + wait_for_ready_net(), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1(), d1(NodeNames)]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app1, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), + ?UNTIL(is_started(app1, Cp1)), + false = is_started(app1, Cp2), % Load app1 with different specs and make sure we get an error - ?line {[{error,_},{error,_}],[]} = + {[{error,_},{error,_}],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1(), d1(NodeNames)]), - ?line {error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]), + {error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]), stop_node_nice(Cp1), stop_node_nice(Cp2), @@ -489,57 +492,57 @@ start_phases(doc) -> start_phases(Conf) when is_list(Conf) -> %% start a help process to check the start type SpPid = spawn_link(?MODULE, start_phase, []), - ?line yes = global:register_name(start_phase, SpPid), + yes = global:register_name(start_phase, SpPid), NodeNames = [Ncp1, _Ncp2, _Ncp3] = node_names([cp1, cp2, cp3], Conf), WithSyncTime = config_fun(config_sf(NodeNames)), - ?line {ok, Cp1} = start_node_config_sf(Ncp1, WithSyncTime, Conf), - ?line wait_for_ready_net(), + {ok, Cp1} = start_node_config_sf(Ncp1, WithSyncTime, Conf), + wait_for_ready_net(), %%============================= %%Example 1 in the user's guide %%============================= - ?line ok = rpc:call(Cp1, application, load, [myApp, + ok = rpc:call(Cp1, application, load, [myApp, d_any3(myApp, NodeNames)]), - ?line ?UNTIL(is_loaded(myApp, Cp1)), - ?line ok = rpc:call(Cp1, application, start, [myApp, permanent]), - ?line ?UNTIL(is_started(myApp, Cp1)), - ?line ok = get_start_phase({sp, 0, 1, 0, 0, 1}), - ?line ok = rpc:call(Cp1, application, stop, [myApp]), + ?UNTIL(is_loaded(myApp, Cp1)), + ok = rpc:call(Cp1, application, start, [myApp, permanent]), + ?UNTIL(is_started(myApp, Cp1)), + ok = get_start_phase({sp, 0, 1, 0, 0, 1}), + ok = rpc:call(Cp1, application, stop, [myApp]), %%============================= %%Example 2 in the user's guide %%============================= - ?line ok = rpc:call(Cp1, application, load, [topApp, + ok = rpc:call(Cp1, application, load, [topApp, d_any3(topApp, NodeNames)]), - ?line ?UNTIL(is_loaded(topApp, Cp1)), - ?line ok = rpc:call(Cp1, application, start, [topApp, permanent]), - ?line ?UNTIL(is_started(topApp, Cp1)), - ?line ok = get_start_phase({sp, 0, 1, 0, 0, 1}), - ?line ok = rpc:call(Cp1, application, stop, [topApp]), + ?UNTIL(is_loaded(topApp, Cp1)), + ok = rpc:call(Cp1, application, start, [topApp, permanent]), + ?UNTIL(is_started(topApp, Cp1)), + ok = get_start_phase({sp, 0, 1, 0, 0, 1}), + ok = rpc:call(Cp1, application, stop, [topApp]), %%============================= %%Example 3 in the user's guide %%============================= - ?line ok = rpc:call(Cp1, application, load, [topApp2, + ok = rpc:call(Cp1, application, load, [topApp2, d_any3(topApp2, NodeNames)]), - ?line ?UNTIL(is_loaded(topApp2, Cp1)), - ?line ok = rpc:call(Cp1, application, start, [topApp2, permanent]), - ?line ?UNTIL(is_started(topApp2, Cp1)), - ?line ok = get_start_phase({sp, 0, 2, 0, 0, 3}), - ?line ok = rpc:call(Cp1, application, stop, [topApp2]), + ?UNTIL(is_loaded(topApp2, Cp1)), + ok = rpc:call(Cp1, application, start, [topApp2, permanent]), + ?UNTIL(is_started(topApp2, Cp1)), + ok = get_start_phase({sp, 0, 2, 0, 0, 3}), + ok = rpc:call(Cp1, application, stop, [topApp2]), %%============================= %%Example 4 in the user's guide %%============================= - ?line ok = rpc:call(Cp1, application, load, [topApp3, + ok = rpc:call(Cp1, application, load, [topApp3, d_any3(topApp3, NodeNames)]), - ?line ?UNTIL(is_loaded(topApp3, Cp1)), - ?line ok = rpc:call(Cp1, application, start, [topApp3, permanent]), - ?line ?UNTIL(is_started(topApp3, Cp1)), - ?line ok = get_start_phase({sp, 1, 3, 3, 2, 4}), - ?line ok = rpc:call(Cp1, application, stop, [topApp3]), + ?UNTIL(is_loaded(topApp3, Cp1)), + ok = rpc:call(Cp1, application, start, [topApp3, permanent]), + ?UNTIL(is_started(topApp3, Cp1)), + ok = get_start_phase({sp, 1, 3, 3, 2, 4}), + ok = rpc:call(Cp1, application, stop, [topApp3]), global:send(start_phase, kill), @@ -554,101 +557,101 @@ script_start(suite) -> []; script_start(Conf) when is_list(Conf) -> %% start a help process to check the start type StPid = spawn_link(?MODULE, start_type, []), - ?line yes = global:register_name(st_type, StPid), + yes = global:register_name(st_type, StPid), % Create the .app files and the boot script - ?line ok = create_app(), - ?line {{KernelVer,StdlibVer}, _} = create_script("latest"), - ?line case is_real_system(KernelVer, StdlibVer) of + ok = create_app(), + {{KernelVer,StdlibVer}, _} = create_script("latest"), + case is_real_system(KernelVer, StdlibVer) of true -> Options = []; false -> Options = [local] end, - ?line ok = systools:make_script("latest", Options), + ok = systools:make_script("latest", Options), NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config_fo(NodeNames)), WithSyncTime = config_fun(config_fo(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), - ?line {ok, Cp2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest), - ?line {ok, Cp3} = start_node_boot_config(Ncp3, WithSyncTime, Conf, latest), - ?line wait_for_ready_net(), + {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), + wait_for_ready_net(), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line ?UNTIL(is_started(app2, Cp1)), - ?line ?UNTIL(is_started(app_sp, Cp1)), - ?line false = is_started(app1, Cp2), - ?line ok = get_start_type(#st{normal = 9}), + ?UNTIL(is_started(app1, Cp1)), + ?UNTIL(is_started(app2, Cp1)), + ?UNTIL(is_started(app_sp, Cp1)), + 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_node_nice(Cp1), - ?line ?UNTIL(is_started(app1, Cp2)), - ?line ?UNTIL(is_started(app2, Cp2)), - ?line ?UNTIL(is_started(app_sp, Cp2)), - ?line ok = get_start_type(#st{normal = 6, failover = 3}), + ?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 - ?line {ok, Cp1_2} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), - ?line global:sync(), - ?line ?UNTIL(is_started(app1, Cp1_2)), - ?line false = is_started(app1, Cp2), - ?line ?UNTIL(is_started(app2, Cp1_2)), - ?line true = is_started(app_sp, Cp2), - ?line ?UNTIL(not is_started(app1, Cp2)), - ?line ?UNTIL(not is_started(app2, Cp2)), - ?line ok = get_start_type(#st{takeover = 6}), + {ok, Cp1_2} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), + global:sync(), + ?UNTIL(is_started(app1, Cp1_2)), + false = is_started(app1, Cp2), + ?UNTIL(is_started(app2, Cp1_2)), + true = is_started(app_sp, Cp2), + ?UNTIL(not is_started(app1, Cp2)), + ?UNTIL(not is_started(app2, Cp2)), + ok = get_start_type(#st{takeover = 6}), % Stop cp2 and make sure cp1 starts app_sp. - ?line false = is_started(app_sp, Cp1_2), + false = is_started(app_sp, Cp1_2), stop_node_nice(Cp2), - ?line ?UNTIL(is_started(app_sp, Cp1_2)), - ?line ok = get_start_type(#st{failover = 3}), + ?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_node_nice(Cp1_2), - ?line ?UNTIL(is_started(app_sp, Cp3)), - ?line ?UNTIL(is_started(app1, Cp3)), - ?line ?UNTIL(is_started(app2, Cp3)), - ?line ok = get_start_type(#st{normal = 6, failover = 3}), + ?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 - ?line {ok, Cp2_2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest), - ?line global:sync(), - ?line ?UNTIL(is_started(app_sp, Cp2_2)), - ?line ?UNTIL(is_started(app1, Cp2_2)), - ?line ?UNTIL(is_started(app2, Cp2_2)), - ?line ?UNTIL(not is_started(app_sp, Cp3)), - ?line ?UNTIL(not is_started(app1, Cp3)), - ?line ?UNTIL(not is_started(app2, Cp3)), - ?line ok = get_start_type(#st{takeover = 9}), + {ok, Cp2_2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest), + global:sync(), + ?UNTIL(is_started(app_sp, Cp2_2)), + ?UNTIL(is_started(app1, Cp2_2)), + ?UNTIL(is_started(app2, Cp2_2)), + ?UNTIL(not is_started(app_sp, Cp3)), + ?UNTIL(not is_started(app1, Cp3)), + ?UNTIL(not is_started(app2, Cp3)), + ok = get_start_type(#st{takeover = 9}), % Restart cp1 and make sure it takesover app1, app2 - ?line {ok, Cp1_3} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), - ?line global:sync(), - ?line ?UNTIL(is_started(app1, Cp1_3)), - ?line ?UNTIL(is_started(app2, Cp1_3)), - ?line false = is_started(app_sp, Cp1_3), - ?line true = is_started(app_sp, Cp2_2), - ?line ?UNTIL(not is_started(app1, Cp2_2)), - ?line ?UNTIL(not is_started(app2, Cp2_2)), - ?line ok = get_start_type(#st{takeover = 6}), + {ok, Cp1_3} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest), + global:sync(), + ?UNTIL(is_started(app1, Cp1_3)), + ?UNTIL(is_started(app2, Cp1_3)), + false = is_started(app_sp, Cp1_3), + true = is_started(app_sp, Cp2_2), + ?UNTIL(not is_started(app1, Cp2_2)), + ?UNTIL(not is_started(app2, Cp2_2)), + ok = get_start_type(#st{takeover = 6}), % Force takeover to cp1 - ?line ok = rpc:call(Cp1_3, application, takeover, [app_sp, permanent]), - ?line ?UNTIL(is_started(app_sp, Cp1_3)), - ?line ?UNTIL(not is_started(app_sp, Cp2_2)), - ?line ok = get_start_type(#st{takeover = 3}), + 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)), + ok = get_start_type(#st{takeover = 3}), %% Kill one child process and see that it is started with type local PP = global:whereis_name({ch,3}), exit(PP, kill), - ?line ok = get_start_type(#st{local = 1}), + ok = get_start_type(#st{local = 1}), global:send(st_type, kill), @@ -656,9 +659,9 @@ script_start(Conf) when is_list(Conf) -> stop_node_nice(Cp2_2), stop_node_nice(Cp3), - ?line ok = file:delete("latest.boot"), - ?line ok = file:delete("latest.rel"), - ?line ok = file:delete("latest.script"), + ok = file:delete("latest.boot"), + ok = file:delete("latest.rel"), + ok = file:delete("latest.script"), ok. @@ -672,119 +675,119 @@ permit_false_start_local(Conf) when is_list(Conf) -> % Test [cp1, cp2, cp3] [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line {ok, Cp2} = start_node(Ncp2, Config), - ?line {ok, Cp3} = start_node(Ncp3, Config), - ?line wait_for_ready_net(), + {ok, Cp1} = start_node(Ncp1, Config), + {ok, Cp2} = start_node(Ncp2, Config), + {ok, Cp3} = start_node(Ncp3, Config), + wait_for_ready_net(), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, load, [app1()]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, start, [app1, permanent]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, load, [app2()]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, start, [app2, permanent]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, load, [app3()]), test_server:sleep(1000), - ?line false = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + false = is_started(app1, Cp1), + false = is_started(app1, Cp2), + false = is_started(app1, Cp3), %Permit a not started application - ?line ok = rpc:call(Cp1, application, permit, [app3, true]), + ok = rpc:call(Cp1, application, permit, [app3, true]), test_server:sleep(1000), - ?line false = is_started(app3, Cp1), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + false = is_started(app3, Cp1), + false = is_started(app3, Cp2), + false = is_started(app3, Cp3), %Permit a not loaded application - ?line {error,{not_loaded,app_notloaded}} = + {error,{not_loaded,app_notloaded}} = rpc:call(Cp1, application, permit, [app_notloaded, true]), test_server:sleep(1000), - ?line false = is_started(app_notloaded, Cp1), - ?line false = is_started(app_notloaded, Cp2), - ?line false = is_started(app_notloaded, Cp3), + false = is_started(app_notloaded, Cp1), + false = is_started(app_notloaded, Cp2), + false = is_started(app_notloaded, Cp3), %Unpermit a not started application - ?line ok = rpc:call(Cp1, application, permit, [app3, false]), + ok = rpc:call(Cp1, application, permit, [app3, false]), test_server:sleep(1000), - ?line false = is_started(app3, Cp1), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + false = is_started(app3, Cp1), + false = is_started(app3, Cp2), + false = is_started(app3, Cp3), %Unpermit a not loaded application - ?line {error,{not_loaded,app_notloaded}} = + {error,{not_loaded,app_notloaded}} = rpc:call(Cp1, application, permit, [app_notloaded, false]), test_server:sleep(1000), - ?line false = is_started(app_notloaded, Cp1), - ?line false = is_started(app_notloaded, Cp2), - ?line false = is_started(app_notloaded, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, true]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, true]), + ok = rpc:call(Cp1, application, permit, [app1, true]), test_server:sleep(1000), - ?line true = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app2, true]), - ?line ?UNTIL(is_started(app2, Cp1)), - ?line false = is_started(app2, Cp2), - ?line false = is_started(app2, Cp3), + 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 - ?line ok = rpc:call(Cp2, application, permit, [app1, true]), - ?line ?UNTIL(is_started(app1, Cp2)), - ?line true = is_started(app1, Cp1), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, false]), - ?line ?UNTIL(false =:= is_started(app1, Cp1)), - ?line true = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, false]), + ok = rpc:call(Cp1, application, permit, [app1, false]), test_server:sleep(1000), - ?line false = is_started(app1, Cp1), - ?line true = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, true]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line true = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, false]), - ?line ?UNTIL(false =:= is_started(app1, Cp1)), - ?line true = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp2, application, permit, [app1, false]), + ok = rpc:call(Cp2, application, permit, [app1, false]), test_server:sleep(1000), - ?line ?UNTIL(false =:= is_started(app1, Cp2)), - ?line false = is_started(app1, Cp1), - ?line false = is_started(app1, Cp3), + ?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 - ?line ok = rpc:call(Cp1, application, permit, [app2, false]), - ?line ?UNTIL(false =:= is_started(app2, Cp2)), - ?line false = is_started(app2, Cp1), - ?line false = is_started(app2, Cp3), + ok = rpc:call(Cp1, application, permit, [app2, false]), + ?UNTIL(false =:= is_started(app2, Cp2)), + false = is_started(app2, Cp1), + false = is_started(app2, Cp3), stop_node_nice(Cp1), stop_node_nice(Cp2), @@ -802,125 +805,125 @@ permit_false_start_dist(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config_perm2(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf), - ?line {ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf), + {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], - ?line wait_for_ready_net(), + wait_for_ready_net(), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app1, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app1, permanent]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app2()]), test_server:sleep(1000), - ?line false = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + false = is_started(app1, Cp1), + false = is_started(app1, Cp2), + false = is_started(app1, Cp3), %Permit a not started application - ?line ok = rpc:call(Cp1, application, permit, [app2, true]), + ok = rpc:call(Cp1, application, permit, [app2, true]), test_server:sleep(1000), - ?line false = is_started(app2, Cp1), - ?line false = is_started(app2, Cp2), - ?line false = is_started(app2, Cp3), + false = is_started(app2, Cp1), + false = is_started(app2, Cp2), + false = is_started(app2, Cp3), %Permit a not loaded application - ?line {error,{not_loaded,app3}} = + {error,{not_loaded,app3}} = rpc:call(Cp1, application, permit, [app3, true]), test_server:sleep(1000), - ?line false = is_started(app3, Cp1), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + false = is_started(app3, Cp1), + false = is_started(app3, Cp2), + false = is_started(app3, Cp3), %Unpermit a not started application - ?line ok = rpc:call(Cp1, application, permit, [app2, false]), - ?line {[ok,ok,ok],[]} = + ok = rpc:call(Cp1, application, permit, [app2, false]), + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application, start, [app2, permanent]), test_server:sleep(1000), - ?line false = is_started(app2, Cp1), - ?line false = is_started(app2, Cp2), - ?line false = is_started(app2, Cp3), + false = is_started(app2, Cp1), + false = is_started(app2, Cp2), + false = is_started(app2, Cp3), %Unpermit a not loaded application - ?line {error,{not_loaded,app3}} = + {error,{not_loaded,app3}} = rpc:call(Cp1, application, permit, [app3, false]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, load, [app3()]), - ?line ?UNTIL(is_loaded(app3, Cps)), - ?line {[ok,ok,ok],[]} = + ?UNTIL(is_loaded(app3, Cps)), + {[ok,ok,ok],[]} = rpc:multicall(Cps, application, start, [app3, permanent]), test_server:sleep(1000), - ?line false = is_started(app3, Cp1), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, true]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app1, true]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 - ?line ok = rpc:call(Cp1, application, permit, [app2, true]), - ?line ?UNTIL(is_started(app2, Cp1)), - ?line false = is_started(app2, Cp2), - ?line false = is_started(app2, Cp3), + 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 - ?line ok = rpc:call(Cp2, application, permit, [app1, true]), + ok = rpc:call(Cp2, application, permit, [app1, true]), test_server:sleep(1000), - ?line true = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), - ?line false = is_started(app1, Cp3), + 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 stop_node_nice(Cp1), - ?line ?UNTIL(is_started(app1, Cp2)), - ?line false = is_started(app2, Cp2), + ?UNTIL(is_started(app1, Cp2)), + false = is_started(app2, Cp2), % Restart CP1 again, check nothing is running on it - ?line {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line global:sync(), - ?line ok = rpc:call(Cp1_2, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cp1_2)), - ?line ok = rpc:call(Cp1_2, application, start, [app1, permanent]), - ?line ok = rpc:call(Cp1_2, application, load, [app2()]), - ?line ?UNTIL(is_loaded(app2, Cp1_2)), - ?line ok = rpc:call(Cp1_2, application, start, [app2, permanent]), - ?line ok = rpc:call(Cp1_2, application, load, [app3()]), - ?line ?UNTIL(is_loaded(app3, Cp1_2)), - ?line ok = rpc:call(Cp1_2, application, start, [app3, permanent]), - ?line false = is_started(app1, Cp1_2), - ?line false = is_started(app2, Cp1_2), + {ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf), + global:sync(), + ok = rpc:call(Cp1_2, application, load, [app1()]), + ?UNTIL(is_loaded(app1, Cp1_2)), + ok = rpc:call(Cp1_2, application, start, [app1, permanent]), + ok = rpc:call(Cp1_2, application, load, [app2()]), + ?UNTIL(is_loaded(app2, Cp1_2)), + ok = rpc:call(Cp1_2, application, start, [app2, permanent]), + ok = rpc:call(Cp1_2, application, load, [app3()]), + ?UNTIL(is_loaded(app3, Cp1_2)), + ok = rpc:call(Cp1_2, application, start, [app3, permanent]), + false = is_started(app1, Cp1_2), + false = is_started(app2, Cp1_2), % Permit app3 on CP3 and make sure it is started - ?line ok = rpc:call(Cp3, application, permit, [app3, true]), - ?line ?UNTIL(is_started(app3, Cp3)), - ?line false = is_started(app3, Cp1_2), - ?line false = is_started(app3, Cp2), + 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 - ?line ok = rpc:call(Cp1_2, application, permit, [app3, true]), - ?line ?UNTIL(is_started(app3, Cp1_2)), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, 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 - ?line ok = rpc:call(Cp3, application, permit, [app3, false]), - ?line ok = rpc:call(Cp1_2, application, permit, [app3, false]), - ?line ?UNTIL(false =:= is_started(app3, Cp1_2)), - ?line false = is_started(app3, Cp2), - ?line false = is_started(app3, Cp3), + ok = rpc:call(Cp3, application, permit, [app3, false]), + ok = rpc:call(Cp1_2, application, permit, [app3, false]), + ?UNTIL(false =:= is_started(app3, Cp1_2)), + false = is_started(app3, Cp2), + false = is_started(app3, Cp3), stop_node_nice(Cp1_2), stop_node_nice(Cp2), @@ -937,23 +940,45 @@ nodedown_start(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config4(NodeNames)), % Test [cp1, cp2] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), - ?line wait_for_ready_net(), + {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 - ?line {[ok,ok],[]} = + {[ok,ok],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1()]), - ?line _ = rpc:cast(Cp2, application, start, [app1, permanent]), + _ = rpc:cast(Cp2, application, start, [app1, permanent]), test_server:sleep(1000), % Crash CP1 and make sure app1 is started on CP2 stop_node_nice(Cp1), - ?line ?UNTIL(is_started(app1, Cp2)), + ?UNTIL(is_started(app1, Cp2)), stop_node_nice(Cp2), ok. + +ensure_started(suite) -> []; +ensure_started(doc) -> ["Test application:ensure_started/1."]; +ensure_started(Conf) -> + + {ok, Fd} = file:open("app1.app", [write]), + w_app1(Fd), + file:close(Fd), + + ok = application:ensure_started(app1), + ok = application:ensure_started(app1), + {error, {already_started, app1}} = application:start(app1), + ok = application:stop(app1), + {error,{"no such file or directory", _ }} = application:ensure_started(hopefully_not_an_existing_app_file), + + ok = application:ensure_started(app1, permanent), + ok = application:ensure_started(app1, permanent), + ok = application:stop(app1), + ok = application:unload(app1), + ok. + + %%%----------------------------------------------------------------- %%% Testing of reported bugs and other tickets. %%%----------------------------------------------------------------- @@ -970,9 +995,9 @@ otp_1586(Conf) when is_list(Conf) -> {ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]), w_app5(Fd), file:close(Fd), - ?line code:add_patha(Dir), - ?line ok = application:load(app4()), - ?line ok = application:unload(app4), + code:add_patha(Dir), + ok = application:load(app4()), + ok = application:unload(app4), ok. %%----------------------------------------------------------------- @@ -989,24 +1014,24 @@ otp_2078(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config4(NodeNames)), % Test [cp1, cp2] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), + {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), + {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), Cps = [Cp1, Cp2], - ?line wait_for_ready_net(), + wait_for_ready_net(), % Start app1 and make sure cp1 starts it - ?line {[ok,ok],[]} = + {[ok,ok],[]} = rpc:multicall(Cps, application, load, [app1()]), - ?line ?UNTIL(is_loaded(app1, Cps)), - ?line ok = rpc:call(Cp1, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), + ?UNTIL(is_loaded(app1, Cps)), + ok = rpc:call(Cp1, application, start, [app1, permanent]), + ?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) - ?line ok = rpc:call(Cp2, application, start, [app1, permanent]), - ?line true = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), + ok = rpc:call(Cp2, application, start, [app1, permanent]), + true = is_started(app1, Cp1), + false = is_started(app1, Cp2), stop_node_nice(Cp1), stop_node_nice(Cp2), @@ -1018,7 +1043,7 @@ otp_2012(doc) -> otp_2012(Conf) when is_list(Conf) -> %% start a help process to check the config change CcPid = spawn_link(?MODULE, conf_change, []), - ?line yes = global:register_name(conf_change, CcPid), + yes = global:register_name(conf_change, CcPid), % Write a .app file {ok, Fd} = file:open("app1.app", [write]), @@ -1029,19 +1054,19 @@ otp_2012(Conf) when is_list(Conf) -> file:close(Fd2), % Start app1 - ?line ok = application:load(app1()), - ?line ok = application:start(app1, permanent), + ok = application:load(app1()), + ok = application:start(app1, permanent), %% Read the current configuration parameters, and change them EnvBefore = application_controller:prep_config_change(), application_controller:test_change_apps([app1],[[{app1,[{new1, hi}, {new2, moi}]}]]), - ?line ok = application_controller:config_change(EnvBefore), - ?line ok = get_conf_change([{[], [{new1, hi}, {new2, moi}], []}]), + ok = application_controller:config_change(EnvBefore), + ok = get_conf_change([{[], [{new1, hi}, {new2, moi}], []}]), % Start app2 - ?line ok = application:load(app2()), - ?line ok = application:start(app2, permanent), + ok = application:load(app2()), + ok = application:start(app2, permanent), %% Read the current configuration parameters, and change them again EnvBefore2 = application_controller:prep_config_change(), @@ -1050,13 +1075,13 @@ otp_2012(Conf) when is_list(Conf) -> application_controller:test_change_apps([app2],[[{app2,[{new1, si}, {new2, no}]}]]), _EnvBefore22 = application_controller:prep_config_change(), - ?line ok = application_controller:config_change(EnvBefore2), + ok = application_controller:config_change(EnvBefore2), - ?line ok = get_conf_change([{[],[{new1,si},{new2,no}],[]}, + ok = get_conf_change([{[],[{new1,si},{new2,no}],[]}, {[{new1,hello}],[{new3,mors}],[new2]}]), - ?line ok = application:stop(app1), - ?line ok = application:stop(app2), + ok = application:stop(app1), + ok = application:stop(app2), ok. %%----------------------------------------------------------------- @@ -1067,24 +1092,24 @@ otp_2718(suite) -> []; otp_2718(doc) -> ["Test fail of transient app at start."]; otp_2718(Conf) when is_list(Conf) -> - ?line {ok, Cp1} = start_node_args(cp1, "-pa " ++ ?config(data_dir,Conf)), - ?line wait_for_ready_net(), + {ok, Cp1} = start_node_args(cp1, "-pa " ++ ?config(data_dir,Conf)), + wait_for_ready_net(), %% normal exit from the application - ?line ok = rpc:call(Cp1, application, load, [app_trans_normal()]), - ?line ?UNTIL(is_loaded(trans_normal, Cp1)), - ?line {error, {{'EXIT',normal},_}} = + ok = rpc:call(Cp1, application, load, [app_trans_normal()]), + ?UNTIL(is_loaded(trans_normal, Cp1)), + {error, {{'EXIT',normal},_}} = rpc:call(Cp1, application, start, [trans_normal, transient]), test_server:sleep(2000), - ?line false = is_started(trans_normal, Cp1), + false = is_started(trans_normal, Cp1), %% abnormal exit from the application - ?line ok = rpc:call(Cp1, application, load, [app_trans_abnormal()]), - ?line {error, {bad_return,{{trans_abnormal_sup,start,[normal,[]]}, + ok = rpc:call(Cp1, application, load, [app_trans_abnormal()]), + {error, {bad_return,{{trans_abnormal_sup,start,[normal,[]]}, {'EXIT',abnormal}}}} = rpc:call(Cp1, application, start, [trans_abnormal, transient]), test_server:sleep(3000), - ?line {badrpc,nodedown} = which_applications(Cp1), + {badrpc,nodedown} = which_applications(Cp1), ok. %%----------------------------------------------------------------- @@ -1100,65 +1125,65 @@ otp_2973(Conf) when is_list(Conf) -> w_app(Fd, app0()), file:close(Fd), - ?line Pid1 = spawn_link(?MODULE, init2973, []), - ?line Pid2 = spawn_link(?MODULE, init2973, []), + Pid1 = spawn_link(?MODULE, init2973, []), + Pid2 = spawn_link(?MODULE, init2973, []), - ?line Pid1 ! {start, self(), app0}, - ?line Pid2 ! {start, self(), app0}, + Pid1 ! {start, self(), app0}, + Pid2 ! {start, self(), app0}, - ?line {Res1, Res2} = receive + {Res1, Res2} = receive {Pid1, res, Res1x} -> receive {Pid2, res, Res2x} -> {Res1x, Res2x} after 2000 -> - ?line test_server:fail(timeout_pid2) + test_server:fail(timeout_pid2) end; {Pid2, res, Res2x} -> receive {Pid1, res, Res1x} -> {Res1x, Res2x} after 2000 -> - ?line test_server:fail(timeout_pid1) + test_server:fail(timeout_pid1) end end, %% Stop it. Inteferes with other global. - ?line ok = application:stop(app0), + ok = application:stop(app0), %% Test result. case {Res1, Res2} of {ok, ok} -> ok; _ -> - ?line Txt = io_lib:format("Illegal results from start: ~p ~p ", + Txt = io_lib:format("Illegal results from start: ~p ~p ", [Res1, Res2]), - ?line test_server:fail(lists:flatten(Txt)) + test_server:fail(lists:flatten(Txt)) end, % Write a .app file - ?line {ok, Fda} = file:open("app_start_error.app", [write]), - ?line w_app_start_error(Fda), - ?line file:close(Fda), + {ok, Fda} = file:open("app_start_error.app", [write]), + w_app_start_error(Fda), + file:close(Fda), - ?line Pid1 ! {start, self(), app_start_error}, - ?line Pid2 ! {start, self(), app_start_error}, + Pid1 ! {start, self(), app_start_error}, + Pid2 ! {start, self(), app_start_error}, - ?line {Res1a, Res2a} = receive + {Res1a, Res2a} = receive {Pid1, res, Res1y} -> receive {Pid2, res, Res2y} -> {Res1y, Res2y} after 2000 -> - ?line test_server:fail(timeout_pid2) + test_server:fail(timeout_pid2) end; {Pid2, res, Res2y} -> receive {Pid1, res, Res1y} -> {Res1y, Res2y} after 2000 -> - ?line test_server:fail(timeout_pid1) + test_server:fail(timeout_pid1) end end, @@ -1167,8 +1192,8 @@ otp_2973(Conf) when is_list(Conf) -> {error,{'start error',{app_start_error,start,[normal,[]]}}}} -> ok; _ -> - ?line Txta = io_lib:format("Illegal results from start ~p ~p ",[Res1a, Res2a]), - ?line test_server:fail(lists:flatten(Txta)) + Txta = io_lib:format("Illegal results from start ~p ~p ",[Res1a, Res2a]), + test_server:fail(lists:flatten(Txta)) end, ok. @@ -1190,34 +1215,34 @@ otp_3184(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config3184(NodeNames)), % Test [cp1, cp2] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), - ?line wait_for_ready_net(), + {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 - ?line {[ok,ok],[]} = + {[ok,ok],[]} = rpc:multicall([Cp1, Cp2], application, load, [app1()]), test_server:sleep(3000), - ?line false = is_started(app1, Cp1), - ?line false = is_started(app1, Cp2), + false = is_started(app1, Cp1), + false = is_started(app1, Cp2), % Start app1 on cp1 - ?line ok = rpc:call(Cp1, application, permit, [app1, true]), - ?line ok = rpc:call(Cp1, application, start, [app1, permanent]), - ?line ok = rpc:call(Cp2, application, start, [app1, permanent]), - ?line ?UNTIL(is_started(app1, Cp1)), - ?line false = is_started(app1, Cp2), + 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 - ?line X = rpc:call(Cp1, application_controller, info, []), - ?line {value, {running, Xrunning}} = lists:keysearch(running, 1, X), - ?line {value, Xapp1} = lists:keysearch(app1, 1, Xrunning), - ?line {app1, _Xpid} = Xapp1, + X = rpc:call(Cp1, application_controller, info, []), + {value, {running, Xrunning}} = lists:keysearch(running, 1, X), + {value, Xapp1} = lists:keysearch(app1, 1, Xrunning), + {app1, _Xpid} = Xapp1, - ?line Y = rpc:call(Cp2, application_controller, info, []), - ?line {value, {running, Yrunning}} = lists:keysearch(running, 1, Y), - ?line {value, Yapp1} = lists:keysearch(app1, 1, Yrunning), - ?line {app1, {distributed, Cp1}} = Yapp1, + Y = rpc:call(Cp2, application_controller, info, []), + {value, {running, Yrunning}} = lists:keysearch(running, 1, Y), + {value, Yapp1} = lists:keysearch(app1, 1, Yrunning), + {app1, {distributed, Cp1}} = Yapp1, stop_node_nice(Cp1), stop_node_nice(Cp2), @@ -1232,26 +1257,26 @@ otp_3002(doc) -> ["crash the node if permanent appl has illegal env parameter values."]; otp_3002(Conf) when is_list(Conf) -> % Create the boot script - ?line {{KernelVer,StdlibVer}, {LatestDir, LatestName}} = + {{KernelVer,StdlibVer}, {LatestDir, LatestName}} = create_script_3002("script_3002"), ?t:format(0, "LatestDir = ~p~n", [LatestDir]), ?t:format(0, "LatestName = ~p~n", [LatestName]), - ?line case is_real_system(KernelVer, StdlibVer) of + case is_real_system(KernelVer, StdlibVer) of true -> Options = []; false -> Options = [local] end, - ?line ok = systools:make_script("script_3002", Options), - ?line ok = systools:script2boot("script_3002"), + ok = systools:make_script("script_3002", Options), + ok = systools:script2boot("script_3002"), - ?line {error, timeout} = start_node_boot_3002(cp1, "script_3002"), + {error, timeout} = start_node_boot_3002(cp1, "script_3002"), - ?line ok = file:delete("script_3002.boot"), - ?line ok = file:delete("script_3002.rel"), - ?line ok = file:delete("script_3002.script"), + ok = file:delete("script_3002.boot"), + ok = file:delete("script_3002.rel"), + ok = file:delete("script_3002.script"), ok. %%----------------------------------------------------------------- @@ -1273,51 +1298,51 @@ otp_4066(Conf) when is_list(Conf) -> App1Nodes = {app1, AllNodes}, Dir = ?config(priv_dir,Conf), - ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), [write]), - ?line write_config(FdC, config_4066(AllNodes, 5000, [App1Nodes])), - ?line file:close(FdC), + {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 - ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]), - ?line w_app1(FdA12), - ?line file:close(FdA12), + {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]), + w_app1(FdA12), + file:close(FdA12), Args1 = "-pa " ++ Dir ++ " -config " ++ filename:join(Dir, "otp_4066"), Args2 = "-pa " ++ Dir ++ " -kernel start_dist_ac true", - ?line {ok, Cp2} = start_node_args(Ncp2, Args2), + {ok, Cp2} = start_node_args(Ncp2, Args2), %% Cp1 syncs with cp2 (which is known to be up). - ?line {ok, Cp1} = start_node_args(Ncp1, Args1), - ?line wait_for_ready_net(), + {ok, Cp1} = start_node_args(Ncp1, Args1), + wait_for_ready_net(), - ?line ok = rpc:call(Cp1, application, start, [app1]), - ?line wait_until_started(app1, [Cp1]), - ?line test_server:format("--- App1 started at Cp1 ---~n", []), - ?line print_dac_state(AllNodes), + ok = rpc:call(Cp1, application, start, [app1]), + wait_until_started(app1, [Cp1]), + test_server:format("--- App1 started at Cp1 ---~n", []), + print_dac_state(AllNodes), % Cp2 previously crashed on this stop - ?line ok = rpc:call(Cp1, application, stop, [app1]), - ?line wait_until_stopped(app1, [Cp1]), - ?line test_server:format("--- App1 stopped at Cp1 ---~n", []), - ?line print_dac_state(AllNodes), + ok = rpc:call(Cp1, application, stop, [app1]), + wait_until_stopped(app1, [Cp1]), + test_server:format("--- App1 stopped at Cp1 ---~n", []), + print_dac_state(AllNodes), - ?line ok = rpc:call(Cp1, application, start, [app1]), - ?line wait_until_started(app1, [Cp1]), - ?line test_server:format("--- App1 started at Cp1 ---~n", []), - ?line print_dac_state(AllNodes), + ok = rpc:call(Cp1, application, start, [app1]), + wait_until_started(app1, [Cp1]), + test_server:format("--- App1 started at Cp1 ---~n", []), + print_dac_state(AllNodes), - ?line ok = rpc:call(Cp2, application, load, [app1, App1Nodes]), - ?line ok = rpc:call(Cp2, application, start, [app1]), - ?line test_server:format("--- App1 started at Cp2 ---~n", []), - ?line 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", []), + print_dac_state(AllNodes), - ?line stop_node_nice(Cp1), - ?line wait_until_started(app1, [Cp2]), - ?line test_server:format("--- Cp1 crashed; failover to Cp2 ---~n", []), - ?line print_dac_state(Cp2), + stop_node_nice(Cp1), + wait_until_started(app1, [Cp2]), + test_server:format("--- Cp1 crashed; failover to Cp2 ---~n", []), + print_dac_state(Cp2), - ?line stop_node_nice(Cp2), + stop_node_nice(Cp2), ok. config_4066(SyncNodesOptional, SyncNodesTimeout, Distributed) -> @@ -1349,34 +1374,34 @@ otp_4227(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config_4227(NodeNames)), %% Test [cp1, cp2] - ?line {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), - ?line {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), + {ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf), + {ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf), Cps = [Cp1, Cp2], - ?line wait_for_ready_net(), + wait_for_ready_net(), %% Try to start app10 which should fail since app9 is not started - ?line {[ok,ok],[]} = + {[ok,ok],[]} = rpc:multicall(Cps, application, load, [app9()]), - ?line ?UNTIL(is_loaded(app9, Cps)), - ?line {[ok,ok],[]} = + ?UNTIL(is_loaded(app9, Cps)), + {[ok,ok],[]} = rpc:multicall(Cps, application, load, [app10_dep9()]), - ?line {error, {not_started, app9}} = + {error, {not_started, app9}} = rpc:call(Cp1, application, start, [app10]), %% Start app9 and brutally kill it, then try to start app10 - ?line ok = rpc:call(Cp1, application, start, [app9]), - ?line test_server:sleep(1000), - ?line Pid9 = rpc:call(Cp1, erlang, whereis, [ch_sup19]), - ?line true = erlang:is_pid(Pid9), - ?line true = erlang:exit(Pid9, kill), - ?line test_server:sleep(1000), + ok = rpc:call(Cp1, application, start, [app9]), + test_server:sleep(1000), + Pid9 = rpc:call(Cp1, erlang, whereis, [ch_sup19]), + true = erlang:is_pid(Pid9), + true = erlang:exit(Pid9, kill), + test_server:sleep(1000), %% This gave {error, no_report} before the patch - ?line {error, {not_running, app9}} = + {error, {not_running, app9}} = rpc:call(Cp1, application, start, [app10]), - ?line stop_node_nice(Cp1), - ?line stop_node_nice(Cp2), + stop_node_nice(Cp1), + stop_node_nice(Cp2), ok. config_4227([Ncp1, Ncp2]) -> @@ -1410,18 +1435,18 @@ otp_5363(Conf) when is_list(Conf) -> OldPath = code:get_path(), code:add_patha(?config(data_dir,Conf)), try - ?line ok = application:load(app_group_leader()), - ?line ok = application:start(group_leader), - ?line case whereis(nisse) of + ok = application:load(app_group_leader()), + ok = application:start(group_leader), + case whereis(nisse) of Pid when is_pid(Pid) -> - ?line Mref = erlang:monitor(process, Pid), - ?line ok = application:stop(group_leader), + Mref = erlang:monitor(process, Pid), + ok = application:stop(group_leader), receive {'DOWN',Mref,_,_,_} -> ok end, - ?line undefined = whereis(nisse); + undefined = whereis(nisse); Bad -> - ?line io:format("~p\n", [Bad]), + io:format("~p\n", [Bad]), ?t:fail() end after @@ -1448,25 +1473,25 @@ otp_5606(Conf) when is_list(Conf) -> Config = filename:join(Dir, "sys"), %% Test [cp1, cp2] - ?line {ok, Cp1} = start_node(Ncp1, Config), - ?line {ok, Cp2} = start_node(Ncp2, Config), + {ok, Cp1} = start_node(Ncp1, Config), + {ok, Cp2} = start_node(Ncp2, Config), Cps = [Cp1, Cp2], - ?line wait_for_ready_net(), + wait_for_ready_net(), %% Load app1 on both nodes - ?line {[ok, ok], []} = + {[ok, ok], []} = rpc:multicall(Cps, application, load, [app1()]), %% Attempt to start app1 from different processes simultaneously - ?line Pid11 = spawn_link(Cp1, ?MODULE, loop5606, [self()]), - ?line Pid12 = spawn_link(Cp1, ?MODULE, loop5606, [self()]), - ?line Pid13 = spawn_link(Cp1, ?MODULE, loop5606, [self()]), - ?line Pid2 = spawn_link(Cp2, ?MODULE, loop5606, [self()]), + Pid11 = spawn_link(Cp1, ?MODULE, loop5606, [self()]), + Pid12 = spawn_link(Cp1, ?MODULE, loop5606, [self()]), + Pid13 = spawn_link(Cp1, ?MODULE, loop5606, [self()]), + Pid2 = spawn_link(Cp2, ?MODULE, loop5606, [self()]), - ?line Pid2 ! start, - ?line Pid11 ! start, - ?line Pid12 ! start, - ?line Pid13 ! start, + Pid2 ! start, + Pid11 ! start, + Pid12 ! start, + Pid13 ! start, ResL = otp_5606_loop([]), @@ -1476,10 +1501,10 @@ 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]), - ?line test_server:fail(lists:flatten(Txt)) + test_server:fail(lists:flatten(Txt)) end, - ?line {error, {already_started, app1}} = + {error, {already_started, app1}} = rpc:call(Cp1, application, start, [app1]), stop_node_nice(Cp1), @@ -1491,7 +1516,7 @@ otp_5606_loop(ResL) when length(ResL)<4 -> {_Pid, Res} -> otp_5606_loop([Res|ResL]) after 5000 -> - ?line test_server:fail(timeout_waiting_for_res) + test_server:fail(timeout_waiting_for_res) end; otp_5606_loop(ResL) -> ResL. @@ -1503,6 +1528,15 @@ loop5606(Pid) -> Pid ! {self(), Res} end. +get_env(suite) -> []; +get_env(doc) -> + ["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), + undefined = application:get_env(kernel, error_logger_xyz), + default = application:get_env(kernel, error_logger_xyz, default), + ok. %%----------------------------------------------------------------- %% Should be started in a CC view with: @@ -1516,34 +1550,34 @@ get_key(Conf) when is_list(Conf) -> WithSyncTime = config_fun(config_inc(NodeNames)), % Test [cp1, cp2, cp3] - ?line {ok, Cp1} = start_node_config(Ncp1, WithSyncTime, Conf), + {ok, Cp1} = start_node_config(Ncp1, WithSyncTime, Conf), - ?line ok = rpc:call(Cp1, application, load, [appinc(), d3(NodeNames)]), - ?line ?UNTIL(is_loaded(appinc, Cp1)), - ?line ok = rpc:call(Cp1, application, start, [appinc, permanent]), - ?line ?UNTIL(is_started(appinc, Cp1)), + ok = rpc:call(Cp1, application, load, [appinc(), d3(NodeNames)]), + ?UNTIL(is_loaded(appinc, Cp1)), + ok = rpc:call(Cp1, application, start, [appinc, permanent]), + ?UNTIL(is_started(appinc, Cp1)), - ?line {ok, "Test of new app file, including appnew"} = + {ok, "Test of new app file, including appnew"} = rpc:call(Cp1, application, get_key, [appinc, description]), - ?line {ok, "CXC 138 ai"} = rpc:call(Cp1, application, get_key, [appinc ,id]), - ?line {ok, "2.0"} = rpc:call(Cp1, application, get_key, [appinc, vsn]), - ?line {ok, [kernel]} = rpc:call(Cp1, application, get_key, [appinc, applications]), - ?line {ok, [appinc1, appinc2]} = + {ok, "CXC 138 ai"} = rpc:call(Cp1, application, get_key, [appinc ,id]), + {ok, "2.0"} = rpc:call(Cp1, application, get_key, [appinc, vsn]), + {ok, [kernel]} = rpc:call(Cp1, application, get_key, [appinc, applications]), + {ok, [appinc1, appinc2]} = rpc:call(Cp1, application, get_key, [appinc, included_applications]), - ?line {ok, []} = rpc:call(Cp1, application, get_key, [appinc, registered]), - ?line {ok, [{init, [kalle]}, {takeover, []}, {go, [sune]}]} = + {ok, []} = rpc:call(Cp1, application, get_key, [appinc, registered]), + {ok, [{init, [kalle]}, {takeover, []}, {go, [sune]}]} = rpc:call(Cp1, application, get_key, [appinc, start_phases]), - ?line {ok, Env} = rpc:call(Cp1, application, get_key, [appinc ,env]), - ?line [{included_applications,[appinc1,appinc2]}, + {ok, Env} = rpc:call(Cp1, application, get_key, [appinc ,env]), + [{included_applications,[appinc1,appinc2]}, {own2,val2},{own_env1,value1}] = lists:sort(Env), - ?line {ok, []} = rpc:call(Cp1, application, get_key, [appinc, modules]), - ?line {ok, {application_starter, [ch_sup, {appinc, 41, 43}] }} = + {ok, []} = rpc:call(Cp1, application, get_key, [appinc, modules]), + {ok, {application_starter, [ch_sup, {appinc, 41, 43}] }} = rpc:call(Cp1, application, get_key, [appinc, mod]), - ?line {ok, infinity} = rpc:call(Cp1, application, get_key, [appinc, maxP]), - ?line {ok, infinity} = rpc:call(Cp1, application, get_key, [appinc, maxT]), - ?line undefined = rpc:call(Cp1, application, get_key, [appinc, very_unknown]), + {ok, infinity} = rpc:call(Cp1, application, get_key, [appinc, maxP]), + {ok, infinity} = rpc:call(Cp1, application, get_key, [appinc, maxT]), + undefined = rpc:call(Cp1, application, get_key, [appinc, very_unknown]), - ?line {ok, [{description, "Test of new app file, including appnew"}, + {ok, [{description, "Test of new app file, including appnew"}, {id, "CXC 138 ai"}, {vsn, "2.0"}, {modules, []}, @@ -1556,40 +1590,40 @@ get_key(Conf) when is_list(Conf) -> {mod, {application_starter, [ch_sup, {appinc, 41, 43}] }}, {start_phases, [{init, [kalle]}, {takeover, []}, {go, [sune]}]}]} = rpc:call(Cp1, application, get_all_key, [appinc]), - ?line [{included_applications,[appinc1,appinc2]}, + [{included_applications,[appinc1,appinc2]}, {own2,val2},{own_env1,value1}] = lists:sort(Env), - ?line {ok, "Test of new app file, including appnew"} = + {ok, "Test of new app file, including appnew"} = gen_server:call({global, {ch,41}}, {get_pid_key, description}), - ?line {ok, "CXC 138 ai"} = + {ok, "CXC 138 ai"} = gen_server:call({global, {ch,41}}, {get_pid_key, id}), - ?line {ok, "2.0"} = + {ok, "2.0"} = gen_server:call({global, {ch,41}}, {get_pid_key, vsn}), - ?line {ok, [kernel]} = + {ok, [kernel]} = gen_server:call({global, {ch,41}}, {get_pid_key, applications}), - ?line {ok, [appinc1, appinc2]} = + {ok, [appinc1, appinc2]} = gen_server:call({global, {ch,41}}, {get_pid_key, included_applications}), - ?line {ok, []} = + {ok, []} = gen_server:call({global, {ch,41}}, {get_pid_key, registered}), - ?line {ok, [{init, [kalle]}, {takeover, []}, {go, [sune]}]} = + {ok, [{init, [kalle]}, {takeover, []}, {go, [sune]}]} = gen_server:call({global, {ch,41}}, {get_pid_key, start_phases}), - ?line {ok, Env} = gen_server:call({global, {ch,41}}, {get_pid_key, env}), - ?line [{included_applications,[appinc1,appinc2]}, + {ok, Env} = gen_server:call({global, {ch,41}}, {get_pid_key, env}), + [{included_applications,[appinc1,appinc2]}, {own2,val2},{own_env1,value1}] = lists:sort(Env), - ?line {ok, []} = + {ok, []} = gen_server:call({global, {ch,41}}, {get_pid_key, modules}), - ?line {ok, {application_starter, [ch_sup, {appinc, 41, 43}] }} = + {ok, {application_starter, [ch_sup, {appinc, 41, 43}] }} = gen_server:call({global, {ch,41}}, {get_pid_key, mod}), - ?line {ok, infinity} = + {ok, infinity} = gen_server:call({global, {ch,41}}, {get_pid_key, maxP}), - ?line {ok, infinity} = + {ok, infinity} = gen_server:call({global, {ch,41}}, {get_pid_key, maxT}), - ?line undefined = + undefined = gen_server:call({global, {ch,41}}, {get_pid_key, very_unknown}), - ?line {ok, [{description, "Test of new app file, including appnew"}, + {ok, [{description, "Test of new app file, including appnew"}, {id, "CXC 138 ai"}, {vsn, "2.0"}, {modules, []}, @@ -1602,7 +1636,7 @@ get_key(Conf) when is_list(Conf) -> {mod, {application_starter, [ch_sup, {appinc, 41, 43}] }}, {start_phases, [{init, [kalle]}, {takeover, []}, {go, [sune]}]}]} = gen_server:call({global, {ch,41}}, get_pid_all_key), - ?line [{included_applications,[appinc1,appinc2]}, + [{included_applications,[appinc1,appinc2]}, {own2,val2},{own_env1,value1}] = lists:sort(Env), stop_node_nice(Cp1), @@ -1619,81 +1653,81 @@ distr_changed_tc1(Conf) when is_list(Conf) -> {OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {_Ncp1, _Ncp2, _Ncp3}, _Config2} = distr_changed_prep(Conf), - ?line NewDist = {distributed, [{app1, [Cp3]}, + NewDist = {distributed, [{app1, [Cp3]}, {app2, 5000, [Cp2]}, {app3, [Cp3, {Cp1, Cp2}]}, {app6, [Cp1, {Cp3, Cp2}]}, {app7, 1000, [Cp3]}, {app8, [Cp1, {Cp2, Cp3}]}]}, - ?line NewKernel = [{kernel, lists:keyreplace(distributed, 1, OldKernel, NewDist)}], - ?line ok = rpc:call(Cp1, application_controller, test_change_apps, + NewKernel = [{kernel, lists:keyreplace(distributed, 1, OldKernel, NewDist)}], + ok = rpc:call(Cp1, application_controller, test_change_apps, [[kernel], [NewKernel]]), - ?line ok = rpc:call(Cp2, application_controller, test_change_apps, + ok = rpc:call(Cp2, application_controller, test_change_apps, [[kernel], [NewKernel]]), - ?line ok = rpc:call(Cp3, application_controller, test_change_apps, + ok = rpc:call(Cp3, application_controller, test_change_apps, [[kernel], [NewKernel]]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application_controller, config_change, [OldEnv]), - ?line test_server:sleep(7000), + test_server:sleep(7000), - ?line DcInfo1 = rpc:call(Cp1, dist_ac, info, []), - ?line DcInfo2 = rpc:call(Cp2, dist_ac, info, []), - ?line DcInfo3 = rpc:call(Cp3, dist_ac, info, []), + DcInfo1 = rpc:call(Cp1, dist_ac, info, []), + DcInfo2 = rpc:call(Cp2, dist_ac, info, []), + DcInfo3 = rpc:call(Cp3, dist_ac, info, []), - ?line DcWa1 = which_applications(Cp1), - ?line DcWa2 = which_applications(Cp2), - ?line DcWa3 = which_applications(Cp3), + DcWa1 = which_applications(Cp1), + DcWa2 = which_applications(Cp2), + DcWa3 = which_applications(Cp3), - ?line Wa1 = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, + Wa1 = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, [], DcWa1), - ?line Wa2 = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, + Wa2 = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, [], DcWa2), - ?line Wa3 = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, + Wa3 = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, [], DcWa3), - ?line case lists:sort(Wa1) of + case lists:sort(Wa1) of [app1, app2, app3, kernel, stdlib] -> ok; EWa1 -> X1 = io_lib:format("distribution error: Cp1 ~p ",[EWa1]), - ?line test_server:fail(lists:flatten(X1)) + test_server:fail(lists:flatten(X1)) end, - ?line case lists:sort(Wa2) of + case lists:sort(Wa2) of [app6, app8, kernel, stdlib] -> ok; EWa2 -> X2 = io_lib:format("distribution error: Cp2 ~p ",[EWa2]), - ?line test_server:fail(lists:flatten(X2)) + test_server:fail(lists:flatten(X2)) end, - ?line case lists:sort(Wa3) of + case lists:sort(Wa3) of [app7, kernel, stdlib] -> ok; EWa3 -> X3 = io_lib:format("distribution error: Cp3 ~p ",[EWa3]), - ?line test_server:fail(lists:flatten(X3)) + test_server:fail(lists:flatten(X3)) end, - ?line DcInfo1n = rpc:call(Cp1, dist_ac, info, []), - ?line DcInfo2n = rpc:call(Cp2, dist_ac, info, []), - ?line DcInfo3n = rpc:call(Cp3, dist_ac, info, []), + DcInfo1n = rpc:call(Cp1, dist_ac, info, []), + DcInfo2n = rpc:call(Cp2, dist_ac, info, []), + DcInfo3n = rpc:call(Cp3, dist_ac, info, []), %% Added afterwards. Got rid of some warnings for unused variables. - ?line true = DcInfo1 =:= DcInfo1n, - ?line true = DcInfo2 =:= DcInfo2n, - ?line true = DcInfo3 =:= DcInfo3n, + true = DcInfo1 =:= DcInfo1n, + true = DcInfo2 =:= DcInfo2n, + true = DcInfo3 =:= DcInfo3n, stop_node_nice(Cp1), stop_node_nice(Cp2), stop_node_nice(Cp3), - ?line ok = file:delete("dc.boot"), - ?line ok = file:delete("dc.rel"), - ?line ok = file:delete("dc.script"), + ok = file:delete("dc.boot"), + ok = file:delete("dc.rel"), + ok = file:delete("dc.script"), ok. @@ -1705,103 +1739,103 @@ distr_changed_tc2(Conf) when is_list(Conf) -> {OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {Ncp1, _Ncp2, _Ncp3}, Config2} = distr_changed_prep(Conf), - ?line NewDist = {distributed, [{app1, [Cp3]}, + NewDist = {distributed, [{app1, [Cp3]}, {app2, 5000, [Cp2]}, {app3, [Cp3, {Cp1, Cp2}]}, {app6, [Cp1, {Cp3, Cp2}]}, {app7, 1000, [Cp3]}, {app8, [Cp1, {Cp2, Cp3}]}]}, - ?line NewKernel = [{kernel, lists:keyreplace(distributed, 1, OldKernel, NewDist)}], - ?line ok = rpc:call(Cp1, application_controller, test_change_apps, + NewKernel = [{kernel, lists:keyreplace(distributed, 1, OldKernel, NewDist)}], + ok = rpc:call(Cp1, application_controller, test_change_apps, [[kernel], [NewKernel]]), - ?line ok = rpc:call(Cp2, application_controller, test_change_apps, + ok = rpc:call(Cp2, application_controller, test_change_apps, [[kernel], [NewKernel]]), - ?line ok = rpc:call(Cp3, application_controller, test_change_apps, + ok = rpc:call(Cp3, application_controller, test_change_apps, [[kernel], [NewKernel]]), - ?line {[ok,ok,ok],[]} = + {[ok,ok,ok],[]} = rpc:multicall([Cp1, Cp2, Cp3], application_controller, config_change, [OldEnv]), - ?line test_server:sleep(4000), - ?line stop_node_nice(Cp1), - ?line test_server:sleep(10000), + test_server:sleep(4000), + stop_node_nice(Cp1), + test_server:sleep(10000), -% ?line _DcInfo1 = rpc:call(Cp1, dist_ac, info, []), - ?line _DcInfo2 = rpc:call(Cp2, dist_ac, info, []), - ?line _DcInfo3 = rpc:call(Cp3, dist_ac, info, []), +% _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]), -% ?line DcWa1 = which_applications(Cp1), - ?line DcWa2 = which_applications(Cp2), - ?line DcWa3 = which_applications(Cp3), +% DcWa1 = which_applications(Cp1), + DcWa2 = which_applications(Cp2), + DcWa3 = which_applications(Cp3), -% ?line Wa1 = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, +% Wa1 = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, % [], DcWa1), - ?line Wa2 = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, + Wa2 = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, [], DcWa2), - ?line Wa3 = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, + Wa3 = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, [], DcWa3), - ?line case lists:sort(Wa2) of + case lists:sort(Wa2) of [app2, app6, app8, kernel, stdlib] -> ok; EWa2 -> X2 = io_lib:format("distribution error: Cp2 ~p ",[EWa2]), - ?line test_server:fail(lists:flatten(X2)) + test_server:fail(lists:flatten(X2)) end, - ?line case lists:sort(Wa3) of + case lists:sort(Wa3) of [app1, app3, app7, kernel, stdlib] -> ok; EWa3 -> X3 = io_lib:format("distribution error: Cp3 ~p ",[EWa3]), - ?line test_server:fail(lists:flatten(X3)) + test_server:fail(lists:flatten(X3)) end, - ?line {ok, Cp1} = start_node_boot(Ncp1, Config2, dc), - ?line test_server:sleep(10000), + {ok, Cp1} = start_node_boot(Ncp1, Config2, dc), + test_server:sleep(10000), - ?line _DcInfo1rs = rpc:call(Cp1, dist_ac, info, []), - ?line _DcInfo2rs = rpc:call(Cp2, dist_ac, info, []), - ?line _DcInfo3rs = rpc:call(Cp3, dist_ac, info, []), + _DcInfo1rs = rpc:call(Cp1, dist_ac, info, []), + _DcInfo2rs = rpc:call(Cp2, dist_ac, info, []), + _DcInfo3rs = rpc:call(Cp3, dist_ac, info, []), - ?line DcWa1rs = which_applications(Cp1), - ?line DcWa2rs = which_applications(Cp2), - ?line DcWa3rs = which_applications(Cp3), + DcWa1rs = which_applications(Cp1), + DcWa2rs = which_applications(Cp2), + DcWa3rs = which_applications(Cp3), - ?line Wa1rs = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, + Wa1rs = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end, [], DcWa1rs), - ?line Wa2rs = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, + Wa2rs = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end, [], DcWa2rs), - ?line Wa3rs = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, + Wa3rs = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end, [], DcWa3rs), - ?line case lists:sort(Wa1rs) of + case lists:sort(Wa1rs) of [app6, app8, kernel, stdlib] -> ok; EWa1rs -> X1rs = io_lib:format("distribution error: Cp1 ~p ",[EWa1rs]), - ?line test_server:fail(lists:flatten(X1rs)) + test_server:fail(lists:flatten(X1rs)) end, - ?line case lists:sort(Wa2rs) of + case lists:sort(Wa2rs) of [app2, kernel, stdlib] -> ok; EWa2rs -> X2rs = io_lib:format("distribution error: Cp2 ~p ",[EWa2rs]), - ?line test_server:fail(lists:flatten(X2rs)) + test_server:fail(lists:flatten(X2rs)) end, - ?line case lists:sort(Wa3rs) of + case lists:sort(Wa3rs) of [app1, app3, app7, kernel, stdlib] -> ok; EWa3rs -> X3rs = io_lib:format("distribution error: Cp3 ~p ",[EWa3rs]), - ?line test_server:fail(lists:flatten(X3rs)) + test_server:fail(lists:flatten(X3rs)) end, @@ -1809,9 +1843,9 @@ distr_changed_tc2(Conf) when is_list(Conf) -> stop_node_nice(Cp2), stop_node_nice(Cp3), - ?line ok = file:delete("dc.boot"), - ?line ok = file:delete("dc.rel"), - ?line ok = file:delete("dc.script"), + ok = file:delete("dc.boot"), + ok = file:delete("dc.rel"), + ok = file:delete("dc.script"), ok. @@ -1827,36 +1861,36 @@ config_change(doc) -> config_change(Conf) when is_list(Conf) -> %% Change to data_dir - ?line {ok, CWD} = file:get_cwd(), - ?line DataDir = ?config(data_dir, Conf), - ?line ok = file:set_cwd(DataDir), + {ok, CWD} = file:get_cwd(), + DataDir = ?config(data_dir, Conf), + ok = file:set_cwd(DataDir), %% Find out application data from boot script - ?line Boot = filename:join([code:root_dir(), "bin", "start.boot"]), - ?line {ok, Bin} = file:read_file(Boot), - ?line Appls = get_appls(binary_to_term(Bin)), + Boot = filename:join([code:root_dir(), "bin", "start.boot"]), + {ok, Bin} = file:read_file(Boot), + Appls = get_appls(binary_to_term(Bin)), %% Simulate contents of "sys.config" - ?line Config = [{stdlib, [{par1,sys},{par2,sys}]}, + Config = [{stdlib, [{par1,sys},{par2,sys}]}, "t1", "t2.config", filename:join([DataDir, "subdir", "t3"]), {stdlib, [{par6,sys}]}], %% Order application_controller to update configuration - ?line ok = application_controller:change_application_data(Appls, + ok = application_controller:change_application_data(Appls, Config), %% Check that stdlib parameters are correctly set - ?line Env = application:get_all_env(stdlib), - ?line {value, {par1,sys}} = lists:keysearch(par1, 1, Env), - ?line {value, {par2,t1}} = lists:keysearch(par2, 1, Env), - ?line {value, {par3,t1}} = lists:keysearch(par3, 1, Env), - ?line {value, {par4,t2}} = lists:keysearch(par4, 1, Env), - ?line {value, {par5,t3}} = lists:keysearch(par5, 1, Env), - ?line {value, {par6,sys}} = lists:keysearch(par6, 1, Env), + Env = application:get_all_env(stdlib), + {value, {par1,sys}} = lists:keysearch(par1, 1, Env), + {value, {par2,t1}} = lists:keysearch(par2, 1, Env), + {value, {par3,t1}} = lists:keysearch(par3, 1, Env), + {value, {par4,t2}} = lists:keysearch(par4, 1, Env), + {value, {par5,t3}} = lists:keysearch(par5, 1, Env), + {value, {par6,sys}} = lists:keysearch(par6, 1, Env), - ?line ok = file:set_cwd(CWD). + ok = file:set_cwd(CWD). %% This function is stolen from SASL module release_handler, OTP R10B get_appls({script, _, Script}) -> @@ -1882,18 +1916,18 @@ shutdown_func(suite) -> shutdown_func(doc) -> ["Tests the 'shutdown_func' kernel config parameter"]; shutdown_func(Config) when is_list(Config) -> - ?line {ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_func"), - ?line wait_for_ready_net(), - ?line Tag = make_ref(), - ?line ok = rpc:call(Cp1, application, set_env, + {ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_func"), + wait_for_ready_net(), + Tag = make_ref(), + ok = rpc:call(Cp1, application, set_env, [kernel, shutdown_func, {?MODULE, do_shutdown}]), - ?line ok = rpc:call(Cp1, application, set_env, + ok = rpc:call(Cp1, application, set_env, [kernel, shutdown_func_test, {self(), Tag}]), - ?line _ = rpc:call(Cp1, init, stop, []), - ?line receive + _ = rpc:call(Cp1, init, stop, []), + receive {Pid, Tag, shutting_down, shutdown} -> - ?line Mref = erlang:monitor(process, Pid), - ?line Pid ! {self(), Tag, ok}, + Mref = erlang:monitor(process, Pid), + Pid ! {self(), Tag, ok}, receive {'DOWN', Mref, _, Pid, noconnection} -> ok @@ -2479,9 +2513,9 @@ node_name(Name, Config) -> lists:concat([Name,U,?testcase,U,U,L]). stop_node_nice(Node) when is_atom(Node) -> - ?line test_server:stop_node(Node); + test_server:stop_node(Node); stop_node_nice(Nodes) when is_list(Nodes) -> - ?line lists:foreach(fun (N) -> stop_node_nice(N) end, Nodes). + lists:foreach(fun (N) -> stop_node_nice(N) end, Nodes). get_start_type(Expected) -> @@ -2572,10 +2606,10 @@ get_conf_change(Expected) -> {cc, Expected} -> ok; {cc, List} -> - ?line test_server:format("====== ~p ======~n",[{cc, List}]), - ?line test_server:fail(not_valid_conf_change) + test_server:format("====== ~p ======~n",[{cc, List}]), + test_server:fail(not_valid_conf_change) after 5000 -> - ?line test_server:fail(not_valid_conf_change_to) + test_server:fail(not_valid_conf_change_to) end. conf_change() -> @@ -2595,75 +2629,75 @@ cc(List) -> create_app() -> - ?line Dir = "./", - ?line App1 = Dir ++ "app1", - ?line {ok, Fd1} = file:open(App1++".app",[write]), - ?line io:format(Fd1, "~p. \n", [app1()]), - ?line file:close(Fd1), - ?line App2 = Dir ++ "app2", - ?line {ok, Fd2} = file:open(App2++".app",[write]), - ?line io:format(Fd2, "~p. \n", [app2()]), - ?line file:close(Fd2), - ?line App3 = Dir ++ "app_sp", - ?line {ok, Fd3} = file:open(App3++".app",[write]), - ?line io:format(Fd3, "~p. \n", [app_sp()]), - ?line file:close(Fd3), + Dir = "./", + App1 = Dir ++ "app1", + {ok, Fd1} = file:open(App1++".app",[write]), + io:format(Fd1, "~p. \n", [app1()]), + file:close(Fd1), + App2 = Dir ++ "app2", + {ok, Fd2} = file:open(App2++".app",[write]), + io:format(Fd2, "~p. \n", [app2()]), + file:close(Fd2), + App3 = Dir ++ "app_sp", + {ok, Fd3} = file:open(App3++".app",[write]), + io:format(Fd3, "~p. \n", [app_sp()]), + file:close(Fd3), ok. create_script(ScriptName) -> - ?line Dir = "./", - ?line Name = Dir ++ ScriptName, - ?line Apps = 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, + Dir = "./", + Name = Dir ++ ScriptName, + Apps = 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\", \"LATEST\"}, \n" " {erts, \"4.4\"}, \n" " [{kernel, \"~s\"}, {stdlib, \"~s\"}, \n" " {app1, \"2.0\"}, {app2, \"2.0\"}, {app_sp, \"2.0\"}]}.\n", [KernelVer,StdlibVer]), - ?line file:close(Fd), + file:close(Fd), {{KernelVer,StdlibVer}, {filename:dirname(Name), filename:basename(Name)}}. create_script_dc(ScriptName) -> - ?line Dir = "./", - ?line Name = Dir ++ ScriptName, - ?line Apps = 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, + Dir = "./", + Name = Dir ++ ScriptName, + Apps = 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\", \"LATEST\"}, \n" " {erts, \"4.4\"}, \n" " [{kernel, \"~s\"}, {stdlib, \"~s\"}, \n" " {app1, \"2.0\"}, {app2, \"2.0\"}, {app3, \"2.0\"}, \n" " {app6, \"2.0\"}, {app7, \"2.0\"}, {app8, \"2.0\"}]}.\n", [KernelVer,StdlibVer]), - ?line file:close(Fd), + file:close(Fd), {{KernelVer,StdlibVer}, {filename:dirname(Name), filename:basename(Name)}}. create_script_3002(ScriptName) -> - ?line Dir = "./", - ?line Name = Dir ++ ScriptName, - ?line Apps = which_applications(), - ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), - ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), - ?line {value,{_,_,SaslVer}} = lists:keysearch(sasl,1,Apps), - ?line {ok,Fd} = file:open(Name++".rel",[write]), - ?line io:format(Fd, + Dir = "./", + Name = Dir ++ ScriptName, + Apps = which_applications(), + {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), + {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), + {value,{_,_,SaslVer}} = lists:keysearch(sasl,1,Apps), + {ok,Fd} = file:open(Name++".rel",[write]), + io:format(Fd, "{release, {\"Test release 3\", \"LATEST\"}, \n" " {erts, \"4.4\"}, \n" " [{kernel, \"~s\"}, {stdlib, \"~s\"}, \n" " {sasl, \"~s\"}]}.\n", [KernelVer, StdlibVer, SaslVer]), - ?line file:close(Fd), + file:close(Fd), {{KernelVer,StdlibVer}, {filename:dirname(Name), filename:basename(Name)}}. @@ -2672,57 +2706,57 @@ create_script_3002(ScriptName) -> distr_changed_prep(Conf) when is_list(Conf) -> % Write .app files - ?line {ok, Fd1} = file:open("app1.app", [write]), - ?line w_app1(Fd1), - ?line file:close(Fd1), - ?line {ok, Fd2} = file:open("app2.app", [write]), - ?line w_app2(Fd2), - ?line file:close(Fd2), - ?line {ok, Fd3} = file:open("app3.app", [write]), - ?line w_app3(Fd3), - ?line file:close(Fd3), - ?line {ok, Fd4} = file:open("app6.app", [write]), - ?line w_app6(Fd4), - ?line file:close(Fd4), - ?line {ok, Fd5} = file:open("app7.app", [write]), - ?line w_app7(Fd5), - ?line file:close(Fd5), - ?line {ok, Fd6} = file:open("app8.app", [write]), - ?line w_app8(Fd6), - ?line file:close(Fd6), + {ok, Fd1} = file:open("app1.app", [write]), + w_app1(Fd1), + file:close(Fd1), + {ok, Fd2} = file:open("app2.app", [write]), + w_app2(Fd2), + file:close(Fd2), + {ok, Fd3} = file:open("app3.app", [write]), + w_app3(Fd3), + file:close(Fd3), + {ok, Fd4} = file:open("app6.app", [write]), + w_app6(Fd4), + file:close(Fd4), + {ok, Fd5} = file:open("app7.app", [write]), + w_app7(Fd5), + file:close(Fd5), + {ok, Fd6} = file:open("app8.app", [write]), + w_app8(Fd6), + file:close(Fd6), % Create the .app files and the boot script - ?line {{KernelVer,StdlibVer}, _} = create_script_dc("dc"), + {{KernelVer,StdlibVer}, _} = create_script_dc("dc"), - ?line case is_real_system(KernelVer, StdlibVer) of + case is_real_system(KernelVer, StdlibVer) of true -> Options = []; false -> Options = [local] end, - ?line ok = systools:make_script("dc", Options), + ok = systools:make_script("dc", Options), NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf), NoSyncTime = config_fun_fast(config_dc(NodeNames)), WithSyncTime = config_fun(config_dc(NodeNames)), - ?line Dir = ?config(priv_dir,Conf), - ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]), - ?line (config_dc2(NodeNames))(Fd_dc2), - ?line file:close(Fd_dc2), - ?line Config2 = filename:join(Dir, "sys2"), + Dir = ?config(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] - ?line {ok, Cp1} = start_node_boot_config(Ncp1, NoSyncTime, Conf, dc), - ?line {ok, Cp2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, dc), - ?line {ok, Cp3} = start_node_boot_config(Ncp3, WithSyncTime, Conf, dc), - ?line global:sync(), + {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), + global:sync(), %% Read the current configuration parameters, and change them - ?line OldEnv = rpc:call(Cp1, application_controller, prep_config_change, []), - ?line {value, {kernel, OldKernel}} = lists:keysearch(kernel, 1, OldEnv), + OldEnv = rpc:call(Cp1, application_controller, prep_config_change, []), + {value, {kernel, OldKernel}} = lists:keysearch(kernel, 1, OldEnv), {OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {Ncp1, Ncp2, Ncp3}, Config2}. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 827208b048..fc17db2745 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -25,6 +25,7 @@ replace_path/1, load_file/1, load_abs/1, ensure_loaded/1, delete/1, purge/1, soft_purge/1, is_loaded/1, all_loaded/1, load_binary/1, dir_req/1, object_code/1, set_path_file/1, + 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, @@ -32,7 +33,7 @@ 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]). + native_early_modules/1, get_mode/1]). -export([init_per_testcase/2, end_per_testcase/2, init_per_suite/1, end_per_suite/1, @@ -43,6 +44,8 @@ handle_event/2, handle_call/2, handle_info/2, terminate/2]). +-export([compile_load/4]). + suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -50,13 +53,14 @@ all() -> replace_path, load_file, load_abs, ensure_loaded, delete, purge, soft_purge, is_loaded, all_loaded, load_binary, dir_req, object_code, set_path_file, + upgrade, 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, bad_erl_libs, code_archive, code_archive2, on_load, on_load_binary, on_load_embedded, on_load_errors, - big_boot_embedded, native_early_modules]. + big_boot_embedded, native_early_modules, get_mode]. groups() -> []. @@ -450,6 +454,46 @@ 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], + + ok. + +upgrade_do(DataDir, Client, U1, U2, O1, O2) -> + compile_load(upgrade_client, DataDir, undefined, Client), + upgrade_client:run(DataDir, U1, U2, O1, O2), + ok. + +compile_load(Mod, Dir, Ver, CodeType) -> + Version = case Ver of + undefined -> + io:format("Compiling '~p' as ~p\n", [Mod, CodeType]), + []; + _ -> + io:format("Compiling version ~p of '~p' as ~p\n", + [Ver, Mod, CodeType]), + [{d,list_to_atom("VERSION_" ++ integer_to_list(Ver))}] + end, + Target = case CodeType of + beam -> []; + hipe -> [native] + end, + CompOpts = [binary, report] ++ Target ++ Version, + + Src = filename:join(Dir, atom_to_list(Mod) ++ ".erl"), + %io:format("compile:file(~p,~p)\n", [Src, CompOpts]), + {ok,Mod,Code} = compile:file(Src, CompOpts), + ObjFile = filename:basename(Src,".erl") ++ ".beam", + {module,Mod} = code:load_binary(Mod, ObjFile, Code), + %IsNative = code:is_module_native(Mod), + ok. + dir_req(suite) -> []; dir_req(doc) -> []; dir_req(Config) when is_list(Config) -> @@ -535,30 +579,25 @@ sticky_compiler(File) -> pa_pz_option(suite) -> []; pa_pz_option(doc) -> ["Test that the -pa and -pz options work as expected"]; pa_pz_option(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "Slave nodes not supported on VxWorks"}; - _ -> - DDir = ?config(data_dir,Config), - PaDir = filename:join(DDir,"pa"), - PzDir = filename:join(DDir,"pz"), - ?line {ok, Node}=?t:start_node(pa_pz1, slave, - [{args, - "-pa " ++ PaDir - ++ " -pz " ++ PzDir}]), - ?line Ret=rpc:call(Node, code, get_path, []), - ?line [PaDir|Paths] = Ret, - ?line [PzDir|_] = lists:reverse(Paths), - ?t:stop_node(Node), - ?line {ok, Node2}=?t:start_node(pa_pz2, slave, - [{args, - "-mode embedded " ++ "-pa " - ++ PaDir ++ " -pz " ++ PzDir}]), - ?line Ret2=rpc:call(Node2, code, get_path, []), - ?line [PaDir|Paths2] = Ret2, - ?line [PzDir|_] = lists:reverse(Paths2), - ?t:stop_node(Node2) - end. + DDir = ?config(data_dir,Config), + PaDir = filename:join(DDir,"pa"), + PzDir = filename:join(DDir,"pz"), + {ok, Node}=?t: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, + [{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). add_del_path(suite) -> []; @@ -645,8 +684,8 @@ ext_mod_dep(Config) when is_list(Config) -> xref:set_default(s, [{verbose,false},{warnings,false}, {builtins,true},{recurse,true}]), xref:set_library_path(s, code:get_path()), - xref:add_directory(s, filename:dirname(code:which(kernel))), - xref:add_directory(s, filename:dirname(code:which(lists))), + xref:add_directory(s, filename:join(code:lib_dir(kernel),"ebin")), + xref:add_directory(s, filename:join(code:lib_dir(stdlib),"ebin")), case catch ext_mod_dep2() of {'EXIT', Reason} -> xref:stop(s), @@ -677,7 +716,7 @@ analyse([], [This={M,F,A}|Path], Visited, ErrCnt0) -> %% These modules should be loaded by code.erl before %% the code_server is started. OK = [erlang, os, prim_file, erl_prim_loader, init, ets, - code_server, lists, lists_sort, unicode, binary, filename, packages, + code_server, lists, lists_sort, unicode, binary, filename, gb_sets, gb_trees, hipe_unified_loader, hipe_bifs, prim_zip, zlib], ErrCnt1 = @@ -783,6 +822,10 @@ check_funs({'$M_EXPR','$F_EXPR',2}, 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; check_funs({'$M_EXPR',warning_msg,2}, [{code_server,finish_on_load_report,2} | _]) -> 0; %% This is cheating! /raimo @@ -1551,10 +1594,15 @@ native_early_modules_1(Architecture) -> ?line true = lists:all(fun code:is_module_native/1, [ets,file,filename,gb_sets,gb_trees, %%hipe_unified_loader, no_native as workaround - lists,os,packages]), + lists,os]), ok end. +get_mode(suite) -> []; +get_mode(doc) -> ["Test that the mode of the code server is properly retrieved"]; +get_mode(Config) when is_list(Config) -> + interactive = code:get_mode(). + %%----------------------------------------------------------------- %% error_logger handler. %% (Copied from stdlib/test/proc_lib_SUITE.erl.) diff --git a/lib/kernel/test/code_SUITE_data/other.erl b/lib/kernel/test/code_SUITE_data/other.erl new file mode 100644 index 0000000000..58ce87f222 --- /dev/null +++ b/lib/kernel/test/code_SUITE_data/other.erl @@ -0,0 +1,38 @@ +-module(other). + +-ifdef(VERSION_1). +-define(VERSION,1). +-export([exp1/0]). +-export([exp1loc2/0]). +-export([exp1exp2/0]). +exp1() -> check([loc1(),exp1loc2(),exp1exp2(),loc1exp2(),loc1loc2()]). +loc1() -> check([exp1loc2(),exp1exp2(),loc1exp2(),loc1loc2()]). +exp1loc2() -> check([exp1exp2(),loc1exp2(),loc1loc2()]). +exp1exp2() -> check([loc1exp2(),loc1loc2()]). +loc1exp2() -> check([loc1loc2()]). +-endif. % VERSION_1 + +-ifdef(VERSION_2). +-define(VERSION,2). +-export([exp2/0]). +-export([loc1exp2/0]). +-export([exp1exp2/0]). +loc1exp2() -> check([exp1exp2(),exp1loc2(),loc2(),exp2(),loc1loc2()]). +exp1exp2() -> check([exp1loc2(),loc2(),exp2(),loc1loc2()]). +exp1loc2() -> check([loc2(),exp2(),loc1loc2()]). +loc2() -> check([exp2(),loc1loc2()]). +exp2() -> check([loc1loc2()]). + +-endif. % VERSION_2 + +loc1loc2() -> ?VERSION. + + +check(VerList) -> + case lists:all(fun(?VERSION) -> true; (_) -> false end, + VerList) of + true -> + ?VERSION; + false -> + VerList + end. diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl new file mode 100644 index 0000000000..bb655e01d3 --- /dev/null +++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl @@ -0,0 +1,259 @@ +-module(upgrade_client). + +-export([run/5]). + +%%-define(line, io:format("~s:~p\n", [?MODULE,?LINE]),). +-define(line,). + +run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> + %% Load version 1 of upgradee + code_SUITE:compile_load(upgradee, Dir, 1, Upgradee1), + + ?line 1 = upgradee:exp1(), + ?line 1 = upgradee:exp1exp2(), + ?line 1 = upgradee:exp1loc2(), + + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1exp2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()), + + P = spawn_link(upgradee,dispatch_loop,[]), + + ?line 1 = proxy_call(P, local, exp1), + ?line 1 = proxy_call(P, local, loc1), + ?line 1 = proxy_call(P, local, exp1exp2), + ?line 1 = proxy_call(P, local, exp1loc2), + ?line 1 = proxy_call(P, local, loc1exp2), + ?line 1 = proxy_call(P, local, loc1loc2), + ?line 1 = proxy_call(P, external, exp1), + ?line 1 = proxy_call(P, external, exp1exp2), + ?line 1 = proxy_call(P, external, exp1loc2), + + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2), + ?line {cannot_compile,1} = proxy_call(P, local, exp2), + ?line {cannot_compile,1} = proxy_call(P, local, loc2), + + ?line {'EXIT',{undef,_}} = (catch other:exp1()), + ?line {'EXIT',{undef,_}} = (catch other:loc1()), + ?line {'EXIT',{undef,_}} = (catch other:exp1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:exp1exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc11exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc2()), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + %% + %% Load version 1 of other + %% + code_SUITE:compile_load(other, Dir, 1, Other1), + ?line 1 = other:exp1(), + ?line 1 = other:exp1loc2(), + ?line 1 = other:exp1exp2(), + ?line {'EXIT',{undef,_}} = (catch other:loc1()), + ?line {'EXIT',{undef,_}} = (catch other:loc1exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc2()), + + ?line 1 = proxy_call(P, other, exp1), + ?line 1 = proxy_call(P, other, exp1loc2), + ?line 1 = proxy_call(P, other, exp1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + %% + %% Load version 2 of upgradee + %% + code_SUITE:compile_load(upgradee, Dir, 2, Upgradee2), + + ?line 2 = upgradee:exp2(), + ?line 2 = upgradee:exp1exp2(), + ?line 2 = upgradee:loc1exp2(), + + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()), + + ?line 1 = proxy_call(P, local, exp1), + ?line 1 = proxy_call(P, local, loc1), + ?line 1 = proxy_call(P, local, exp1exp2), + ?line 1 = proxy_call(P, local, exp1loc2), + ?line 1 = proxy_call(P, local, loc1exp2), + ?line 1 = proxy_call(P, local, loc1loc2), + ?line {cannot_compile,1} = proxy_call(P, local, exp2), + ?line {cannot_compile,1} = proxy_call(P, local, loc2), + + ?line 2 = proxy_call(P, external, exp1exp2), + ?line 2 = proxy_call(P, external, loc1exp2), + ?line 2 = proxy_call(P, external, exp2), + + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2), + + ?line 1 = other:exp1(), + ?line 1 = other:exp1loc2(), + ?line 1 = other:exp1exp2(), + ?line {'EXIT',{undef,_}} = (catch other:loc1()), + ?line {'EXIT',{undef,_}} = (catch other:loc1exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:exp2()), + ?line {'EXIT',{undef,_}} = (catch other:loc2()), + + ?line 1 = proxy_call(P, other, exp1), + ?line 1 = proxy_call(P, other, exp1loc2), + ?line 1 = proxy_call(P, other, exp1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + %% + %% Load version 2 of other + %% + code_SUITE:compile_load(other, Dir, 2, Other2), + + ?line 2 = upgradee:exp2(), + ?line 2 = upgradee:exp1exp2(), + ?line 2 = upgradee:loc1exp2(), + + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()), + + ?line 1 = proxy_call(P, local, exp1), + ?line 1 = proxy_call(P, local, loc1), + ?line 1 = proxy_call(P, local, exp1exp2), + ?line 1 = proxy_call(P, local, exp1loc2), + ?line 1 = proxy_call(P, local, loc1exp2), + ?line 1 = proxy_call(P, local, loc1loc2), + ?line {cannot_compile,1} = proxy_call(P, local, exp2), + ?line {cannot_compile,1} = proxy_call(P, local, loc2), + + ?line 2 = proxy_call(P, external, exp1exp2), + ?line 2 = proxy_call(P, external, loc1exp2), + ?line 2 = proxy_call(P, external, exp2), + + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2), + + ?line 2 = other:exp2(), + ?line 2 = other:loc1exp2(), + ?line 2 = other:exp1exp2(), + ?line {'EXIT',{undef,_}} = (catch other:exp1()), + ?line {'EXIT',{undef,_}} = (catch other:loc1()), + ?line {'EXIT',{undef,_}} = (catch other:exp1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:loc2()), + + ?line 2 = proxy_call(P, other, exp2), + ?line 2 = proxy_call(P, other, loc1exp2), + ?line 2 = proxy_call(P, other, exp1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + + %% + %% Upgrade proxy to version 2 + %% + P ! upgrade_order, + + + %% + io:format("Delete version 2 of 'upgradee'\n",[]), + %% + code:purge(upgradee), + code:delete(upgradee), + + ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1exp2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1exp2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()), + ?line {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()), + + ?line 2 = proxy_call(P, local, exp2), + ?line 2 = proxy_call(P, local, loc2), + ?line 2 = proxy_call(P, local, exp1exp2), + ?line 2 = proxy_call(P, local, exp1loc2), + ?line 2 = proxy_call(P, local, loc1exp2), + ?line 2 = proxy_call(P, local, loc1loc2), + ?line {cannot_compile,2} = proxy_call(P, local, exp1), + ?line {cannot_compile,2} = proxy_call(P, local, loc1), + + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2), + + ?line 2 = other:exp2(), + ?line 2 = other:loc1exp2(), + ?line 2 = other:exp1exp2(), + ?line {'EXIT',{undef,_}} = (catch other:exp1()), + ?line {'EXIT',{undef,_}} = (catch other:loc1()), + ?line {'EXIT',{undef,_}} = (catch other:exp1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()), + ?line {'EXIT',{undef,_}} = (catch other:loc2()), + + ?line 2 = proxy_call(P, other, exp2), + ?line 2 = proxy_call(P, other, loc1exp2), + ?line 2 = proxy_call(P, other, exp1exp2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), + ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + unlink(P), + exit(P, die_please), + + io:format("Purge 'upgradee'\n",[]), + code:purge(upgradee), + + io:format("Delete and purge 'other'\n",[]), + code:purge(other), + code:delete(other), + code:purge(other), + ok. + +proxy_call(Pid, CallType, Func) -> + Pid ! {self(), CallType, Func}, + receive + {Pid, call_result, Func, Ret} -> Ret + end. diff --git a/lib/kernel/test/code_SUITE_data/upgradee.erl b/lib/kernel/test/code_SUITE_data/upgradee.erl new file mode 100644 index 0000000000..62b1d95e30 --- /dev/null +++ b/lib/kernel/test/code_SUITE_data/upgradee.erl @@ -0,0 +1,123 @@ +-module(upgradee). + +-export([dispatch_loop/0]). + +-ifdef(VERSION_1). +-define(VERSION,1). + +-export([exp1/0]). % only exported in v1 +-export([exp1loc2/0]). % exported in v1, local in v2 +-export([exp1exp2/0]). % exported in v1 and v2 + +exp1() -> ?VERSION. +loc1() -> ?VERSION. + +-endif. % VERSION_1 + +-ifdef(VERSION_2). +-define(VERSION,2). + +-export([exp2/0]). +-export([loc1exp2/0]). +-export([exp1exp2/0]). + +exp2() -> ?VERSION. +loc2() -> ?VERSION. + +-endif. % VERSION_2 + +exp1exp2() -> ?VERSION. +exp1loc2() -> ?VERSION. +loc1exp2() -> ?VERSION. +loc1loc2() -> ?VERSION. + +dispatch_loop() -> + receive + upgrade_order -> + %%erlang:display({"upgradee version", ?VERSION, "got upgrade_order"}), + ?MODULE:dispatch_loop(); + + Msg -> + %%erlang:display({"upgradee version", ?VERSION, "got msg", Msg}), + {Func,Ret} = case Msg of + %% Local calls + {Pid, local, F=exp1} -> + {F, local_exp1()}; + {Pid, local, F=loc1} -> + {F, local_loc1()}; + {Pid, local, F=exp1exp2} -> + {F, catch exp1exp2()}; + {Pid, local, F=exp1loc2} -> + {F, catch exp1loc2()}; + {Pid, local, F=loc1exp2} -> + {F, catch loc1exp2()}; + {Pid, local, F=loc1loc2} -> + {F, catch loc1loc2()}; + {Pid, local, F=exp2} -> + {F, local_exp2()}; + {Pid, local, F=loc2} -> + {F, local_loc2()}; + + %% Extern calls to own module + {Pid, external, F=exp1} -> + {F, catch ?MODULE:exp1()}; + {Pid, external, F=loc1} -> + {F, catch ?MODULE:loc1()}; + {Pid, external, F=exp1exp2} -> + {F, catch ?MODULE:exp1exp2()}; + {Pid, external, F=exp1loc2} -> + {F, catch ?MODULE:exp1loc2()}; + {Pid, external, F=loc1exp2} -> + {F, catch ?MODULE:loc1exp2()}; + {Pid, external, F=loc1loc2} -> + {F, catch ?MODULE:loc1loc2()}; + {Pid, external, F=exp2} -> + {F, catch ?MODULE:exp2()}; + {Pid, external, F=loc2} -> + {F, catch ?MODULE:loc2()}; + + %% External calls to other module + {Pid, other, F=exp1} -> + {F, catch other:exp1()}; + {Pid, other, F=loc1} -> + {F, catch other:loc1()}; + {Pid, other, F=exp1exp2} -> + {F, catch other:exp1exp2()}; + {Pid, other, F=exp1loc2} -> + {F, catch other:exp1loc2()}; + {Pid, other, F=loc1exp2} -> + {F, catch other:loc1exp2()}; + {Pid, other, F=loc1loc2} -> + {F, catch other:loc1loc2()}; + {Pid, other, F=exp2} -> + {F, catch other:exp2()}; + {Pid, other, F=loc2} -> + {F, catch other:loc2()} + end, + Pid ! {self(), call_result, Func, Ret}, + + dispatch_loop() % A local call, we don't want to upgrade the dispatcher + end. + + + +-ifdef(VERSION_1). +local_exp1() -> catch exp1(). +local_loc1() -> catch loc1(). +-else. +local_exp1() -> + %%erlang:display({"upgradee:local_exp1 in version", ?VERSION}), + {cannot_compile,?VERSION}. +local_loc1() -> {cannot_compile,?VERSION}. +-endif. + +-ifdef(VERSION_2). +local_exp2() -> catch exp2(). +local_loc2() -> catch loc2(). +-else. +local_exp2() -> + %%erlang:display({"upgradee:local_exp2 in version", ?VERSION}), + {cannot_compile,?VERSION}. +local_loc2() -> + {cannot_compile,?VERSION}. +-endif. diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 0c3f5c3514..f55af1e354 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -126,11 +126,6 @@ error, chunk, truncate, many_users, info, change_size, change_attribute, distribution, evil, otp_6278, otp_10131]). -%% The following two lists should be mutually exclusive. To skip a case -%% on VxWorks altogether, use the kernel.spec.vxworks file instead. -%% PLEASE don't skip out of laziness, the goal is to make every -%% testcase runnable on VxWorks. - %% These test cases should be skipped if the VxWorks card is %% configured without NFS cache. -define(SKIP_NO_CACHE,[distribution]). @@ -3210,7 +3205,7 @@ many_users(Conf) when is_list(Conf) -> ?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,20}, Dir), + {300*NoClients,200}, Dir), ?line true = lists:duplicate(NoClients, ok) == C3, ?line true = length(T3) == N*NoClients, ok. @@ -5126,33 +5121,8 @@ stop_node(Node) -> %% 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. -check_nfs(Config) -> - case (catch check_cache(Config)) of - N when is_integer(N) -> - N; - _ -> - 0 - end. - -check_cache(Config) -> - ?line Check = filename:join(?datadir(Config), "nfs_check"), - ?line P = open_port({spawn, Check}, [{line,100}, eof]), - ?line Size = receive - {P,{data,{eol,S}}} -> - list_to_integer(S) - after 1000 -> - erlang:display(got_timeout), - exit(timeout) - end, - ?line receive - {P, eof} -> - ok - end, - ?line P ! {self(), close}, - ?line receive - {P, closed} -> ok - end, - Size. +check_nfs(_Config) -> + 0. skip_expand([]) -> []; @@ -5175,13 +5145,8 @@ skip_list(Config) -> skip_expand(?SKIP_LARGE_CACHE) end. -should_skip(Test,Config) -> - case os:type() of - vxworks -> - lists:member(Test, skip_list(Config)); - _ -> - false - end. +should_skip(_Test,_Config) -> + false. %%----------------------------------------------------------------- %% The error_logger handler used. diff --git a/lib/kernel/test/disk_log_SUITE_data/Makefile.src b/lib/kernel/test/disk_log_SUITE_data/Makefile.src deleted file mode 100644 index cae2f23d29..0000000000 --- a/lib/kernel/test/disk_log_SUITE_data/Makefile.src +++ /dev/null @@ -1,15 +0,0 @@ -CC = @CC@ -LD = @LD@ -CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@ -CROSSLDFLAGS = @CROSSLDFLAGS@ - -PROGS = nfs_check@exe@ - -all: $(PROGS) - -nfs_check@exe@: nfs_check@obj@ - $(LD) $(CROSSLDFLAGS) -o nfs_check nfs_check@obj@ @LIBS@ - -nfs_check@obj@: nfs_check.c - $(CC) -c -o nfs_check@obj@ $(CFLAGS) nfs_check.c - diff --git a/lib/kernel/test/disk_log_SUITE_data/nfs_check.c b/lib/kernel/test/disk_log_SUITE_data/nfs_check.c deleted file mode 100644 index 31e9ba8190..0000000000 --- a/lib/kernel/test/disk_log_SUITE_data/nfs_check.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Author: Patrik Nyblom - * Purpose: A port program to check the NFS cache size on VxWorks (returns 0 - * for other platforms). - */ - -#ifdef VXWORKS -#include <vxWorks.h> -#include <taskVarLib.h> -#include <taskLib.h> -#include <sysLib.h> -#include <string.h> -#include <ioLib.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#ifdef VXWORKS -extern unsigned nfsCacheSize; -#define MAIN(argc, argv) nfs_check(argc, argv) -#else -#define MAIN(argc, argv) main(argc, argv) -#endif - - -MAIN(argc, argv) -int argc; -char *argv[]; -{ -#ifdef VXWORKS - char str[100]; - sprintf(str,"%d\n", nfsCacheSize); - write(1, str, strlen(str)); -#else - fprintf(stdout,"0"); - fflush(stdout); -#endif - return 0; -} - diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index 72239641e9..35502a1d27 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -110,56 +110,46 @@ get_file(Config) when is_list(Config) -> inet_existing(doc) -> ["Start a node using the 'inet' loading method, ", "from an already started boot server."]; inet_existing(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "VxWorks: tested separately"}; - _ -> - ?line Name = erl_prim_test_inet_existing, - ?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 {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), - ?line stop_node(Node), - ?line unlink(BootPid), - ?line exit(BootPid, kill), - ok - end. + 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), + {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."]; inet_coming_up(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "VxWorks: tested separately"}; - _ -> - ?line Name = erl_prim_test_inet_coming_up, - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line Host = host(), - ?line IpStr = ip_str(Host), - ?line LFlag = get_loader_flag(os:type()), - ?line Args = LFlag ++ - " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - ?line {ok, Node} = start_node(Name, Args, [{wait, false}]), - - %% Wait a while, then start boot server, and wait for node to start. - ?line test_server:sleep(test_server:seconds(6)), - io:format("erl_boot_server:start_link([~p]).", [Host]), - ?line {ok, BootPid} = erl_boot_server:start_link([Host]), - ?line wait_really_started(Node, 25), - - %% Check loader argument, then cleanup. - ?line {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), - ?line stop_node(Node), - ?line unlink(BootPid), - ?line exit(BootPid, kill), - ok - end. + 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}]), + + %% 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]), + wait_really_started(Node, 25), + + %% Check loader argument, then cleanup. + {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]), + stop_node(Node), + unlink(BootPid), + exit(BootPid, kill), + ok. wait_really_started(Node, 0) -> test_server:fail({not_booted,Node}); @@ -249,8 +239,6 @@ multiple_slaves(doc) -> "verify that the boot server manages"]; multiple_slaves(Config) when is_list(Config) -> case os:type() of - vxworks -> - {comment, "VxWorks: tested separately"}; {ose,_} -> {comment, "OSE: multiple nodes not supported"}; _ -> diff --git a/lib/kernel/test/error_handler_SUITE.erl b/lib/kernel/test/error_handler_SUITE.erl new file mode 100644 index 0000000000..2a86d39b74 --- /dev/null +++ b/lib/kernel/test/error_handler_SUITE.erl @@ -0,0 +1,68 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(error_handler_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + undefined_function_handler/1]). + +%% Callback from error_handler. +-export(['$handle_undefined_function'/2]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [undefined_function_handler]. + +groups() -> + []. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + + +%%----------------------------------------------------------------- + +undefined_function_handler(_) -> + 42 = ?MODULE:forty_two(), + 42 = (id(?MODULE)):forty_two(), + {ok,{a,b,c}} = ?MODULE:one_arg({a,b,c}), + {ok,{a,b,c}} = (id(?MODULE)):one_arg({a,b,c}), + {'EXIT',{undef,[{?MODULE,undef_and_not_handled,[[1,2,3]],[]}|_]}} = + (catch ?MODULE:undef_and_not_handled([1,2,3])), + ok. + +'$handle_undefined_function'(forty_two, []) -> + 42; +'$handle_undefined_function'(one_arg, [Arg]) -> + {ok,Arg}; +'$handle_undefined_function'(Func, Args) -> + error_handler:raise_undef_exception(?MODULE, Func, Args). + +id(I) -> + I. diff --git a/lib/kernel/test/error_logger_warn_SUITE.erl b/lib/kernel/test/error_logger_warn_SUITE.erl index 265e1ae4c8..2bf467610e 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-2011. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -310,7 +310,7 @@ nice_stop_node(Name) -> {nodedown,Name} -> ok end. -%rensa rd() f�re varje rapport-test s� man bara f�r en fil... +%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) -> diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 848db06e82..e4c8f0ffaf 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -45,6 +45,8 @@ init_per_testcase/2, end_per_testcase/2, read_write_file/1, names/1]). -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]). -export([close/1, consult1/1, path_consult/1, delete/1]). -export([ eval1/1, path_eval/1, script1/1, path_script/1, @@ -55,12 +57,13 @@ -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]). +-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]). + 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]). @@ -84,8 +87,12 @@ -export([advise/1]). +-export([allocate/1]). + -export([standard_io/1,mini_server/1]). +-export([old_io_protocol/1]). + %% Debug exports -export([create_file_slow/2, create_file/2, create_bin/2]). -export([verify_file/2, verify_bin/3]). @@ -107,16 +114,18 @@ all() -> {group, files}, delete, rename, names, {group, errors}, {group, compression}, {group, links}, copy, delayed_write, read_ahead, segment_read, segment_write, - ipread, pid2name, interleaved_read_write, otp_5814, + ipread, pid2name, interleaved_read_write, otp_5814, otp_10852, large_file, large_write, read_line_1, read_line_2, read_line_3, - read_line_4, standard_io]. + read_line_4, standard_io, old_io_protocol]. groups() -> - [{dirs, [], [make_del_dir, cur_dir_0, cur_dir_1]}, + [{dirs, [], [make_del_dir, cur_dir_0, cur_dir_1, + list_dir, list_dir_error, untranslatable_names, + untranslatable_names_error]}, {files, [], [{group, open}, {group, pos}, {group, file_info}, {group, consult}, {group, eval}, {group, script}, - truncate, sync, datasync, advise]}, + truncate, sync, datasync, advise, allocate]}, {open, [], [open1, old_modes, new_modes, path_open, close, access, read_write, pread_write, append, open_errors, @@ -133,7 +142,8 @@ groups() -> {compression, [], [read_compressed_cooked, read_compressed_cooked_binary, read_cooked_tar_problem, read_not_really_compressed, - write_compressed, compress_errors, catenated_gzips]}, + write_compressed, compress_errors, catenated_gzips, + compress_async_crash]}, {links, [], [make_link, read_link_info_for_non_link, symlinks]}]. @@ -228,7 +238,7 @@ mini_server(Parent) -> receive die -> ok; - {io_request,From,To,{put_chars,Data}} -> + {io_request,From,To,{put_chars,_Encoding,Data}} -> Parent ! {io_request,From,To,{put_chars,Data}}, From ! {io_reply, To, ok}, mini_server(Parent); @@ -302,6 +312,31 @@ standard_io(Config) when is_list(Config) -> 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"]; +old_io_protocol(Config) when is_list(Config) -> + Dog = test_server:timetrap(test_server:seconds(5)), + RootDir = ?config(priv_dir,Config), + Name = filename:join(RootDir, + atom_to_list(?MODULE) + ++"old_io_protocol.fil"), + MyData = "0123456789abcdefghijklmnopqrstuvxyz", + ok = ?FILE_MODULE:write_file(Name, MyData), + {ok, Fd} = ?FILE_MODULE:open(Name, write), + Fd ! {file_request,self(),Fd,truncate}, + receive + {file_reply,Fd,ok} -> ok + end, + ok = ?FILE_MODULE:close(Fd), + {ok, <<>>} = ?FILE_MODULE:read_file(Name), + test_server:timetrap_cancel(Dog), + [] = flush(), + ok. + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% read_write_file(suite) -> []; @@ -492,8 +527,6 @@ cur_dir_1(Config) when is_list(Config) -> ?line case os:type() of {unix, _} -> ?line {error, enotsup} = ?FILE_MODULE:get_cwd("d:"); - vxworks -> - ?line {error, enotsup} = ?FILE_MODULE:get_cwd("d:"); {win32, _} -> win_cur_dir_1(Config) end, @@ -517,6 +550,148 @@ win_cur_dir_1(_Config) -> ok. + +%%% +%%% Test list_dir() on a non-existing pathname. +%%% + +list_dir_error(Config) -> + Priv = ?config(priv_dir, Config), + NonExisting = filename:join(Priv, "non-existing-dir"), + {error,enoent} = ?FILE_MODULE:list_dir(NonExisting), + ok. + +%%% +%%% Test list_dir() and list_dir_all(). +%%% + +list_dir(Config) -> + RootDir = ?config(priv_dir, Config), + TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"), + ?FILE_MODULE:make_dir(TestDir), + list_dir_1(TestDir, 42, []). + +list_dir_1(TestDir, 0, Sorted) -> + [ok = ?FILE_MODULE:delete(filename:join(TestDir, F)) || + F <- Sorted], + ok = ?FILE_MODULE:del_dir(TestDir); +list_dir_1(TestDir, Cnt, Sorted0) -> + Base = "file" ++ integer_to_list(Cnt), + Name = filename:join(TestDir, Base), + ok = ?FILE_MODULE:write_file(Name, Base), + Sorted = lists:merge([Base], Sorted0), + {ok,DirList0} = ?FILE_MODULE:list_dir(TestDir), + {ok,DirList1} = ?FILE_MODULE:list_dir_all(TestDir), + Sorted = lists:sort(DirList0), + Sorted = lists:sort(DirList1), + list_dir_1(TestDir, Cnt-1, Sorted). + +untranslatable_names(Config) -> + case no_untranslatable_names() of + true -> + {skip,"Not a problem on this OS"}; + false -> + untranslatable_names_1(Config) + end. + +untranslatable_names_1(Config) -> + {ok,OldCwd} = file:get_cwd(), + PrivDir = ?config(priv_dir, Config), + Dir = filename:join(PrivDir, "untranslatable_names"), + ok = file:make_dir(Dir), + Node = start_node(untranslatable_names, "+fnu"), + try + ok = file:set_cwd(Dir), + [ok = file:write_file(F, F) || {_,F} <- untranslatable_names()], + + ExpectedListDir0 = [unicode:characters_to_list(N, utf8) || + {utf8,N} <- untranslatable_names()], + ExpectedListDir = lists:sort(ExpectedListDir0), + io:format("ExpectedListDir: ~p\n", [ExpectedListDir]), + ExpectedListDir = call_and_sort(Node, file, list_dir, [Dir]), + + ExpectedListDirAll0 = [case Enc of + utf8 -> + unicode:characters_to_list(N, utf8); + latin1 -> + N + end || {Enc,N} <- untranslatable_names()], + ExpectedListDirAll = lists:sort(ExpectedListDirAll0), + io:format("ExpectedListDirAll: ~p\n", [ExpectedListDirAll]), + ExpectedListDirAll = call_and_sort(Node, file, list_dir_all, [Dir]) + after + catch test_server:stop_node(Node), + file:set_cwd(OldCwd), + [file:delete(F) || {_,F} <- untranslatable_names()], + file:del_dir(Dir) + end, + ok. + +untranslatable_names_error(Config) -> + case no_untranslatable_names() of + true -> + {skip,"Not a problem on this OS"}; + false -> + untranslatable_names_error_1(Config) + end. + +untranslatable_names_error_1(Config) -> + {ok,OldCwd} = file:get_cwd(), + PrivDir = ?config(priv_dir, Config), + Dir = filename:join(PrivDir, "untranslatable_names_error"), + ok = file:make_dir(Dir), + Node = start_node(untranslatable_names, "+fnue"), + try + ok = file:set_cwd(Dir), + [ok = file:write_file(F, F) || {_,F} <- untranslatable_names()], + + ExpectedListDir0 = [unicode:characters_to_list(N, utf8) || + {utf8,N} <- untranslatable_names()], + ExpectedListDir = lists:sort(ExpectedListDir0), + io:format("ExpectedListDir: ~p\n", [ExpectedListDir]), + {error,{no_translation,BadFile}} = + rpc:call(Node, file, list_dir, [Dir]), + true = lists:keymember(BadFile, 2, untranslatable_names()) + + after + catch test_server:stop_node(Node), + file:set_cwd(OldCwd), + [file:delete(F) || {_,F} <- untranslatable_names()], + file:del_dir(Dir) + end, + ok. + +untranslatable_names() -> + [{utf8,<<"abc">>}, + {utf8,<<"def">>}, + {utf8,<<"Lagerl",195,182,"f">>}, + {utf8,<<195,150,"stra Emterwik">>}, + {latin1,<<"M",229,"rbacka">>}, + {latin1,<<"V",228,"rmland">>}]. + +call_and_sort(Node, M, F, A) -> + {ok,Res} = rpc:call(Node, M, F, A), + lists:sort(Res). + +no_untranslatable_names() -> + case os:type() of + {unix,darwin} -> true; + {win32,_} -> true; + _ -> false + end. + +start_node(Name, Args) -> + [_,Host] = string:tokens(atom_to_list(node()), "@"), + 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); + {ok,Node} -> + ct:log("Node ~p started~n", [Node]), + Node + end. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1038,32 +1213,29 @@ file_info_basic_file(Config) when is_list(Config) -> file_info_basic_directory(suite) -> []; file_info_basic_directory(doc) -> []; file_info_basic_directory(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(5)), + 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. - ?line RootDir = filename:join([?config(priv_dir, Config)]), + RootDir = filename:join([?config(priv_dir, Config)]), %% Test that the RootDir directory has the expected attributes. - ?line test_directory(RootDir, read_write), + test_directory(RootDir, read_write), %% Note that on Windows file systems, %% "/" or "c:/" are *NOT* directories. %% Therefore, test that ?FILE_MODULE:file_info/1 behaves as if they were %% directories. - ?line case os:type() of - {win32, _} -> - ?line test_directory("/", read_write), - ?line test_directory("c:/", read_write), - ?line test_directory("c:\\", read_write); - {unix, _} -> - ?line test_directory("/", read); - vxworks -> - %% Check is just done for owner - ?line test_directory("/", read_write) - end, - ?line test_server:timetrap_cancel(Dog). + case os:type() of + {win32, _} -> + ?line test_directory("/", read_write), + ?line test_directory("c:/", read_write), + ?line test_directory("c:\\", read_write); + {unix, _} -> + ?line test_directory("/", read) + end, + test_server:timetrap_cancel(Dog). test_directory(Name, ExpectedAccess) -> ?line {ok,#file_info{size=Size,type=Type,access=Access, @@ -1622,6 +1794,74 @@ advise(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +allocate(suite) -> []; +allocate(doc) -> "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"), + + Line1 = "Hello\n", + Line2 = "World!\n", + + ?line {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), + + ?line {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), + + ?line {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), + + ?line {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), + + ?line [] = flush(), + ?line test_server:timetrap_cancel(Dog), + 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. + Result = ?FILE_MODULE:allocate(Fd, Offset, Length), + case os:type() of + {win32, _} -> + ?line {error, enotsup} = Result; + _ -> + ?line _ = Result + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1784,9 +2024,7 @@ e_delete(Config) when is_list(Config) -> Base, #file_info {mode=8#600}); {win32, _} -> %% Remove a character device. - ?line {error, eacces} = ?FILE_MODULE:delete("nul"); - vxworks -> - ok + ?line {error, eacces} = ?FILE_MODULE:delete("nul") end, ?line [] = flush(), @@ -1801,148 +2039,133 @@ e_delete(Config) when is_list(Config) -> e_rename(suite) -> []; e_rename(doc) -> []; e_rename(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "Windriver: dosFs must be fixed first!"}; - _ -> - ?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 = ?FILE_MODULE:make_dir(Base), - - %% Create an empty directory. - ?line EmptyDir = filename:join(Base, "empty_dir"), - ?line ok = ?FILE_MODULE:make_dir(EmptyDir), - - %% Create a non-empty directory. - ?line NonEmptyDir = filename:join(Base, "non_empty_dir"), - ?line ok = ?FILE_MODULE:make_dir(NonEmptyDir), - ?line ok = ?FILE_MODULE:write_file( - filename:join(NonEmptyDir, "a_file"), - "hello\n"), - - %% Create another non-empty directory. - ?line ADirectory = filename:join(Base, "a_directory"), - ?line ok = ?FILE_MODULE:make_dir(ADirectory), - ?line ok = ?FILE_MODULE:write_file( - filename:join(ADirectory, "a_file"), - "howdy\n\n"), - - %% Create a data file. - ?line File = filename:join(Base, "just_a_file"), - ?line ok = ?FILE_MODULE:write_file(File, "anything goes\n\n"), - - %% Move an existing directory to a non-empty directory. - ?line {error, eexist} = - ?FILE_MODULE:rename(ADirectory, NonEmptyDir), - - %% Move a root directory. - ?line {error, einval} = ?FILE_MODULE:rename("/", "arne"), - - %% Move Base into Base/new_name. - ?line {error, einval} = - ?FILE_MODULE:rename(Base, filename:join(Base, "new_name")), - - %% Overwrite a directory with a file. - ?line expect({error, eexist}, %FreeBSD (?) - {error, eisdir}, - ?FILE_MODULE:rename(File, EmptyDir)), - ?line expect({error, eexist}, %FreeBSD (?) - {error, eisdir}, - ?FILE_MODULE:rename(File, NonEmptyDir)), - - %% Move a non-existing file. - ?line NonExistingFile = - filename:join(Base, "non_existing_file"), - ?line {error, enoent} = - ?FILE_MODULE:rename(NonExistingFile, NonEmptyDir), - - %% Overwrite a file with a directory. - ?line expect({error, eexist}, %FreeBSD (?) - {error, enotdir}, - ?FILE_MODULE:rename(ADirectory, File)), - - %% Move a file to another filesystem. - %% XXX - This test case is bogus. We cannot be guaranteed that - %% the source and destination are on - %% different filesystems. - %% - %% XXX - Gross hack! - ?line Comment = - case os:type() of - {unix, _} -> - OtherFs = "/tmp", - ?line NameOnOtherFs = - filename:join(OtherFs, filename:basename(File)), - ?line {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, - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), - Comment - end. + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = ?config(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_rename"), + ok = ?FILE_MODULE:make_dir(Base), + + %% Create an empty directory. + EmptyDir = filename:join(Base, "empty_dir"), + ok = ?FILE_MODULE:make_dir(EmptyDir), + + %% Create a non-empty directory. + 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"), + + %% 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"), + + %% Create a data file. + File = filename:join(Base, "just_a_file"), + ok = ?FILE_MODULE:write_file(File, "anything goes\n\n"), + + %% Move an existing directory to a non-empty directory. + {error, eexist} = ?FILE_MODULE:rename(ADirectory, NonEmptyDir), + + %% Move a root directory. + {error, einval} = ?FILE_MODULE:rename("/", "arne"), + + %% Move Base into Base/new_name. + {error, einval} = + ?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)), + expect({error, eexist}, %FreeBSD (?) + {error, eisdir}, + ?FILE_MODULE:rename(File, NonEmptyDir)), + + %% Move a non-existing file. + NonExistingFile = filename:join(Base, "non_existing_file"), + {error, enoent} = ?FILE_MODULE:rename(NonExistingFile, NonEmptyDir), + + %% Overwrite a file with a directory. + expect({error, eexist}, %FreeBSD (?) + {error, enotdir}, + ?FILE_MODULE:rename(ADirectory, File)), + + %% Move a file to another filesystem. + %% XXX - This test case is bogus. We cannot be guaranteed that + %% the source and destination are on + %% different filesystems. + %% + %% 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 + end, + [] = flush(), + test_server:timetrap_cancel(Dog), + 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 = ?FILE_MODULE:make_dir(Base), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = ?config(priv_dir, Config), + Base = filename:join(RootDir, + atom_to_list(?MODULE)++"_e_make_dir"), + ok = ?FILE_MODULE:make_dir(Base), %% A component of the path does not exist. - ?line {error, enoent} = - ?FILE_MODULE:make_dir(filename:join([Base, "a", "b"])), + {error, enoent} = ?FILE_MODULE: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 = ?FILE_MODULE:write_file(Afile, "hello\n"), - ?line case ?FILE_MODULE: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 = ?FILE_MODULE:write_file(Afile, "hello\n"), + case ?FILE_MODULE: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 {unix, _} -> - ?line ?FILE_MODULE:write_file_info(Base, #file_info {mode=0}), - ?line {error, eacces} = - ?FILE_MODULE:make_dir(filename:join(Base, "xxxx")), - ?line ?FILE_MODULE:write_file_info( + ?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}); {win32, _} -> - ok; - vxworks -> ok end, - ?line test_server:timetrap_cancel(Dog), + test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1950,57 +2173,50 @@ e_make_dir(Config) when is_list(Config) -> 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 = test_server:temp_name(filename:join(RootDir, "e_del_dir")), - ?line io:format("Base: ~p", [Base]), - ?line ok = ?FILE_MODULE:make_dir(Base), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = ?config(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), %% Delete a non-existent directory. - ?line {error, enoent} = + {error, enoent} = ?FILE_MODULE: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 = ?FILE_MODULE:write_file(Afile, "hello\n"), - ?line {error, E1} = - expect({error, enotdir}, {error, enoent}, - ?FILE_MODULE:del_dir( - filename:join(Afile, "another_directory"))), - ?line io:format("Result: ~p", [E1]), + 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"))), + io:format("Result: ~p", [E1]), %% Delete a non-empty directory. - ?line {error, E2} = - expect({error, enotempty}, {error, eexist}, {error, eacces}, + {error, E2} = expect({error, enotempty}, {error, eexist}, {error, eacces}, ?FILE_MODULE:del_dir(Base)), - ?line io:format("Result: ~p", [E2]), + io:format("Result: ~p", [E2]), %% Remove the current directory. - ?line {error, E3} = - expect({error, einval}, + {error, E3} = expect({error, einval}, {error, eperm}, % Linux and DUX {error, eacces}, {error, ebusy}, ?FILE_MODULE:del_dir(".")), - ?line io:format("Result: ~p", [E3]), + io:format("Result: ~p", [E3]), %% No permission. case os:type() of {unix, _} -> - ?line ADirectory = filename:join(Base, "no_perm"), - ?line ok = ?FILE_MODULE:make_dir(ADirectory), - ?line ?FILE_MODULE:write_file_info( - Base, #file_info {mode=0}), - ?line {error, eacces} = ?FILE_MODULE:del_dir(ADirectory), - ?line ?FILE_MODULE:write_file_info( - Base, #file_info {mode=8#600}); + ADirectory = filename:join(Base, "no_perm"), + ok = ?FILE_MODULE:make_dir(ADirectory), + ?FILE_MODULE:write_file_info( Base, #file_info {mode=0}), + {error, eacces} = ?FILE_MODULE:del_dir(ADirectory), + ?FILE_MODULE:write_file_info( Base, #file_info {mode=8#600}); {win32, _} -> - ok; - vxworks -> ok end, - ?line [] = flush(), - ?line test_server:timetrap_cancel(Dog), + [] = flush(), + test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2271,6 +2487,57 @@ compress_errors(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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"), + 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), + + % 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), + ok. + +compress_async_crash_loop(0, _Path, _ExpectedData) -> + ok; +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), + receive + {Pid, continue} -> + exit(Pid, shutdown), + receive + {'DOWN', Ref, _, _, Reason} -> + ?line shutdown = Reason + end; + {'DOWN', Ref, _, _, Reason2} -> + test_server:fail({worker_exited, Reason2}) + after 60000 -> + exit(Pid, shutdown), + erlang:demonitor(Ref, [flush]), + test_server:fail(worker_timeout) + end, + compress_async_crash_loop(N - 1, Path, ExpectedData). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + altname(doc) -> "Test the file:altname/1 function"; altname(suite) -> @@ -2359,6 +2626,7 @@ symlinks(suite) -> []; 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_all(lists:duplicate(10000,$a)), ?line RootDir = ?config(priv_dir, Config), ?line NewDir = filename:join(RootDir, atom_to_list(?MODULE) @@ -2382,6 +2650,9 @@ symlinks(Config) when is_list(Config) -> ?line {ok, Info2} = ?FILE_MODULE:read_link_info(Alias), ?line #file_info{links=1, type=symlink} = Info2, ?line {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, @@ -2564,147 +2835,123 @@ delayed_write(doc) -> ["Tests the file open option {delayed_write, Size, Delay}"]; delayed_write(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)++"_delayed_write.txt"), - ?line Data1 = "asdfghjkl", - ?line Data2 = "qwertyuio", - ?line Data3 = "zxcvbnm,.", - ?line Size = length(Data1), - ?line Size = length(Data2), - ?line Size = length(Data3), - ?line Data1Data1 = Data1++Data1, - ?line Data1Data1Data1 = Data1Data1++Data1, - ?line Data1Data1Data1Data1 = Data1Data1++Data1Data1, + Dog = ?t:timetrap(?t:seconds(20)), + + RootDir = ?config(priv_dir, Config), + File = filename:join(RootDir, + atom_to_list(?MODULE)++"_delayed_write.txt"), + Data1 = "asdfghjkl", + Data2 = "qwertyuio", + Data3 = "zxcvbnm,.", + Size = length(Data1), + Size = length(Data2), + Size = length(Data3), + Data1Data1 = Data1++Data1, + Data1Data1Data1 = Data1Data1++Data1, + Data1Data1Data1Data1 = Data1Data1++Data1Data1, %% %% Test caching and normal close of non-raw file - ?line {ok, Fd1} = + {ok, Fd1} = ?FILE_MODULE:open(File, [write, {delayed_write, Size+1, 2000}]), - ?line ok = ?FILE_MODULE:write(Fd1, Data1), - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Fd2} = ?FILE_MODULE:open(File, [read]), - ?line case os:type() of - vxworks -> - io:format("Line ~p skipped on vxworks", [?LINE]); - _ -> - ?line eof = ?FILE_MODULE:read(Fd2, 1) - end, - ?line ok = ?FILE_MODULE:write(Fd1, Data1), % Data flush on size - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 2*Size+1), - ?line ok = ?FILE_MODULE:write(Fd1, Data1), - ?line ?t:sleep(3000), % Wait until data flush on timeout - ?line {ok, Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 3*Size+1), - ?line ok = ?FILE_MODULE:write(Fd1, Data1), - ?line ok = ?FILE_MODULE:close(Fd1), % Data flush on close - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Data1Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 4*Size+1), - ?line ok = ?FILE_MODULE:close(Fd2), + ok = ?FILE_MODULE:write(Fd1, Data1), + ?t: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 + {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 + {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 + {ok, Data1Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 4*Size+1), + ok = ?FILE_MODULE:close(Fd2), %% %% Test implicit close through exit by file owning process, %% raw file, default parameters. - ?line Parent = self(), - ?line Fun = - fun () -> - Child = self(), - Test = - fun () -> - ?line {ok, Fd} = - ?FILE_MODULE:open(File, - [raw, write, - delayed_write]), - ?line ok = ?FILE_MODULE:write(Fd, Data1), - ?line Parent ! {Child, wrote}, - ?line 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, - ?line Child1 = spawn(Fun), - ?line Mref1 = erlang:monitor(process, Child1), - ?line receive - {Child1, wrote} -> - ok; - {'DOWN', Mref1, _, _, _} = Down1a -> - ?t:fail(Down1a) - end, - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Fd3} = ?FILE_MODULE:open(File, [read]), - ?line case os:type() of - vxworks -> - io:format("Line ~p skipped on vxworks", [?LINE]); - _ -> - ?line eof = ?FILE_MODULE:read(Fd3, 1) - end, - ?line Child1 ! {Parent, continue, normal}, - ?line receive - {'DOWN', Mref1, process, Child1, normal} -> - ok; - {'DOWN', Mref1, _, _, _} = Down1b -> - ?t:fail(Down1b) - end, - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Data1} = ?FILE_MODULE:pread(Fd3, bof, Size+1), - ?line ok = ?FILE_MODULE:close(Fd3), + 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, + Child1 = spawn(Fun), + Mref1 = erlang:monitor(process, Child1), + receive + {Child1, wrote} -> + ok; + {'DOWN', Mref1, _, _, _} = Down1a -> + ?t:fail(Down1a) + end, + ?t: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}, + receive + {'DOWN', Mref1, process, Child1, normal} -> + ok; + {'DOWN', Mref1, _, _, _} = Down1b -> + ?t:fail(Down1b) + end, + ?t:sleep(1000), % Just in case the file system is slow + {ok, Data1} = ?FILE_MODULE:pread(Fd3, bof, Size+1), + ok = ?FILE_MODULE:close(Fd3), %% %% The same again, but this time with reason 'kill'. - ?line Child2 = spawn(Fun), - ?line Mref2 = erlang:monitor(process, Child2), - ?line receive - {Child2, wrote} -> - ok; - {'DOWN', Mref2, _, _, _} = Down2a -> - ?t:fail(Down2a) - end, - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line {ok, Fd4} = ?FILE_MODULE:open(File, [read]), - ?line case os:type() of - vxworks -> - io:format("Line ~p skipped on vxworks", [?LINE]); - _ -> - ?line eof = ?FILE_MODULE:read(Fd4, 1) - end, - ?line Child2 ! {Parent, continue, kill}, - ?line receive - {'DOWN', Mref2, process, Child2, kill} -> - ok; - {'DOWN', Mref2, _, _, _} = Down2b -> - ?t:fail(Down2b) - end, - ?line ?t:sleep(1000), % Just in case the file system is slow - ?line eof = ?FILE_MODULE:pread(Fd4, bof, 1), - ?line ok = ?FILE_MODULE:close(Fd4), + Child2 = spawn(Fun), + Mref2 = erlang:monitor(process, Child2), + receive + {Child2, wrote} -> + ok; + {'DOWN', Mref2, _, _, _} = Down2a -> + ?t:fail(Down2a) + end, + ?t: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}, + receive + {'DOWN', Mref2, process, Child2, kill} -> + ok; + {'DOWN', Mref2, _, _, _} = Down2b -> + ?t:fail(Down2b) + end, + ?t: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 - ?line {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, - delayed_write]), - ?line ok = ?FILE_MODULE:truncate(Fd5), - ?line ok = ?FILE_MODULE:write(Fd5, [Data1|Data2]), - ?line {ok, 0} = ?FILE_MODULE:position(Fd5, bof), - ?line ok = ?FILE_MODULE:write(Fd5, [Data3]), - ?line {ok, Data2} = ?FILE_MODULE:read(Fd5, Size+1), - ?line {ok, 0} = ?FILE_MODULE:position(Fd5, bof), - ?line Data3Data2 = Data3++Data2, - ?line {ok, Data3Data2} = ?FILE_MODULE:read(Fd5, 2*Size+1), - ?line ok = ?FILE_MODULE:close(Fd5), + {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, + delayed_write]), + ok = ?FILE_MODULE:truncate(Fd5), + ok = ?FILE_MODULE:write(Fd5, [Data1|Data2]), + {ok, 0} = ?FILE_MODULE:position(Fd5, bof), + ok = ?FILE_MODULE:write(Fd5, [Data3]), + {ok, Data2} = ?FILE_MODULE:read(Fd5, Size+1), + {ok, 0} = ?FILE_MODULE:position(Fd5, bof), + Data3Data2 = Data3++Data2, + {ok, Data3Data2} = ?FILE_MODULE:read(Fd5, 2*Size+1), + ok = ?FILE_MODULE:close(Fd5), %% - ?line [] = flush(), - ?line ?t:timetrap_cancel(Dog), - ?line case os:type() of - vxworks -> - {comment, "Some lines skipped on vxworks"}; - _ -> - ok - end. + [] = flush(), + ?t:timetrap_cancel(Dog), + ok. pid2name(doc) -> "Tests file:pid2name/1."; @@ -3300,6 +3547,49 @@ otp_5814(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +otp_10852(suite) -> + []; +otp_10852(doc) -> + ["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), + B = filename:join(Dir, <<"\xE4">>), + ok = rpc_call(Node, get_cwd, [B]), + {error, no_translation} = rpc_call(Node, set_cwd, [B]), + ok = rpc_call(Node, delete, [B]), + ok = rpc_call(Node, rename, [B, B]), + ok = rpc_call(Node, read_file_info, [B]), + ok = rpc_call(Node, read_link_info, [B]), + ok = rpc_call(Node, read_link, [B]), + ok = rpc_call(Node, write_file_info, [B,#file_info{}]), + ok = rpc_call(Node, list_dir, [B]), + ok = rpc_call(Node, list_dir_all, [B]), + ok = rpc_call(Node, read_file, [B]), + ok = rpc_call(Node, make_link, [B,B]), + ok = rpc_call(Node, make_symlink, [B,B]), + ok = rpc_call(Node, delete, [B]), + ok = rpc_call(Node, make_dir, [B]), + ok = rpc_call(Node, del_dir, [B]), + ok = rpc_call(Node, write_file, [B,B]), + {ok, Fd} = rpc_call(Node, open, [B,[read]]), + ok = rpc_call(Node, close, [Fd]), + {ok,0} = rpc_call(Node, copy, [B,B]), + {ok, Fd2, B} = rpc_call(Node, path_open, [["."], B, [read]]), + ok = rpc_call(Node, close, [Fd2]), + true = test_server:stop_node(Node), + ok. + +rpc_call(N, F, As) -> + case rpc:call(N, ?FILE_MODULE, F, As) of + {error, enotsup} -> ok; + {error, enoent} -> ok; + {error, badarg} -> ok; + Else -> Else + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + large_file(suite) -> []; large_file(doc) -> @@ -4016,3 +4306,18 @@ disc_free(Path) -> memsize() -> {Tot,_Used,_} = memsup:get_memory_data(), Tot. + +%%%----------------------------------------------------------------- +%%% Utilities +rm_rf(Mod,Dir) -> + case Mod:read_link_info(Dir) of + {ok, #file_info{type = directory}} -> + {ok, Content} = Mod:list_dir_all(Dir), + [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ], + Mod:del_dir(Dir), + ok; + {ok, #file_info{}} -> + Mod:delete(Dir); + _ -> + ok + end. diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 3aa010a708..0c8082026a 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -1,8 +1,9 @@ -module(file_name_SUITE). +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -196,7 +197,10 @@ normal(Config) when is_list(Config) -> put(file_module,prim_file), ok = check_normal(prim_file), put(file_module,file), - ok = check_normal(file) + ok = check_normal(file), + %% If all is good, delete dir again (avoid hanging dir on windows) + rm_rf(file,"normal_dir"), + ok after file:set_cwd(Dir) end. @@ -218,7 +222,10 @@ icky(Config) when is_list(Config) -> put(file_module,prim_file), ok = check_icky(prim_file), put(file_module,file), - ok = check_icky(file) + ok = check_icky(file), + %% If all is good, delete dir again (avoid hanging dir on windows) + rm_rf(file,"icky_dir"), + ok after file:set_cwd(Dir) end @@ -242,7 +249,11 @@ very_icky(Config) when is_list(Config) -> {skipped,"VM needs to be started in Unicode filename mode"}; ok -> put(file_module,file), - ok = check_very_icky(file) + ok = check_very_icky(file), + %% If all is good, delete dir again + %% (avoid hanging dir on windows) + rm_rf(file,"very_icky_dir"), + ok end after file:set_cwd(Dir) @@ -336,12 +347,12 @@ check_normal(Mod) -> check_icky(Mod) -> {ok,Dir} = Mod:get_cwd(), try - ?line true=(length("���") =:= 3), + ?line true=(length("åäö") =:= 3), ?line UniMode = file:native_name_encoding() =/= latin1, ?line make_icky_dir(Mod), - ?line {ok, L0} = Mod:list_dir("."), + {ok, L0} = Mod:list_dir_all("."), ?line L1 = lists:sort(L0), - io:format("~p ~p~n",[L1,list(icky_dir())]), + 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), @@ -356,66 +367,59 @@ check_icky(Mod) -> ?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 ], - ?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ], - ?line chk_cre_dir(Mod,[{directory,"���_dir",icky_dir()}]), + [ {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 {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"), - {OS,TYPE} = os:type(), + ?line rm_r2(Mod,"åäö_dir"), + {OS,_} = os:type(), % 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(<<"���">>), - ?line {ok,[Treated]} = Mod:list_dir("."), - ?line ok = Mod:delete(<<"���">>), + ?line chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]), + ?line ok = Mod:set_cwd("åäö_dir"), + ?line ok = Mod:write_file(<<"ååå">>,<<"hello">>), + ?line 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"); + ?line rm_r2(Mod,"åäö_dir"); false -> ok end, - ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"���_dir">>),icky_dir()}]), + ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]), if UniMode and (OS =/= win32) -> - ?line {error,enoent} = Mod:set_cwd("���_dir"); + ?line {error,enoent} = Mod:set_cwd("åäö_dir"); true -> ok end, - ?line ok = Mod:set_cwd(treat_icky(<<"���_dir">>)), - ?line {ok, NowAt2} = Mod:get_cwd(), - io:format("~p~n",[NowAt2]), - % Cannot create raw unicode-breaking filenames on windows or macos - ?line true = ((((not UniMode) or (OS =:= win32) or (TYPE=:=darwin)) and is_list(NowAt2)) orelse ((UniMode) and is_binary(NowAt2))), - ?line true = BeginAt =/= NowAt2, - ?line ok = Mod:set_cwd(".."), ?line {ok,BeginAt} = Mod:get_cwd(), - ?line rm_r2(Mod,conv(treat_icky(<<"���_dir">>))), 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 = 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�">>)); + ?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 end, @@ -430,42 +434,42 @@ check_icky(Mod) -> ?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"), + ?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"), - ?line Mod:rename("���2",treat_icky(<<"���_fil1">>)), - ?line {ok, <<"���2">>} = Mod:read_file(treat_icky(<<"���_fil1">>)), + ?line Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)), + ?line {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)), if UniMode and (OS =/= win32) -> - {error,enoent} = Mod:read_file("���_fil1"); + {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">>)), + ?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">>)), - ?line {ok,FI} = Mod:read_file_info("���2"), + ?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"), + ?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"), - ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"���5">>)), + ?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">>)), + ?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 after Mod:set_cwd(Dir), @@ -475,7 +479,7 @@ check_icky(Mod) -> check_very_icky(Mod) -> {ok,Dir} = Mod:get_cwd(), try - ?line true=(length("���") =:= 3), + ?line true=(length("åäö") =:= 3), ?line UniMode = file:native_name_encoding() =/= latin1, if not UniMode -> @@ -484,7 +488,7 @@ check_very_icky(Mod) -> ok end, ?line make_very_icky_dir(Mod), - ?line {ok, L0} = Mod:list_dir("."), + {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(), @@ -493,11 +497,12 @@ check_very_icky(Mod) -> ?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(SymL)) || {SymL,Targ,_} <- 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 {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), @@ -514,16 +519,16 @@ check_very_icky(Mod) -> ?line {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 = 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�">>), + 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�">>); + ?line {error,enoent} = Mod:read_file(<<"nisseö">>), + ?line {error,enoent} = Mod:read_link_info(<<"nisseö">>); false -> ok end, @@ -540,10 +545,10 @@ check_very_icky(Mod) -> 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 {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 {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]), ?line {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"), ?line {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]), @@ -558,33 +563,6 @@ check_very_icky(Mod) -> FI#file_info{mode = NewMode2}), ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info([956,965,963,954,959,49]), - ?line NumOK0 = case has_links() of - true -> 5; - false -> 3 - end, - ?line NumNOK0 = case has_links() of - true -> 4; - false -> 3 - end, - ?line {NumOK,NumNOK} = case is_binary(treat_icky(<<"foo">>)) of - false -> - {NumOK0+NumNOK0,0}; - true -> - {NumOK0,NumNOK0} - end, - ?line {NumOK,NumNOK} = filelib:fold_files(".",".*",true,fun(_F,{N,M}) when is_list(_F) -> io:format("~ts~n",[_F]),{N+1,M}; (_F,{N,M}) -> io:format("~p~n",[_F]),{N,M+1} end,{0,0}), - ?line ok = filelib:fold_files(".",[1076,1089,1072,124,46,42],true,fun(_F,_) -> ok end,false), - ?line SF3 = unicode:characters_to_binary("���subfil3", - file:native_name_encoding()), - ?line SF2 = case treat_icky(<<"���subfil2">>) of - LF2 when is_list(LF2) -> - unicode:characters_to_binary(LF2, - file:native_name_encoding()); - BF2 -> - BF2 - end, - ?line Sorted = lists:sort([SF3,SF2]), - ?line Sorted = lists:sort(filelib:wildcard("*",<<"���subdir2">>)), ok catch throw:need_unicode_mode -> @@ -603,7 +581,7 @@ check_very_icky(Mod) -> rm_rf(Mod,Dir) -> case Mod:read_link_info(Dir) of {ok, #file_info{type = directory}} -> - {ok, Content} = Mod:list_dir(Dir), + {ok, Content} = Mod:list_dir_all(Dir), [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ], Mod:del_dir(Dir), ok; @@ -618,7 +596,7 @@ rm_r(Mod,Dir) -> case Mod:read_link_info(Dir) of {ok, #file_info{type = directory}} -> {ok,#file_info{type = directory}} = Mod:read_file_info(Dir), - {ok, Content} = Mod:list_dir(Dir), + {ok, Content} = Mod:list_dir_all(Dir), [ true = is_list(Part) || Part <- Content ], [ true = is_list(filename:join(Dir,Part)) || Part <- Content ], [ rm_r(Mod,filename:join(Dir,C)) || C <- Content ], @@ -636,7 +614,7 @@ rm_r2(Mod,Dir) -> case Mod:read_link_info(Dir) of {ok, #file_info{type = directory}} -> {ok,#file_info{type = directory}} = Mod:read_file_info(Dir), - {ok, Content} = Mod:list_dir(Dir), + {ok, Content} = Mod:list_dir_all(Dir), UniMode = file:native_name_encoding() =/= latin1, [ true = (is_list(Part) orelse UniMode) || Part <- Content ], [ true = (is_list(filename:join(Dir,Part)) orelse UniMode) || Part <- Content ], @@ -744,26 +722,26 @@ hopeless_darwin() -> icky_dir() -> [{regular,"fil1","fil1"}, - {regular,"���2","���2"}] ++ + {regular,"åäö2","åäö2"}] ++ case has_links() of true -> - [{regular,"���3","���2"}, - {symlink,"���4","���2"}]; + [{regular,"åäö3","åäö2"}, + {symlink,"åäö4","åäö2"}]; false -> [] end ++ - [{regular,treat_icky(<<"���5">>),"���5"}] ++ + [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++ case has_links() of true -> - [{symlink,treat_icky(<<"���6">>),treat_icky(<<"���5">>)}]; + [{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"}]}]. + [{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"), @@ -774,26 +752,26 @@ make_very_icky_dir(Mod) -> very_icky_dir() -> [{regular,"fil1","fil1"}, - {regular,[956,965,963,954,959,49],"���2"}] ++ + {regular,[956,965,963,954,959,49],"åäö2"}] ++ case has_links() of true -> - [{regular,[956,965,963,954,959,50],"���2"}, + [{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"}] ++ + [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++ case has_links() of true -> - [{symlink,treat_icky(<<"���6">>),treat_icky(<<"���5">>)}]; + [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}]; false -> [] end ++ - [{directory,treat_icky(<<"���subdir2">>), - [{regular,treat_icky(<<"���subfil2">>),"���subfil12"}, - {regular,"���subfil3","���subfil13"}]}, + [{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"}]}]. + [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}]. %% Some OS'es simply do not allow non UTF8 filenames treat_icky(Bin) -> diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index bcc2f0b840..e89cb44797 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -31,22 +31,24 @@ [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, - basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1, open_multihoming_ipv4_socket/1, open_unihoming_ipv6_socket/1, open_multihoming_ipv6_socket/1, - open_multihoming_ipv4_and_ipv6_socket/1]). + open_multihoming_ipv4_and_ipv6_socket/1, + basic_stream/1, xfer_stream_min/1, peeloff_active_once/1, + peeloff_active_true/1, buffers/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [basic, api_open_close, api_listen, api_connect_init, api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6, - basic_stream, xfer_stream_min, peeloff, buffers, open_multihoming_ipv4_socket, open_unihoming_ipv6_socket, open_multihoming_ipv6_socket, - open_multihoming_ipv4_and_ipv6_socket]. + open_multihoming_ipv4_and_ipv6_socket, + basic_stream, xfer_stream_min, peeloff_active_once, + peeloff_active_true, buffers]. groups() -> []. @@ -923,23 +925,34 @@ do_from_other_process(Fun) -> end. +peeloff_active_once(doc) -> + "Peel off an SCTP stream socket ({active,once})"; +peeloff_active_once(suite) -> + []; + +peeloff_active_once(Config) -> + peeloff(Config, [{active,once}]). -peeloff(doc) -> - "Peel off an SCTP stream socket"; -peeloff(suite) -> +peeloff_active_true(doc) -> + "Peel off an SCTP stream socket ({active,true})"; +peeloff_active_true(suite) -> []; -peeloff(Config) when is_list(Config) -> + +peeloff_active_true(Config) -> + peeloff(Config, [{active,true}]). + +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}], Timeout), + ?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}], Timeout), + ?line S2 = socket_open([{ifaddr,Addr}|SockOpts], Timeout), ?line ?LOGVAR(S2), ?line P2 = socket_call(S2, get_port), ?line ?LOGVAR(P2), @@ -983,7 +996,7 @@ peeloff(Config) when is_list(Config) -> socket_bailout([S1,S2]) end, %% - ?line S3 = socket_peeloff(Socket1, S1Ai, Timeout), + ?line S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout), ?line ?LOGVAR(S3), ?line P3_X = socket_call(S3, get_port), ?line ?LOGVAR(P3_X), @@ -1302,8 +1315,15 @@ recv_comm_up_eventually(S) -> %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% socket gen_server ultra light -socket_open(SocketOpts, Timeout) -> - Opts = [{type,seqpacket},{active,once},binary|SocketOpts], +socket_open(SockOpts0, Timeout) -> + SockOpts = + case lists:keyfind(active,1,SockOpts0) of + false -> + [{active,once}|SockOpts0]; + _ -> + SockOpts0 + end, + Opts = [{type,seqpacket},binary|SockOpts], Starter = fun () -> {ok,Socket} = @@ -1312,8 +1332,8 @@ socket_open(SocketOpts, Timeout) -> end, s_start(Starter, Timeout). -socket_peeloff(Socket, AssocId, Timeout) -> - Opts = [{active,once},binary], +socket_peeloff(Socket, AssocId, SocketOpts, Timeout) -> + Opts = [binary|SocketOpts], Starter = fun () -> {ok,NewSocket} = @@ -1379,8 +1399,7 @@ s_req(S, Req) -> {'DOWN',Mref,_,_,Error} -> exit(Error); {S,Mref,Reply} -> - erlang:demonitor(Mref), - receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end, + erlang:demonitor(Mref, [flush]), Reply end. diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl index 5bbaeb02ad..9bc66dbae0 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-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -190,24 +190,19 @@ echo_test_1(SockOpts, EchoFun, Config0) -> ok. echo_packet(SockOpts, EchoFun, Opts) -> - ?line Type = - case lists:keysearch(type, 1, Opts) of - {value, {type, T}} -> - T; - _ -> - {value, {packet, T}} = lists:keysearch(packet, 1, SockOpts), - T - end, + Type = case lists:keysearch(type, 1, Opts) of + {value, {type, T}} -> + T; + _ -> + {value, {packet, T}} = lists:keysearch(packet, 1, SockOpts), + T + end, %% Connect to the echo server. - ?line EchoPort = ?config(echo_port, Opts), - ?line {ok, Echo} = gen_tcp:connect(localhost, EchoPort, SockOpts), + EchoPort = ?config(echo_port, Opts), + {ok, Echo} = gen_tcp:connect(localhost, EchoPort, SockOpts), - ?line SlowEcho = - case os:type() of - vxworks -> true; - _ -> lists:member(slow_echo, Opts) - end, + SlowEcho = lists:member(slow_echo, Opts), case Type of http -> diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 1592399996..ee271fbdfa 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -42,13 +42,22 @@ 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, + otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, wrapping_oct/1, otp_9389/1]). %% Internal exports. -export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1, - otp_7731_server/1, zombie_server/2]). - + oct_acceptor/1, + otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]). + +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(_Func, Config) when is_list(Config) -> Dog = test_server:timetrap(test_server:seconds(240)), [{watchdog, Dog}|Config]. @@ -75,6 +84,7 @@ all() -> killing_acceptor, killing_multi_acceptors, killing_multi_acceptors2, several_accepts_in_one_go, accept_system_limit, active_once_closed, send_timeout, send_timeout_active, otp_7731, + wrapping_oct, zombie_sockets, otp_7816, otp_8102, otp_9389]. groups() -> @@ -340,39 +350,23 @@ no_accept(doc) -> "a tcp_closed message."]; no_accept(suite) -> []; no_accept(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Too tough for vxworks"}; - _ -> - no_accept2() + {ok, L} = gen_tcp:listen(0, []), + {ok, {_, Port}} = inet:sockname(L), + {ok, Client} = gen_tcp:connect(localhost, Port, []), + ok = gen_tcp:close(L), + receive + {tcp_closed, Client} -> + ok + after 5000 -> + ?line test_server:fail(never_closed) + end. -no_accept2() -> - ?line {ok, L} = gen_tcp:listen(0, []), - ?line {ok, {_, Port}} = inet:sockname(L), - ?line {ok, Client} = gen_tcp:connect(localhost, Port, []), - ?line ok = gen_tcp:close(L), - ?line receive - {tcp_closed, Client} -> - ok - after 5000 -> - ?line test_server: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) -> []; close_with_pending_output(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skipped,"Too tough for vxworks"}; - _ -> - close_with_pending_output2() - end. - -close_with_pending_output2() -> ?line {ok, L} = gen_tcp:listen(0, [binary, {active, false}]), ?line {ok, {_, Port}} = inet:sockname(L), ?line Packets = 16, @@ -423,22 +417,16 @@ otp_3924(doc) -> otp_3924(suite) -> []; otp_3924(Config) when is_list(Config) -> MaxDelay = (case has_superfluous_schedulers() of - true -> 4; - false -> 1 - end - * case {erlang:system_info(debug_compiled), - erlang:system_info(lock_checking)} of - {true, _} -> 6; - {_, true} -> 2; - _ -> 1 - end * ?OTP_3924_MAX_DELAY), - case os:type() of - vxworks -> -%% {skip,"Too tough for vxworks"}; - otp_3924_1(MaxDelay); - _ -> - otp_3924_1(MaxDelay) - end. + true -> 4; + false -> 1 + end + * case {erlang:system_info(debug_compiled), + erlang:system_info(lock_checking)} of + {true, _} -> 6; + {_, true} -> 2; + _ -> 1 + end * ?OTP_3924_MAX_DELAY), + otp_3924_1(MaxDelay). otp_3924_1(MaxDelay) -> Dog = test_server:timetrap(test_server:seconds(240)), @@ -559,26 +547,18 @@ otp_3924_sender(Receiver, Host, Port, Data) -> data_before_close(doc) -> ["Tests that a huge amount of data can be received before a close."]; data_before_close(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Too tough for vxworks"}; - _ -> - data_before_close2() - end. - -data_before_close2() -> - ?line {ok, L} = gen_tcp:listen(0, [binary]), - ?line {ok, {_, TcpPort}} = inet:sockname(L), - ?line Bytes = 256*1024, - ?line spawn_link(fun() -> huge_sender(TcpPort, Bytes) end), - ?line {ok, A} = gen_tcp:accept(L), - ?line case count_bytes_recv(A, 0) of - {Bytes, Result} -> - io:format("Result: ~p", [Result]); - {Wrong, Result} -> - io:format("Result: ~p", [Result]), - test_server:fail({wrong_count, Wrong}) - end, + {ok, L} = gen_tcp:listen(0, [binary]), + {ok, {_, TcpPort}} = inet:sockname(L), + Bytes = 256*1024, + spawn_link(fun() -> huge_sender(TcpPort, Bytes) end), + {ok, A} = gen_tcp:accept(L), + case count_bytes_recv(A, 0) of + {Bytes, Result} -> + io:format("Result: ~p", [Result]); + {Wrong, Result} -> + io:format("Result: ~p", [Result]), + test_server:fail({wrong_count, Wrong}) + end, ok. count_bytes_recv(Sock, Total) -> @@ -611,32 +591,24 @@ get_status(Config) when is_list(Config) -> ?line {ok,{socket,Pid,_,_}} = gen_tcp:listen(5678,[]), ?line {status,Pid,_,_} = sys:get_status(Pid). +-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(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Too tough for vxworks"}; - _ -> - iter_max_socks2() - end. - --define(RECOVER_SLEEP, 60000). --define(RETRY_SLEEP, 15000). + N = case os:type() of {win32,_} -> 10; _ -> 20 end, + %% Run on a different node in order to limit the effect if this test fails. + Dir = filename:dirname(code:which(?MODULE)), + {ok,Node} = test_server:start_node(test_iter_max_socks,slave, + [{args,"+Q 2048 -pa " ++ Dir}]), + L = rpc:call(Node,?MODULE,do_iter_max_socks,[N, initalize]), + test_server:stop_node(Node), -iter_max_socks2() -> - ?line N = - case os:type() of - vxworks -> - 10; - _ -> - 20 - end, - L = do_iter_max_socks(N, initalize), - ?line io:format("Result: ~p",[L]), - ?line all_equal(L), - ?line {comment, "Max sockets: " ++ integer_to_list(hd(L))}. + io:format("Result: ~p",[L]), + all_equal(L), + {comment, "Max sockets: " ++ integer_to_list(hd(L))}. do_iter_max_socks(0, _) -> []; @@ -2619,3 +2591,71 @@ otp_9389_loop(S, OrigLinkHdr, State) -> 3000 -> ?line error({timeout,header}) end. + +wrapping_oct(doc) -> + "Check that 64bit octet counters work."; +wrapping_oct(suite) -> + []; +wrapping_oct(Config) when is_list(Config) -> + Dog = test_server:timetrap(test_server:seconds(600)), + {ok,Sock} = gen_tcp:listen(0,[{active,false},{mode,binary}]), + {ok,Port} = inet:port(Sock), + spawn_link(?MODULE,oct_acceptor,[Sock]), + Res = oct_datapump(Port,16#1FFFFFFFF), + gen_tcp:close(Sock), + test_server:timetrap_cancel(Dog), + ok = Res, + ok. + +oct_datapump(Port,N) -> + {ok,Sock} = gen_tcp:connect("localhost",Port, + [{active,false},{mode,binary}]), + oct_pump(Sock,N,binary:copy(<<$a:8>>,100000),0). + +oct_pump(S,N,_,_) when N =< 0 -> + gen_tcp:close(S), + ok; +oct_pump(S,N,Bin,Last) -> + case gen_tcp:send(S,Bin) of + ok -> + {ok,Stat}=inet:getstat(S), + {_,R}=lists:keyfind(send_oct,1,Stat), + case (R < Last) of + true -> + io:format("ERROR (output) ~p < ~p~n",[R,Last]), + output_counter_error; + false -> + oct_pump(S,N-byte_size(Bin),Bin,R) + end; + _ -> + input_counter_error + end. + + +oct_acceptor(Sock) -> + {ok,Data} = gen_tcp:accept(Sock), + oct_aloop(Data,0,0). + +oct_aloop(S,X,Times) -> + case gen_tcp:recv(S,0) of + {ok,_} -> + {ok,Stat}=inet:getstat(S), + {_,R}=lists:keyfind(recv_oct,1,Stat), + case (R < X) of + true -> + io:format("ERROR ~p < ~p~n",[R,X]), + gen_tcp:close(S), + input_counter_error; + false -> + case Times rem 16#FFFFF of + 0 -> + io:format("Read: ~p~n",[R]); + _ -> + ok + end, + oct_aloop(S,R,Times+1) + end; + _ -> + gen_tcp:close(S), + closed + end. diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index 2354f8accd..cd768813cf 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -1,7 +1,8 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -442,7 +443,7 @@ open_fd(suite) -> open_fd(doc) -> ["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?", + Msg = "Det gör ont när knoppar brista. Varför skulle annars våren tveka?", Addr = {127,0,0,1}, {ok,S1} = gen_udp:open(0), {ok,P2} = inet:port(S1), diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl index 1cc3eb7c79..9428a38660 100644 --- a/lib/kernel/test/global_SUITE.erl +++ b/lib/kernel/test/global_SUITE.erl @@ -91,27 +91,9 @@ end_per_group(_GroupName, Config) -> Config. init_per_suite(Config) -> - - %% Copied from test_server_ctrl ln 647, we have to do this here as - %% the test_server only does this when run without common_test - global:sync(), - case global:whereis_name(test_server) of - undefined -> - io:format(user, "Registering test_server globally!~n",[]), - global:register_name(test_server, whereis(test_server_ctrl)); - Pid -> - case node() of - N when N == node(Pid) -> - io:format(user, "Warning: test_server already running!\n", []), - global:re_register_name(test_server,self()); - _ -> - ok - end - end, Config. end_per_suite(_Config) -> - global:unregister_name(test_server), ok. @@ -135,8 +117,7 @@ end_per_testcase(_Case, Config) -> ?line write_high_level_trace(Config), ?line _ = gen_server:call(global_name_server, high_level_trace_stop, infinity), - ?line[global:unregister_name(N) || N <- global:registered_names(), - N =/= test_server], + [global:unregister_name(N) || N <- global:registered_names()], ?line InitRegistered = ?registered, ?line Registered = registered(), ?line [io:format("~s local names: ~p~n", [What, N]) || @@ -1840,16 +1821,16 @@ do_otp_3162(StartFun, Config) -> ?line ?UNTIL ([Cp3] =:= lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]), - ?line ?UNTIL([kalle, test_server, vera] =:= + ?UNTIL([kalle, vera] =:= lists:sort(rpc:call(Cp1, global, registered_names, []))), ?line ?UNTIL ([Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]), - ?line ?UNTIL([stina, test_server, vera] =:= + ?UNTIL([stina, vera] =:= lists:sort(rpc:call(Cp2, global, registered_names, []))), ?line ?UNTIL ([Cp1, Cp2] =:= lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]), - ?line ?UNTIL([kalle, stina, test_server, vera] =:= + ?UNTIL([kalle, stina, vera] =:= lists:sort(rpc:call(Cp3, global, registered_names, []))), ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1]), @@ -1860,17 +1841,17 @@ do_otp_3162(StartFun, Config) -> ?line ?UNTIL(begin NN = lists:sort(rpc:call(Cp1, global, registered_names, [])), - [kalle, stina, test_server, vera] =:= NN + [kalle, stina, vera] =:= NN end), ?line ?UNTIL ([Cp1, Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]), - ?line ?UNTIL([kalle, stina, test_server, vera] =:= + ?UNTIL([kalle, stina, vera] =:= lists:sort(rpc:call(Cp2, global, registered_names, []))), ?line ?UNTIL ([Cp1, Cp2] =:= lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]), - ?line ?UNTIL([kalle, stina, test_server, vera] =:= + ?UNTIL([kalle, stina, vera] =:= lists:sort(rpc:call(Cp3, global, registered_names, []))), write_high_level_trace(Config), @@ -3821,7 +3802,7 @@ start_node_rel(Name0, Rel, Config) -> Name = node_name(Name0, Config), {Release, Compat} = case Rel of this -> - {[this], "+R8"}; + {[this], ""}; Rel when is_atom(Rel) -> {[{release, atom_to_list(Rel)}], ""}; RelList -> @@ -4154,7 +4135,7 @@ init_condition(Config) -> {"Global Locks (ETS)", global_locks}, {"Global Pid Names (ETS)", global_pid_names}, {"Global Pid Ids (ETS)", global_pid_ids}]], - ?UNTIL([test_server] =:= global:registered_names()), + ?UNTIL([] =:= global:registered_names()), ?UNTIL([] =:= nodes()), ?UNTIL([node()] =:= get_known(node())), ok. diff --git a/lib/kernel/test/global_SUITE_data/global_trace.erl b/lib/kernel/test/global_SUITE_data/global_trace.erl index 4f253baac4..00bacf8f54 100644 --- a/lib/kernel/test/global_SUITE_data/global_trace.erl +++ b/lib/kernel/test/global_SUITE_data/global_trace.erl @@ -1,7 +1,8 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -122,12 +123,12 @@ state(Else) -> %%% {ops,Ops}] %%% NewKnown = Known ++ AddedNodes %%% AddedNodes = NewNodes -- Known -%%% NewNodes �r h�r den man f�rhandlat med plus de noder den k�nner till. +%%% NewNodes är här den man förhandlat med plus de noder den känner till. %%% {added, AddedNodes}, Extra = [{ops,Ops}] %%% NewKnown = Known ++ AddedNodes -%%% Den (passiva) noden f�r Nodes som �r NewNodes -%%% hos den f�rhandlande. Sedan: AddedNodes = (Nodes -- Known) -- [node()]. -%%% Det �r som hos f�rhandlaren. +%%% Den (passiva) noden får Nodes som är NewNodes +%%% hos den förhandlande. Sedan: AddedNodes = (Nodes -- Known) -- [node()]. +%%% Det är som hos förhandlaren. %%% {nodes_changed, {New,Old}} %%% Every now and then the list [node() | nodes()] is checked for updates. %%% New are the nodes that global does not know of (yet). diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl index 4a8033e3a3..320b23bea1 100644 --- a/lib/kernel/test/heart_SUITE.erl +++ b/lib/kernel/test/heart_SUITE.erl @@ -83,10 +83,10 @@ init_per_suite(Config) when is_list(Config) -> {win32, windows} -> {skipped, "No use to run on Windows 95/98"}; _ -> - Config + ignore_cores:init(Config) end. end_per_suite(Config) when is_list(Config) -> - Config. + ignore_cores:fini(Config). start_check(Type, Name) -> @@ -188,8 +188,20 @@ reboot(Config) when is_list(Config) -> %% Check that a node is up and running after a crash. %% This test exhausts the atom table on the remote node. %% ERL_CRASH_DUMP_SECONDS=0 will force beam not to dump an erl_crash.dump. +%% 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 + node_start_immediately_after_crash_test(Config2) + after + ignore_cores:restore(Config2) + end. + + +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 = rpc:call(Node, heart, set_cmd, @@ -228,8 +240,19 @@ node_start_immediately_after_crash(Config) when is_list(Config) -> %% This test exhausts the atom table on the remote node. %% ERL_CRASH_DUMP_SECONDS=10 will force beam %% to only dump an erl_crash.dump for 10 seconds. +%% 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 + node_start_soon_after_crash_test(Config2) + after + ignore_cores:restore(Config2) + 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 = rpc:call(Node, heart, set_cmd, @@ -345,13 +368,8 @@ dont_drop(doc) -> "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... - case os:type() of - vxworks -> - {comment, "No use to run with slaves on other nodes..."}; - _ -> - [ok,ok,ok,ok,ok,ok,ok,ok,ok,ok] = do_dont_drop(Config,10), - ok - end. + [ok,ok,ok,ok,ok,ok,ok,ok,ok,ok] = do_dont_drop(Config,10), + ok. do_dont_drop(_,0) -> []; do_dont_drop(Config,N) -> @@ -408,13 +426,7 @@ kill_pid(doc) -> ["Tests that heart kills the old erlang node before executing ", "heart command."]; kill_pid(Config) when is_list(Config) -> - %%% Have to do it some times to make it happen... - case os:type() of - vxworks -> - {comment, "No use to run with slaves on other nodes..."}; - _ -> - ok = do_kill_pid(Config) - end. + ok = do_kill_pid(Config). do_kill_pid(_Config) -> Name = heart_test, diff --git a/lib/kernel/test/heart_SUITE_data/simple_echo.c b/lib/kernel/test/heart_SUITE_data/simple_echo.c index 0093dbce9b..a92bb8af95 100644 --- a/lib/kernel/test/heart_SUITE_data/simple_echo.c +++ b/lib/kernel/test/heart_SUITE_data/simple_echo.c @@ -2,11 +2,7 @@ #include <stdlib.h> #include <string.h> -#ifdef VXWORKS -int simple_echo(void){ -#else int main(void){ -#endif int x; while((x = getchar()) != EOF){ putchar(x); @@ -14,4 +10,3 @@ int main(void){ } return 0; } - diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl new file mode 100644 index 0000000000..d4bb02df3f --- /dev/null +++ b/lib/kernel/test/ignore_cores.erl @@ -0,0 +1,158 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : ignore_cores.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : +%%% +%%% Created : 11 Feb 2008 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- + +-module(ignore_cores). + +-include_lib("test_server/include/test_server.hrl"). + +-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]). + +-record(ignore_cores, {org_cwd, + org_path, + org_pwd_env, + ign_dir = false, + cores_dir = false}). + +%% +%% Takes a testcase config +%% + +init(Config) -> + {ok, OrgCWD} = file:get_cwd(), + [{ignore_cores, + #ignore_cores{org_cwd = OrgCWD, + org_path = code:get_path(), + org_pwd_env = os:getenv("PWD")}} + | lists:keydelete(ignore_cores, 1, Config)]. + +fini(Config) -> + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + ok = file:set_cwd(OrgCWD), + true = code:set_path(OrgPath), + case OrgPWD of + false -> ok; + _ -> true = os:putenv("PWD", OrgPWD) + end, + lists:keydelete(ignore_cores, 1, Config). + +setup(Suite, Testcase, Config) -> + setup(Suite, Testcase, Config, false). + +setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite), + is_atom(Testcase), + is_list(Config) -> + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath), + true = code:set_path(Path), + PrivDir = ?config(priv_dir, Config), + IgnDir = filename:join([PrivDir, + atom_to_list(Suite) + ++ "_" + ++ atom_to_list(Testcase) + ++ "_wd"]), + ok = file:make_dir(IgnDir), + case SetCwd of + false -> + ok; + _ -> + ok = file:set_cwd(IgnDir), + OrgPWD = case os:getenv("PWD") of + false -> false; + PWD -> + os:putenv("PWD", IgnDir), + PWD + end + 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 + {{unix,darwin}, true} -> + filelib:fold_files("/cores", + "^core.*$", + false, + fun (C,Cs) -> [C|Cs] end, + []); + _ -> + false + end, + lists:keyreplace(ignore_cores, + 1, + Config, + {ignore_cores, + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD, + ign_dir = IgnDir, + cores_dir = CoresDir}}). + +restore(Config) -> + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD, + ign_dir = IgnDir, + cores_dir = CoresDir} = ?config(ignore_cores, Config), + try + case CoresDir of + false -> + ok; + _ -> + %% Move cores dumped by these testcases in /cores + %% to cwd. + lists:foreach(fun (C) -> + case lists:member(C, CoresDir) of + true -> ok; + _ -> + Dst = filename:join( + [IgnDir, + filename:basename(C)]), + {ok, _} = file:copy(C, Dst), + file:delete(C) + end + end, + filelib:fold_files("/cores", + "^core.*$", + false, + fun (C,Cs) -> [C|Cs] end, + [])) + end + after + catch file:set_cwd(OrgCWD), + catch code:set_path(OrgPath), + case OrgPWD of + false -> ok; + _ -> catch os:putenv("PWD", OrgPWD) + end + end. + + +dir(Config) -> + #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config), + Dir. diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index 7241b093d0..62ba95e1a3 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,7 +37,8 @@ gethostnative_soft_restart/0, gethostnative_soft_restart/1, gethostnative_debug_level/0, gethostnative_debug_level/1, getif/1, - getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1]). + getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1, + parse_strict_address/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0]). @@ -52,7 +53,7 @@ all() -> t_gethostnative, gethostnative_parallell, cname_loop, gethostnative_debug_level, gethostnative_soft_restart, getif, getif_ifr_name_overflow, getservbyname_overflow, - getifaddrs]. + getifaddrs, parse_strict_address]. groups() -> [{parse, [], [parse_hosts, parse_address]}]. @@ -66,7 +67,7 @@ required(v6) -> {require, test_dummy_ipv6_host}]; required(hosts) -> case os:type() of - {OS, _} when OS =:= win32; OS =:= vxworks -> + {OS, _} when OS =:= win32 -> [{require, hardcoded_hosts}, {require, hardcoded_ipv6_hosts}]; _Else -> @@ -182,80 +183,74 @@ t_gethostbyname(Config) when is_list(Config) -> h_addr_list = [IP]}, ?line HEntF_ = HEntF, ?line check_elems([{HEnt#hostent.h_aliases,[[],Aliases]}]), + %% + ?line FullNameU = toupper(FullName), + ?line {ok,HEntU} = inet:gethostbyname(FullNameU), + ?line FullNameU = toupper(HEntU#hostent.h_name), + ?line #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]]}]), ?line {DName, _DFullName, _DIPStr, _DIP, _, _, _} = ct:get_config(test_dummy_host), ?line {error,nxdomain} = inet:gethostbyname(DName), - ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str). + ?line {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) -> []; t_gethostbyname_v6(Config) when is_list(Config) -> - ?line {Name, _, _, _,Aliases,IP_46_Str,IP_46} = - ct:get_config(test_host_ipv4_only), + {Name, FullName, IPStr, IP, Aliases} = + ct:get_config(test_host_ipv6_only), - case {inet:gethostbyname(IP_46_Str, inet6), - inet:gethostbyname(Name, inet6)} of - {{ok,HEnt46},{ok,_}} -> - ?line HEnt46_ = HEnt46#hostent{h_name = IP_46_Str, - h_addrtype = inet6, - h_length = 16, - h_addr_list = [IP_46]}, - ?line HEnt46_ = HEnt46, - ?line check_elems([{HEnt46#hostent.h_aliases,[[],Aliases]}]), - - ?line {Name6, FullName6, IPStr6, IP6, Aliases6} = - ct:get_config(test_host_ipv6_only), - ?line {ok,_} = inet:gethostbyname(IPStr6, inet6), - ?line {ok,HEnt6} = inet:gethostbyname(Name6, inet6), - ?line {ok,HEnt6} = inet:gethostbyname(list_to_atom(Name6), inet6), - ?line case HEnt6#hostent.h_addr_list of - [IP6] -> % ipv6 ok - ?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]}]); - _ -> % ipv4 compatible addr - ?line {ok,HEnt4} = inet:gethostbyname(Name6, inet), - ?line [IP4] = HEnt4#hostent.h_addr_list, - ?line {ok,IP46_2} = - inet_parse:ipv6_address("::ffff:"++inet_parse:ntoa(IP4)), - ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6, - h_length = 16, - h_addr_list = [IP46_2]}, - ?line HEnt6_ = HEnt6, - ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]}]) - end, - - ?line {ok,HEntF6} = inet:gethostbyname(FullName6, inet6), - ?line case HEntF6#hostent.h_addr_list of - [IP6] -> % ipv6 ok - ?line HEntF6_ = HEntF6#hostent{h_name = FullName6, - h_addrtype = inet6, - h_length = 16, - h_addr_list = [IP6]}, - ?line HEntF6_ = HEntF6, - ?line check_elems([{HEntF6#hostent.h_aliases,[[],Aliases6]}]); - _ -> % ipv4 compatible addr - ?line {ok,HEntF4} = inet:gethostbyname(FullName6, inet), - ?line [IPF4] = HEntF4#hostent.h_addr_list, - ?line {ok,IPF46_2} = - inet_parse:ipv6_address("::ffff:"++inet_parse:ntoa(IPF4)), - ?line HEntF6_ = HEntF6#hostent{h_addrtype = inet6, - h_length = 16, - h_addr_list = [IPF46_2]}, - ?line HEntF6_ = HEntF6, - ?line check_elems([{HEntF6#hostent.h_name,[Name6,FullName6]}]) - end, - - ?line {DName6, _DFullName6, _DIPStr6, _DIP6, _} = - ct:get_config(test_dummy_ipv6_host), - ?line {error,nxdomain} = inet:gethostbyname(DName6, inet6), - ok; - {_,_} -> + case inet:gethostbyname(Name, inet6) of + {ok,HEnt} -> + {ok,_} = inet:gethostbyname(IPStr, inet6), + {ok,HEnt} = inet:gethostbyname(list_to_atom(Name), inet6), + case HEnt#hostent.h_addr_list of + [IP] -> % IPv6 address + #hostent{h_addrtype = inet6, + h_length = 16} = HEnt, + check_elems( + [{HEnt#hostent.h_name,[Name,FullName]}, + {HEnt#hostent.h_aliases,[[],Aliases]}]); + [IP46] -> % IPv4 compatible address + {ok,HEnt4} = inet:gethostbyname(Name, inet), + #hostent{h_addrtype = inet, + h_length = 4, + h_addr_list = [IP4]} = HEnt4, + {ok,IP46} = + inet_parse:ipv6_address( + "::ffff:" ++ inet_parse:ntoa(IP4)), + check_elems( + [{HEnt#hostent.h_name,[Name,FullName]}]) + end, + + {ok,HEntF} = inet:gethostbyname(FullName, inet6), + case HEntF#hostent.h_addr_list of + [IP] -> % IPv6 address + #hostent{h_name = FullName, + h_addrtype = inet6, + h_length = 16} = HEntF, + check_elems( + [{HEnt#hostent.h_aliases,[[],Aliases]}]); + [IP46F] -> % IPv4 compatible address + {ok,HEnt4F} = inet:gethostbyname(FullName, inet), + #hostent{h_addrtype = inet, + h_length = 4, + h_addr_list = [IP4F]} = HEnt4F, + {ok,IP46F} = + inet_parse:ipv6_address( + "::ffff:" ++ inet_parse:ntoa(IP4F)), + check_elems( + [{HEntF#hostent.h_name,[Name,FullName]}]) + end; + _ -> {skip, "IPv6 is not supported on this host"} end. @@ -289,47 +284,35 @@ t_getaddr(Config) when is_list(Config) -> ?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). + ?line {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) -> []; t_getaddr_v6(Config) when is_list(Config) -> - ?line {Name,FullName,IPStr,_IP,_,IP_46_Str,IP46} = - ct:get_config(test_host_ipv4_only), - case {inet:getaddr(IP_46_Str, inet6),inet:getaddr(Name, inet6)} of - {{ok,IP46},{ok,V4Addr}} when V4Addr /= {0,0,0,0,0,0,0,1} -> - %% Since we suceeded in parsing an IPv6 address string and - %% look up the name, this computer fully supports IPv6. - ?line {ok,IP46} = inet:getaddr(IP46, inet6), - ?line {ok,IP46} = inet:getaddr(Name, inet6), - ?line {ok,IP46} = inet:getaddr(FullName, inet6), - ?line {ok,IP46} = inet:getaddr(IPStr, inet6), -%% ?line IP4toIP6 = inet:getaddr(IPStr, inet6), -%% ?line case IP4toIP6 of -%% {ok,IP46} -> -%% ?line ok; -%% {error,nxdomain} -> -%% ?line false = -%% lists:member(native, -%% inet_db:res_option(lookup)) -%% end, - ?line {Name6, FullName6, IPStr6, IP6, _} = - ct:get_config(test_host_ipv6_only), - ?line {ok,_} = inet:getaddr(list_to_atom(Name6), inet6), - ?line {ok,_} = inet:getaddr(Name6, inet6), - ?line {ok,_} = inet:getaddr(FullName6, inet6), - ?line {ok,IP6} = inet:getaddr(IP6, inet6), - ?line {ok,IP6} = inet:getaddr(IPStr6, inet6), - - ?line {DName6, DFullName6, DIPStr6, DIP6, _} = + {Name,FullName,IPStr,IP,_} = + ct:get_config(test_host_ipv6_only), + + case inet:getaddr(Name, inet6) of + {ok,Addr} -> + IP = Addr, + {ok,IP} = inet:getaddr(toupper(Name), inet6), + {ok,IP} = inet:getaddr(list_to_atom(Name), inet6), + {ok,IP} = inet:getaddr(list_to_atom(toupper(Name)), inet6), + {ok,IP} = inet:getaddr(FullName, inet6), + {ok,IP} = inet:getaddr(toupper(FullName), inet6), + {ok,IP} = inet:getaddr(IP, inet6), + {ok,IP} = inet:getaddr(IPStr, inet6), + %% + {DName,DFullName,DIPStr,DIP,_} = ct:get_config(test_dummy_ipv6_host), - ?line {error,nxdomain} = inet:getaddr(DName6, inet6), - ?line {error,nxdomain} = inet:getaddr(DFullName6, inet6), - ?line {ok,DIP6} = inet:getaddr(DIPStr6, inet6), - ?line {ok,DIP6} = inet:getaddr(DIP6, inet6), + {error,nxdomain} = inet:getaddr(DName, inet6), + {error,nxdomain} = inet:getaddr(DFullName, inet6), + {ok,DIP} = inet:getaddr(DIPStr, inet6), + {ok,DIP} = inet:getaddr(DIP, inet6), ok; - {_,_} -> + _ -> {skip, "IPv6 is not supported on this host"} end. @@ -582,16 +565,16 @@ parse_address(Config) when is_list(Config) -> "fe80::198.168.0.", "fec0::fFfF:127.0.0.1."], t_parse_address - (ipv6_address, + (parse_ipv6_address, V6Strict++V6Sloppy++V6Err++V4Err), t_parse_address - (ipv6strict_address, + (parse_ipv6strict_address, V6Strict++V6Err++V4Err++[S || {_,S} <- V6Sloppy]), t_parse_address - (ipv4_address, + (parse_ipv4_address, V4Strict++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Strict]), t_parse_address - (ipv4strict_address, + (parse_ipv4strict_address, V4Strict++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Strict]). t_parse_address(Func, []) -> @@ -599,14 +582,20 @@ t_parse_address(Func, []) -> ok; t_parse_address(Func, [{Addr,String}|L]) -> io:format("~p = ~p.~n", [Addr,String]), - {ok,Addr} = inet_parse:Func(String), + {ok,Addr} = inet:Func(String), t_parse_address(Func, L); t_parse_address(Func, [String|L]) -> io:format("~p.~n", [String]), - {error,einval} = inet_parse:Func(String), + {error,einval} = inet:Func(String), t_parse_address(Func, L). - +parse_strict_address(Config) when is_list(Config) -> + {ok, {127,0,0,1}} = + inet:parse_strict_address("127.0.0.1"), + {ok, {3089,3106,23603,50240,21952,50796,119,136}} = + inet:parse_strict_address("c11:0c22:5c33:c440:55c0:c66c:77:0088"), + {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) ->[]; @@ -614,17 +603,12 @@ 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 - case os:type() of - vxworks -> - {skipped, "VxWorks has no native gethostbyname()"}; - _ -> - ?line case inet_gethost_native:gethostbyname( - "a23456789012345678901234") of - {error,notfound} -> - ?line ok; - {error,no_data} -> - ?line ok - end + ?line case inet_gethost_native:gethostbyname( + "a23456789012345678901234") of + {error,notfound} -> + ?line ok; + {error,no_data} -> + ?line ok end. gethostnative_parallell(suite) -> @@ -1104,3 +1088,14 @@ ip_member({127,_,_,_}, [{127,_,_,_}|_]) -> true; ip_member(K, [K|_]) -> true; ip_member(K, [_|T]) -> ip_member(K, T); ip_member(_, []) -> false. + +%% Case fold to upper case according to RFC 4343 +%% +toupper([C|Cs]) when is_integer(C) -> + if $a =< C, C =< $z -> + [(C - $a + $A)|toupper(Cs)]; + true -> + [C|toupper(Cs)] + end; +toupper([]) -> + []. diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl index f3ba28e4f9..1bc93e3138 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-2011. All Rights Reserved. +%% Copyright Ericsson AB 2009-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -282,6 +282,7 @@ basic(doc) -> basic(Config) when is_list(Config) -> NS = ns(Config), Name = "ns.otptest", + NameC = caseflip(Name), IP = {127,0,0,254}, %% %% nslookup @@ -292,6 +293,17 @@ basic(Config) when is_list(Config) -> Bin1 = inet_dns:encode(Msg1), %%io:format("Bin1 = ~w~n", [Bin1]), {ok,Msg1} = inet_dns:decode(Bin1), + %% Now with scrambled case + {ok,Msg1b} = inet_res:nslookup(NameC, in, a, [NS]), + io:format("~p~n", [Msg1b]), + [RR1b] = inet_dns:msg(Msg1b, anlist), + IP = inet_dns:rr(RR1b, data), + Bin1b = inet_dns:encode(Msg1b), + %%io:format("Bin1b = ~w~n", [Bin1b]), + {ok,Msg1b} = inet_dns:decode(Bin1b), + true = + (tolower(inet_dns:rr(RR1, domain)) + =:= tolower(inet_dns:rr(RR1b, domain))), %% %% resolve {ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]},verbose]), @@ -301,15 +313,29 @@ basic(Config) when is_list(Config) -> Bin2 = inet_dns:encode(Msg2), %%io:format("Bin2 = ~w~n", [Bin2]), {ok,Msg2} = inet_dns:decode(Bin2), + %% Now with scrambled case + {ok,Msg2b} = inet_res:resolve(NameC, in, a, [{nameservers,[NS]},verbose]), + io:format("~p~n", [Msg2b]), + [RR2b] = inet_dns:msg(Msg2b, anlist), + IP = inet_dns:rr(RR2b, data), + Bin2b = inet_dns:encode(Msg2b), + %%io:format("Bin2b = ~w~n", [Bin2b]), + {ok,Msg2b} = inet_dns:decode(Bin2b), + true = + (tolower(inet_dns:rr(RR2, domain)) + =:= tolower(inet_dns:rr(RR2b, domain))), %% %% lookup [IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose]), + [IP] = inet_res:lookup(NameC, in, a, [{nameservers,[NS]},verbose]), %% %% gethostbyname {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(Name), + {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(NameC), %% %% getbyname {ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(Name, a), + {ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(NameC, a), ok. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -317,63 +343,115 @@ basic(Config) when is_list(Config) -> resolve(doc) -> ["Lookup different records using resolve/2..4"]; resolve(Config) when is_list(Config) -> + Class = in, NS = ns(Config), Domain = "otptest", RDomain4 = "0.0.127.in-addr.arpa", RDomain6 = "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa", Name = "resolve."++Domain, - L = [{in,a,Name,[{127,0,0,28}],undefined}, - {in,aaaa,Name,[{0,0,0,0,0,0,32512,28}],undefined}, - {in,cname,"cname."++Name,[Name],undefined}, - {in,a,"cname."++Name,[Name,{127,0,0,28}],undefined}, - {in,ns,"ns."++Name,[],[Name]}, - {in,soa,Domain,[],[{"ns.otptest","lsa.otptest",1,60,10,300,30}]}, + L = [{a,Name,[{a,{127,0,0,28}}],undefined}, + {aaaa,Name,[{aaaa,{0,0,0,0,0,0,32512,28}}],undefined}, + {cname,"cname."++Name,[{cname,Name}],undefined}, + {a,"cname."++Name,[{cname,Name},{a,{127,0,0,28}}],undefined}, + {ns,"ns."++Name,[],[{ns,Name}]}, + {soa,Domain,[],[{soa,{"ns.otptest","lsa.otptest",1,60,10,300,30}}]}, %% WKS: protocol TCP (6), services (bits) TELNET (23) and SMTP (25) - {in,wks,"wks."++Name,[{{127,0,0,28},6,<<0,0,1,64>>}],undefined}, - {in,ptr,"28."++RDomain4,[Name],undefined}, - {in,ptr,"c.1.0.0.0.0.f.7."++RDomain6,[Name],undefined}, - {in,hinfo,Name,[{"BEAM","Erlang/OTP"}],undefined}, - {in,mx,RDomain4,[{10,"mx."++Domain}],undefined}, - {in,srv,"_srv._tcp."++Name,[{10,3,4711,Name}],undefined}, - {in,naptr,"naptr."++Name, - [{10,5,"s","http","","_srv._tcp."++Name}],undefined}, - {in,txt,"txt."++Name, - [["Hej ","du ","glade "],["ta ","en ","spade!"]],undefined}, - {in,mb,"mb."++Name,["mx."++Name],undefined}, - {in,mg,"mg."++Name,["lsa."++Domain],undefined}, - {in,mr,"mr."++Name,["lsa."++Domain],undefined}, - {in,minfo,"minfo."++Name, - [{"minfo-owner."++Name,"minfo-bounce."++Name}],undefined}, - {in,any,"cname."++Name,[Name],undefined}, - {in,any,Name,[{127,0,0,28}, - {0,0,0,0,0,0,32512,28}, - {"BEAM","Erlang/OTP"}],undefined} + {wks,"wks."++Name,[{wks,{{127,0,0,28},6,<<0,0,1,64>>}}],undefined}, + {ptr,"28."++RDomain4,[{ptr,Name}],undefined}, + {ptr,"c.1.0.0.0.0.f.7."++RDomain6,[{ptr,Name}],undefined}, + {hinfo,Name,[{hinfo,{"BEAM","Erlang/OTP"}}],undefined}, + {mx,RDomain4,[{mx,{10,"mx."++Domain}}],undefined}, + {srv,"_srv._tcp."++Name,[{srv,{10,3,4711,Name}}],undefined}, + {naptr,"naptr."++Name, + [{naptr,{10,5,"s","http","","_srv._tcp."++Name}}], + undefined}, + {txt,"txt."++Name, + [{txt,["Hej ","du ","glade "]},{txt,["ta ","en ","spade!"]}], + undefined}, + {mb,"mb."++Name,[{mb,"mx."++Name}],undefined}, + {mg,"mg."++Name,[{mg,"Lsa."++Domain}],undefined}, + {mr,"mr."++Name,[{mr,"LSA."++Domain}],undefined}, + {minfo,"minfo."++Name, + [{minfo,{"minfo-OWNER."++Name,"MinfoBounce."++Name}}], + undefined}, + {any,"cname."++Name,[{cname,Name}],undefined}, + {any,Name, + [{a,{127,0,0,28}}, + {aaaa,{0,0,0,0,0,0,32512,28}}, + {hinfo,{"BEAM","Erlang/OTP"}}], + undefined} ], - resolve([{edns,false},{nameservers,[NS]}], L), - resolve([{edns,0},{nameservers,[NS]}], L). - -resolve(_Opts, []) -> ok; -resolve(Opts, [{Class,Type,Name,Answers,Authority}=Q|Qs]) -> + resolve(Class, [{edns,0},{nameservers,[NS]}], L), + resolve(Class, [{edns,false},{nameservers,[NS]}], L), + %% Again, to see ensure the cache does not mess things up + resolve(Class, [{edns,0},{nameservers,[NS]}], L), + resolve(Class, [{edns,false},{nameservers,[NS]}], L). + +resolve(_Class, _Opts, []) -> + ok; +resolve(Class, Opts, [{Type,Nm,Answers,Authority}=Q|Qs]) -> io:format("Query: ~p~nOptions: ~p~n", [Q,Opts]), - {ok,Msg} = inet_res:resolve(Name, Class, Type, Opts), + {Name,NameC} = + case erlang:phash2(Q) band 4 of + 0 -> + {Nm,caseflip(Nm)}; + _ -> + {caseflip(Nm),Nm} + end, AnList = if Answers =/= undefined -> - lists:sort(Answers); + normalize_answers(Answers); true -> undefined end, NsList = if Authority =/= undefined -> - lists:sort(Authority); + normalize_answers(Authority); true -> undefined end, - case {lists:sort - ([inet_dns:rr(RR, data) || RR <- inet_dns:msg(Msg, anlist)]), - lists:sort - ([inet_dns:rr(RR, data) || RR <- inet_dns:msg(Msg, nslist)])} of + {ok,Msg} = inet_res:resolve(Name, Class, Type, Opts), + check_msg(Class, Type, Msg, AnList, NsList), + {ok,MsgC} = inet_res:resolve(NameC, Class, Type, Opts), + check_msg(Class, Type, MsgC, AnList, NsList), + resolve(Class, Opts, Qs). + + + +normalize_answers(AnList) -> + lists:sort([normalize_answer(Answer) || Answer <- AnList]). + +normalize_answer({soa,{NS,HM,Ser,Ref,Ret,Exp,Min}}) -> + {tolower(NS),tolower_email(HM),Ser,Ref,Ret,Exp,Min}; +normalize_answer({mx,{Prio,DN}}) -> + {Prio,tolower(DN)}; +normalize_answer({srv,{Prio,Weight,Port,DN}}) -> + {Prio,Weight,Port,tolower(DN)}; +normalize_answer({naptr,{Order,Pref,Flags,Service,RE,Repl}}) -> + {Order,Pref,Flags,Service,RE,tolower(Repl)}; +normalize_answer({minfo,{RespM,ErrM}}) -> + {tolower_email(RespM),tolower_email(ErrM)}; +normalize_answer({T,MN}) when T =:= mg; T =:= mr -> + tolower_email(MN); +normalize_answer({T,DN}) when T =:= cname; T =:= ns; T =:= ptr; T =:= mb -> + tolower(DN); +normalize_answer(Answer) -> + Answer. + +check_msg(Class, Type, Msg, AnList, NsList) -> + io:format("check_msg Type: ~p, Msg: ~p~n.", [Type,Msg]), + case {normalize_answers( + [begin + Class = inet_dns:rr(RR, class), + {inet_dns:rr(RR, type),inet_dns:rr(RR, data)} + end || RR <- inet_dns:msg(Msg, anlist)]), + normalize_answers( + [begin + Class = inet_dns:rr(RR, class), + {inet_dns:rr(RR, type),inet_dns:rr(RR, data)} + end || RR <- inet_dns:msg(Msg, nslist)])} of {AnList,NsList} -> ok; {NsList,AnList} when Type =:= ns -> @@ -389,7 +467,7 @@ resolve(Opts, [{Class,Type,Name,Answers,Authority}=Q|Qs]) -> end, Buf = inet_dns:encode(Msg), {ok,Msg} = inet_dns:decode(Buf), - resolve(Opts, Qs). + ok. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -497,6 +575,7 @@ files_monitor(Config) when is_list(Config) -> do_files_monitor(Config) -> Dir = ?config(priv_dir, Config), {ok,Hostname} = inet:gethostname(), + io:format("Hostname = ~p.~n", [Hostname]), FQDN = case inet_db:res_option(domain) of "" -> @@ -504,11 +583,13 @@ do_files_monitor(Config) -> _ -> Hostname++"."++inet_db:res_option(domain) end, + io:format("FQDN = ~p.~n", [FQDN]), HostsFile = filename:join(Dir, "files_monitor_hosts"), ResolvConf = filename:join(Dir, "files_monitor_resolv.conf"), ok = inet_db:res_option(resolv_conf, ResolvConf), ok = inet_db:res_option(hosts_file, HostsFile), [] = inet_db:res_option(search), + %% The inet function will use its final fallback to find this host {ok,#hostent{h_name = Hostname, h_addrtype = inet, h_length = 4, @@ -521,6 +602,7 @@ do_files_monitor(Config) -> {error,nxdomain} = inet_res:gethostbyname(FQDN), {ok,{127,0,0,10}} = inet:getaddr("mx.otptest", inet), {ok,{0,0,0,0,0,0,32512,28}} = inet:getaddr("resolve.otptest", inet6), + %% The inet function will use its final fallback to find this host {ok,#hostent{h_name = Hostname, h_addrtype = inet6, h_length = 16, @@ -603,3 +685,41 @@ ipv4_to_ipv6() -> inet_SUITE:ipv4_to_ipv6(). ipv4_to_ipv6(Config) -> inet_SUITE:ipv4_to_ipv6(Config). host_and_addr() -> inet_SUITE:host_and_addr(). host_and_addr(Config) -> inet_SUITE:host_and_addr(Config). + + + +%% Case flip helper + +caseflip([C|Cs]) when is_integer(C), $a =< C, C =< $z -> + [(C - $a + $A)|caseflip_skip(Cs)]; +caseflip([C|Cs]) when is_integer(C), $A =< C, C =< $Z -> + [(C - $A + $a)|caseflip_skip(Cs)]; +caseflip([C|Cs]) -> + [C|caseflip(Cs)]; +caseflip([]) -> + []. + +caseflip_skip([C|Cs]) when is_integer(C), $a =< C, C =< $z -> + [C|caseflip(Cs)]; +caseflip_skip([C|Cs]) when is_integer(C), $A =< C, C =< $Z -> + [C|caseflip(Cs)]; +caseflip_skip([C|Cs]) -> + [C|caseflip_skip(Cs)]; +caseflip_skip([]) -> + []. + +tolower_email([$.|Cs]) -> + [$.|tolower(Cs)]; +tolower_email([C|Cs]) -> + [C|tolower_email(Cs)]. + +%% Case fold to lower case according to RFC 4343 +%% +tolower([C|Cs]) when is_integer(C) -> + if $A =< C, C =< $Z -> + [(C - $A + $a)|tolower(Cs)]; + true -> + [C|tolower(Cs)] + end; +tolower([]) -> + []. diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf b/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf index 0b01b25204..2d68f6e59c 100644 --- a/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf +++ b/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf @@ -2,11 +2,11 @@ zone "." in { type master; file "root.zone"; }; -zone "0.0.127.in-addr.arpa" in { +zone "0.0.127.in-addr.arpa." in { type master; file "0.0.127.in-addr.arpa.zone"; }; -zone "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" in { +zone "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." in { type master; file "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone"; -};
\ No newline at end of file +}; diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone index 11cba18d45..5a56eac95c 100644 --- a/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone +++ b/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone @@ -43,8 +43,8 @@ naptr.resolve.otptest IN NAPTR 10 5 "S" "HTTP" "" _srv._tcp.resolve.otptest txt.resolve.otptest IN TXT "Hej " "du " "glade " txt.resolve.otptest IN TXT "ta " "en " "spade!" mb.resolve.otptest IN MB mx.resolve.otptest -mg.resolve.otptest IN MG lsa.otptest -mr.resolve.otptest IN MR lsa.otptest -minfo.resolve.otptest IN MINFO minfo-owner.resolve.otptest minfo-bounce.resolve.otptest +mg.resolve.otptest IN MG Lsa.otptest +mr.resolve.otptest IN MR LSA.otptest +minfo.resolve.otptest IN MINFO minfo-OWNER.resolve.otptest MinfoBounce.resolve.otptest ns.otptest IN A 127.0.0.254 diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 0c63a6d653..9d236a8a0a 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-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -53,6 +53,8 @@ simple/1, loop_all/1, simple_raw/1, simple_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, + use_ipv6_v6only_udp/1, type_errors/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -64,6 +66,8 @@ all() -> [simple, loop_all, simple_raw, simple_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, + use_ipv6_v6only_udp, type_errors]. groups() -> @@ -127,7 +131,7 @@ loop_all(Config) when is_list(Config) -> io_lib:format("Non mandatory failed:~w", [Failed]))} end. - + simple_raw(suite) -> []; @@ -461,6 +465,153 @@ do_combined(Config,Binary) when is_list(Config) -> ok end. + + +ipv6_v6only_udp(suite) -> []; +ipv6_v6only_udp(doc) -> "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"; +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"; +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. + +ipv6_v6only(Config, Module, Default) when is_list(Config) -> + ?line io:format("Default ~w.~n", [Default]), + ?line {ok,S1} = + ipv6_v6only_open(Module, [{ipv6_v6only,Default}]), + ?line {ok,[{ipv6_v6only,Default}]} = + inet:getopts(S1, [ipv6_v6only]), + ?line 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. + +ipv6_v6only_open(Module, Opts) -> + Module:case Module of + gen_tcp -> listen; + _ -> open + end(0, [inet6|Opts]). + +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"; +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. + +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 = + 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, 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. + +use_ipv6_v6only_udp_sender(Port, E6, E4) -> + D6 = "IPv6-send.", + D4 = "IPv4-send.", + R6 = D6 ++ E6, + R4 = D4 ++ E4, + R6 = sndrcv({0,0,0,0,0,0,0,1}, Port, [inet6], D6), + R4 = sndrcv({127,0,0,1}, Port, [inet], D4), + ok. + +sndrcv(Ip, Port, Opts, Data) -> + {ok,S} = gen_udp:open(0, Opts), + io:format("[~w:~w] ! ~s~n", [Ip,Port,Data]), + ok = gen_udp:send(S, Ip, Port, Data), + receive + {udp,S,Ip,Port,RecData} -> + io:format("[~w:~w] : ~s~n", [Ip,Port,RecData]), + RecData; + Other -> + exit({failed,{sndrcv_unexpectec,Other}}) + end. + + + type_errors(suite) -> []; type_errors(doc) -> @@ -621,9 +772,10 @@ all_listen_options() -> {mode,list,binary,true,true}, {deliver,term,port,true,true}, {exit_on_close, true, false, true, true}, - %{high_watermark,4096,8192,true,true}, - %{low_watermark,2048,4096,true,true}, - {bit8,on,off,true,true}, + {high_watermark,4096,8192,true,true}, + {low_watermark,2048,4096,true,true}, + {high_msgq_watermark,4096,8192,true,true}, + {low_msgq_watermark,2048,4096,true,true}, {send_timeout,infinity,1000,true,true}, {send_timeout_close,false,true,true,true}, {delay_send,false,true,true,true}, @@ -647,7 +799,8 @@ all_connect_options() -> {exit_on_close, true, false, true, true}, {high_watermark,4096,8192,false,true}, {low_watermark,2048,4096,false,true}, - {bit8,on,off,true,true}, + {high_msgq_watermark,4096,8192,true,true}, + {low_msgq_watermark,2048,4096,true,true}, {send_timeout,infinity,1000,true,true}, {send_timeout_close,false,true,true,true}, {delay_send,false,true,true,true}, diff --git a/lib/kernel/test/inet_sockopt_SUITE_data/sockopt_helper.c b/lib/kernel/test/inet_sockopt_SUITE_data/sockopt_helper.c index f24c93edf5..9c8f8eb91a 100644 --- a/lib/kernel/test/inet_sockopt_SUITE_data/sockopt_helper.c +++ b/lib/kernel/test/inet_sockopt_SUITE_data/sockopt_helper.c @@ -1,12 +1,3 @@ -#if defined(VXWORKS) -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -int sockopt_helper(void){ - return 0; -} -#else - #if defined(__WIN32__) #define WIN32_LEAN_AND_MEAN #include <winsock2.h> @@ -215,5 +206,3 @@ int main(void){ } while (x != C_QUIT); return 0; } -#endif - diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index e0b90c5214..6fe97ed04f 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -256,47 +256,42 @@ get_plain_arguments(Config) when is_list(Config) -> boot_var(doc) -> []; boot_var(suite) -> {req, [distribution, {local_slave_nodes, 1}]}; boot_var(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "Not run on VxWorks"}; + ?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), + + 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), + stop_node(Node), + Res = ok; _ -> - ?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), - - 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), - 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", - []), - 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."} - end, - ?line ?t:timetrap_cancel(Dog), - Res - end. + %% 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", + []), + 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."} + end, + ?line ?t:timetrap_cancel(Dog), + Res. create_boot(Config) -> ?line {ok, OldDir} = file:get_cwd(), @@ -579,55 +574,47 @@ script_id(Config) when is_list(Config) -> boot1(doc) -> []; boot1(suite) -> {req, [distribution, {local_slave_nodes, 1}, {time, 35}]}; boot1(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "Not run on VxWorks"}; - _ -> - ?line Dog = ?t:timetrap(?t:seconds(80)), - Args = args() ++ " -boot start_sasl", - ?line {ok, Node} = start_node(init_test, Args), - ?line stop_node(Node), - - %% Try to start with non existing boot file. - Args1 = args() ++ " -boot dummy_script", - ?line {error, timeout} = start_node(init_test, Args1), - - ?line ?t:timetrap_cancel(Dog), - ok - end. + ?line Dog = ?t:timetrap(?t:seconds(80)), + Args = args() ++ " -boot start_sasl", + ?line {ok, Node} = start_node(init_test, Args), + ?line stop_node(Node), + + %% Try to start with non existing boot file. + Args1 = args() ++ " -boot dummy_script", + ?line {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"]), + + Args = args() ++ " -boot \"" ++ Boot++"\"", + {ok, Node} = start_node(init_test, Args), + stop_node(Node), + case os:type() of - vxworks -> - {comment, "Not run on VxWorks"}; + {win32, _} -> + %% Absolute boot file name for Windows -- all slashes are + %% converted to backslashes. + Win_boot = lists:map(fun + ($/) -> $\\; + (C) -> C + end, Boot), + Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"", + {ok, Node2} = start_node(init_test, Args2), + stop_node(Node2); _ -> - ?line Dog = ?t:timetrap(?t:seconds(80)), - - %% Absolute boot file name - Boot = filename:join([code:root_dir(), "bin", "start_sasl"]), - - Args = args() ++ " -boot \"" ++ Boot++"\"", - ?line {ok, Node} = start_node(init_test, Args), - ?line stop_node(Node), - - case os:type() of - {win32, _} -> - %% Absolute boot file name for Windows -- all slashes are - %% converted to backslashes. - Win_boot = lists:map(fun($/) -> $\\; (C) -> C end, - Boot), - Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"", - ?line {ok, Node2} = start_node(init_test, Args2), - ?line stop_node(Node2); - _ -> - ok - end, - - ?line ?t:timetrap_cancel(Dog), ok - end. + end, + + ?t:timetrap_cancel(Dog), + ok. %% Misc. functions diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl index 7549e2c83e..d7d9434b1f 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -29,7 +29,7 @@ -export([toerl_server/3]). init_per_testcase(_Func, Config) -> - Dog = test_server:timetrap(test_server:seconds(60)), + Dog = test_server:timetrap(test_server:minutes(3)), [{watchdog,Dog}|Config]. end_per_testcase(_Func, Config) -> @@ -193,7 +193,7 @@ job_control_remote(Config) when is_list(Config) -> {skip,"No new shell found"}; _ -> ?line RNode = create_nodename(), - ?line MyNode = atom_to_list(node()), + ?line MyNode = atom2list(node()), ?line Pid = spawn_link(fun() -> receive die -> ok @@ -211,7 +211,7 @@ job_control_remote(Config) when is_list(Config) -> {sleep,timeout(short)}, {putline,""}, {getline," -->"}, - {putline,"r "++MyNode}, + {putline,"r '"++MyNode++"'"}, {putline,"c"}, {putline_raw,""}, {getline,"Eshell"}, @@ -254,7 +254,7 @@ job_control_remote_noshell(Config) when is_list(Config) -> end), ?line PidStr = rpc:call(NSNode,erlang,pid_to_list,[Pid]), ?line true = rpc:call(NSNode,erlang,register,[kalaskula,Pid]), - ?line NSNodeStr = atom_to_list(NSNode), + ?line NSNodeStr = atom2list(NSNode), ?line CookieString = lists:flatten( io_lib:format("~w", [erlang:get_cookie()])), @@ -265,7 +265,7 @@ job_control_remote_noshell(Config) when is_list(Config) -> {sleep,timeout(short)}, {putline,""}, {getline," -->"}, - {putline,"r "++NSNodeStr}, + {putline,"r '"++NSNodeStr++"'"}, {putline,"c"}, {putline_raw,""}, {getline,"Eshell"}, @@ -715,7 +715,10 @@ get_default_shell() -> {putline, "whereis(user_drv)."}, {getline, "undefined"}],[]), old - catch E:R -> - ?dbg({E,R}), + catch _E:_R -> + ?dbg({_E,_R}), new end. + +atom2list(A) -> + lists:flatten(io_lib:format("~s", [A])). diff --git a/lib/kernel/test/kernel.cover b/lib/kernel/test/kernel.cover index f6967ca651..af1dd7eaad 100644 --- a/lib/kernel/test/kernel.cover +++ b/lib/kernel/test/kernel.cover @@ -1,3 +1,3 @@ %% -*- erlang -*- -{incl_mods,[gen_udp,inet6_udp,inet_res,inet_dns]}. +{incl_app,kernel,details}. diff --git a/lib/kernel/test/kernel.spec.wxworks b/lib/kernel/test/kernel.spec.wxworks deleted file mode 100644 index 370e474e64..0000000000 --- a/lib/kernel/test/kernel.spec.wxworks +++ /dev/null @@ -1,63 +0,0 @@ -%% -*- erlang -*- -{suites,"kernel_test",all}. -{skip_cases,"kernel_test",bif_SUITE,[spawn_link_race1],"Known bug."}. -{skip_cases,"kernel_test",file_SUITE, - [read_write_file], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [cur_dir_0], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [open1], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [file_info_times], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [file_write_file_info], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [truncate], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [rename], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [e_delete], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [e_rename], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [delayed_write], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [read_ahead], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",file_SUITE, - [segment_write], - "VxWorks filesystem would overload"}. -{skip_cases,"kernel_test",file_SUITE, - [segment_read], - "VxWorks filesystem would overload"}. -{skip_cases,"kernel_test",file_SUITE, - [compress_errors], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",init_SUITE,[restart],"Uses peer nodes"}. -{skip_cases,"kernel_test",os_SUITE,[space_in_cwd],"VxWorks can't handle this"}. -{skip_cases,"kernel_test",os_SUITE, - [space_in_name], - "VxWorks can't handle this"}. -{skip_cases,"kernel_test",os_SUITE,[quoting],"VxWorks can't handle this"}. -{skip_cases,"kernel_test",prim_file_SUITE, - [open1], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",prim_file_SUITE, - [compress_errors], - "VxWorks filesystem can't handle this"}. -{skip_cases,"kernel_test",seq_trace_SUITE, - [distributed_recv], - "Test not adopted to slaves on different machine"}. -{skip_cases,"kernel_test",seq_trace_SUITE, - [distributed_exit], - "Test not adopted to slaves on different machine"}. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index ae3410d13f..73ed704ae3 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -18,20 +18,21 @@ %% -module(os_SUITE). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([space_in_cwd/1, quoting/1, space_in_name/1, bad_command/1, - find_executable/1, unix_comment_in_command/1, evil/1]). + find_executable/1, unix_comment_in_command/1, deep_list_command/1, evil/1]). -include_lib("test_server/include/test_server.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [space_in_cwd, quoting, space_in_name, bad_command, - find_executable, unix_comment_in_command, evil]. + find_executable, unix_comment_in_command, deep_list_command, + evil]. -groups() -> +groups() -> []. init_per_suite(Config) -> @@ -117,9 +118,9 @@ space_in_name(Config) when is_list(Config) -> ?line 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 + %% Quoting on windows depends on if the full path of the executable %% contains special characters. Paths when running common_tests always - %% include @, why Windows would always fail if we do not double the + %% include @, why Windows would always fail if we do not double the %% quotes (this is the behaviour of cmd.exe, not Erlang's idea). Quote = case os:type() of {win32,_} -> @@ -135,7 +136,7 @@ space_in_name(Config) when is_list(Config) -> ?t:sleep(5), ?line [] = 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) -> []; @@ -153,17 +154,17 @@ find_executable(suite) -> []; find_executable(doc) -> []; find_executable(Config) when is_list(Config) -> case os:type() of - {win32, _} -> + {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(), - + ?line Path = lists:concat([Bin, ";", Abin, ";", UsrBin]), ?line 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), @@ -175,18 +176,18 @@ find_executable(Config) when is_list(Config) -> ?line find_exe(Abin, "my_ar.EXE", "", Path), ?line find_exe(Abin, "my_ascii.COM", "", Path), ?line 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), - + %% 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), ok; - {unix, _} -> + {unix, _} -> DataDir = ?config(data_dir, Config), %% Smoke test. @@ -202,8 +203,6 @@ find_executable(Config) when is_list(Config) -> %% Never return a directory name. ?line false = os:find_executable("unix", [DataDir]), - ok; - vxworks -> ok end. @@ -239,6 +238,21 @@ unix_comment_in_command(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +deep_list_command(doc) -> + "Check that a deep list in command works equally on unix and on windows."; +deep_list_command(suite) -> []; +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 + %% be deep lists." + %% That's why os:cmd/1 can have arguments that are deep lists. + %% It is not a problem for unix, but for windows it is (in R15B02 for ex.). + Echo = os:cmd([$e, $c, "ho"]), + true = erlang:is_list(Echo), + %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"]) + ok. + + -define(EVIL_PROCS, 100). -define(EVIL_LOOPS, 100). -define(PORT_CREATOR, os_cmd_port_creator). @@ -305,4 +319,3 @@ receive_all() -> X -> [X|receive_all()] after 0 -> [] end. - diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl index 8afdfc8a47..98cff0222e 100644 --- a/lib/kernel/test/pdict_SUITE.erl +++ b/lib/kernel/test/pdict_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -152,7 +152,6 @@ heavy(Config) when is_list(Config) -> time(5000), ?M([],get()), case {os:type(),?t:is_debug()} of - {vxworks,_} -> ok; {_,true} -> ok; _ -> time(50000), diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 3e2202922c..199e597e78 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-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -49,7 +49,9 @@ make_link_a/1, make_link_b/1, read_link_info_for_non_link/1, symlinks_a/1, symlinks_b/1, - list_dir_limit/1]). + list_dir_limit/1, + list_dir_error/1, + list_dir/1]). -export([advise/1]). -export([large_write/1]). @@ -57,6 +59,8 @@ %% System probe functions that might be handy to check from the shell -export([unix_free/1]). +-export([allocate/1]). + -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -79,7 +83,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [read_write_file, {group, dirs}, {group, files}, delete_a, delete_b, rename_a, rename_b, {group, errors}, - {group, compression}, {group, links}, list_dir_limit]. + {group, compression}, {group, links}, list_dir_limit, list_dir]. groups() -> [{dirs, [], @@ -87,7 +91,7 @@ groups() -> cur_dir_1a, cur_dir_1b]}, {files, [], [{group, open}, {group, pos}, {group, file_info}, - truncate, sync, datasync, advise, large_write]}, + truncate, sync, datasync, advise, large_write, allocate]}, {open, [], [open1, modes, close, access, read_write, pread_write, append, exclusive]}, @@ -108,7 +112,7 @@ groups() -> write_compressed, compress_errors]}, {links, [], [make_link_a, make_link_b, read_link_info_for_non_link, - symlinks_a, symlinks_b]}]. + symlinks_a, symlinks_b, list_dir_error]}]. init_per_group(_GroupName, Config) -> Config. @@ -406,9 +410,6 @@ cur_dir_1(Config, Handle) -> {unix, _} -> ?line {error, enotsup} = ?PRIM_FILE_call(get_cwd, Handle, ["d:"]); - vxworks -> - ?line {error, enotsup} = - ?PRIM_FILE_call(get_cwd, Handle, ["d:"]); {win32, _} -> win_cur_dir_1(Config, Handle) end, @@ -843,10 +844,7 @@ file_info_basic_directory(Config, Handle) -> ?line test_directory("c:/", read_write, Handle), ?line test_directory("c:\\", read_write, Handle); {unix, _} -> - ?line test_directory("/", read, Handle); - vxworks -> - %% Check is just done for owner - ?line test_directory("/", read_write, Handle) + ?line test_directory("/", read, Handle) end, ?line test_server:timetrap_cancel(Dog). @@ -1365,6 +1363,76 @@ check_large_write(Dog, Fd, _, _, []) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +allocate(suite) -> []; +allocate(doc) -> "Tests that ?PRIM_FILE: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"), + + Line1 = "Hello\n", + Line2 = "World!\n", + + ?line {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), + + ?line {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), + + ?line {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), + + ?line {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), + + ?line test_server:timetrap_cancel(Dog), + 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. + Result = ?PRIM_FILE:allocate(Fd, Offset, Length), + case os:type() of + {win32, _} -> + ?line {error, enotsup} = Result; + _ -> + ?line _ = Result + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + delete_a(suite) -> []; delete_a(doc) -> []; delete_a(Config) when is_list(Config) -> @@ -1508,9 +1576,7 @@ e_delete(Config) when is_list(Config) -> Base, #file_info {mode=8#600}); {win32, _} -> %% Remove a character device. - ?line {error, eacces} = ?PRIM_FILE:delete("nul"); - vxworks -> - ok + ?line {error, eacces} = ?PRIM_FILE:delete("nul") end, ?line test_server:timetrap_cancel(Dog), @@ -1524,110 +1590,105 @@ e_delete(Config) when is_list(Config) -> e_rename(suite) -> []; e_rename(doc) -> []; e_rename(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "Windriver: dosFs must be fixed first!"}; - _ -> - ?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), - - %% Create an empty directory. - ?line EmptyDir = filename:join(Base, "empty_dir"), - ?line 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"), - - %% 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"), + ?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), - %% Create a data file. - ?line File = filename:join(Base, "just_a_file"), - ?line 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), - - %% Move a root directory. - ?line {error, einval} = ?PRIM_FILE:rename("/", "arne"), - - %% Move Base into Base/new_name. - ?line {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)), - - %% Move a non-existing file. - ?line NonExistingFile = filename:join( - Base, "non_existing_file"), - ?line {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)), - - %% Move a file to another filesystem. - %% XXX - This test case is bogus. We cannot be guaranteed that - %% the source and destination are on - %% different filesystems. - %% - %% XXX - Gross hack! - ?line Comment = - case os:type() of - {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; - {win32, _} -> - %% At least Windows NT can - %% successfully move a file to - %% another drive. - ok - end, - ?line test_server:timetrap_cancel(Dog), - Comment - end. + %% Create an empty directory. + ?line EmptyDir = filename:join(Base, "empty_dir"), + ?line 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"), + + %% 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"), + + %% Create a data file. + ?line File = filename:join(Base, "just_a_file"), + ?line 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), + + %% Move a root directory. + ?line {error, einval} = ?PRIM_FILE:rename("/", "arne"), + + %% Move Base into Base/new_name. + ?line {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)), + + %% Move a non-existing file. + ?line NonExistingFile = filename:join( + Base, "non_existing_file"), + ?line {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)), + + %% Move a file to another filesystem. + %% XXX - This test case is bogus. We cannot be guaranteed that + %% the source and destination are on + %% different filesystems. + %% + %% XXX - Gross hack! + ?line Comment = + case os:type() of + {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; + {win32, _} -> + %% At least Windows NT can + %% successfully move a file to + %% another drive. + ok + end, + ?line test_server:timetrap_cancel(Dog), + Comment. e_make_dir(suite) -> []; e_make_dir(doc) -> []; @@ -1660,8 +1721,6 @@ e_make_dir(Config) when is_list(Config) -> ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600}); {win32, _} -> - ok; - vxworks -> ok end, ?line test_server:timetrap_cancel(Dog), @@ -1716,8 +1775,6 @@ e_del_dir(Config) when is_list(Config) -> ?line ?PRIM_FILE:write_file_info( Base, #file_info {mode=8#600}); {win32, _} -> - ok; - vxworks -> ok end, ?line test_server:timetrap_cancel(Dog), @@ -1980,6 +2037,10 @@ symlinks(Config, Handle, Suffix) -> ?line #file_info{links=1, type=symlink} = Info2, ?line {ok, Name} = ?PRIM_FILE_call(read_link, Handle, [Alias]), + {ok, Name} = + ?PRIM_FILE_call(read_link_all, Handle, [Alias]), + %% If all is good, delete dir again (avoid hanging dir on windows) + rm_rf(?PRIM_FILE,NewDir), ok end, @@ -2085,6 +2146,41 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) -> list_dir_limit_cleanup(Dir, Handle, N, Cnt+1). %%% +%%% Test list_dir() on a non-existing pathname. +%%% + +list_dir_error(Config) -> + Priv = ?config(priv_dir, Config), + NonExisting = filename:join(Priv, "non-existing-dir"), + {error,enoent} = prim_file:list_dir(NonExisting), + ok. + +%%% +%%% Test list_dir() and list_dir_all(). +%%% + +list_dir(Config) -> + RootDir = ?config(priv_dir, Config), + TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"), + ?PRIM_FILE:make_dir(TestDir), + list_dir_1(TestDir, 42, []). + +list_dir_1(TestDir, 0, Sorted) -> + [ok = ?PRIM_FILE:delete(filename:join(TestDir, F)) || + F <- Sorted], + ok = ?PRIM_FILE:del_dir(TestDir); +list_dir_1(TestDir, Cnt, Sorted0) -> + Base = "file" ++ integer_to_list(Cnt), + Name = filename:join(TestDir, Base), + ok = ?PRIM_FILE:write_file(Name, Base), + Sorted = lists:merge([Base], Sorted0), + {ok,DirList0} = ?PRIM_FILE:list_dir(TestDir), + {ok,DirList1} = ?PRIM_FILE:list_dir_all(TestDir), + Sorted = lists:sort(DirList0), + Sorted = lists:sort(DirList1), + list_dir_1(TestDir, Cnt-1, Sorted). + +%%% %%% Support for testing large files. %%% @@ -2151,3 +2247,18 @@ zip_data([], Bs) -> Bs; zip_data(As, []) -> As. + +%%%----------------------------------------------------------------- +%%% Utilities +rm_rf(Mod,Dir) -> + case Mod:read_link_info(Dir) of + {ok, #file_info{type = directory}} -> + {ok, Content} = Mod:list_dir_all(Dir), + [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ], + Mod:del_dir(Dir), + ok; + {ok, #file_info{}} -> + Mod:delete(Dir); + _ -> + ok + end. diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl index ab95a3ff5f..5c4437d4d3 100644 --- a/lib/kernel/test/ram_file_SUITE.erl +++ b/lib/kernel/test/ram_file_SUITE.erl @@ -1,7 +1,8 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -167,7 +168,7 @@ pread_pwrite(suite) -> pread_pwrite(doc) -> ["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 Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x", ?line Bin = list_to_binary(Str), %% pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]), @@ -206,7 +207,7 @@ position(suite) -> position(doc) -> ["Test that position/2 works."]; position(Config) when is_list(Config) -> - ?line Str = "Att vara eller icke vara, det �r fr�gan. ", + ?line Str = "Att vara eller icke vara, det är frågan. ", ?line Bin = list_to_binary(Str), %% position_test(?FILE_MODULE, Str, [ram, read]), @@ -287,8 +288,8 @@ truncate(suite) -> truncate(doc) -> ["Test that truncate/1 works."]; truncate(Config) when is_list(Config) -> - ?line Str = "M�n �dlare att lida och f�rdraga " - ++ "ett bittert �des stygn av pilar, ", + ?line Str = "Mån ädlare att lida och fördraga " + ++ "ett bittert ödes stygn av pilar, ", ?line Bin = list_to_binary(Str), %% ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]), @@ -331,7 +332,7 @@ sync(suite) -> sync(doc) -> ["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 Str = "än att ta till vapen mot ett hav av kval. ", ?line Bin = list_to_binary(Str), %% sync_test(?FILE_MODULE, Str, [ram, read, write]), @@ -365,8 +366,8 @@ get_set_file(doc) -> ["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 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), %% |