diff options
44 files changed, 733 insertions, 321 deletions
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 4efd155b09..b2e2254a65 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -1101,15 +1101,6 @@ typedef enum { Erlang operators <c>=:=</c> and <c>=/=</c>.</p></desc> </func> - <func><name><ret>int</ret><nametext>enif_is_on_dirty_scheduler(ErlNifEnv* env)</nametext></name> - <fsummary>Check to see if executing on a dirty scheduler thread</fsummary> - <desc> - <p>Check to see if the current NIF is executing on a dirty scheduler thread. If - executing on a dirty scheduler thread true returned; otherwise false.</p> - <p>This function can only be used from a NIF-calling thread, and with an - environment corresponding to currently executing processes.</p> - </desc> - </func> <func><name><ret>int</ret><nametext>enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> <fsummary>Determine if a term is a pid</fsummary> <desc><p>Return true if <c>term</c> is a pid.</p></desc> @@ -1820,7 +1811,25 @@ enif_map_iterator_destroy(env, &iter); <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_self">erl_drv_thread_self</seealso>. </p></desc> </func> - + <func><name><ret>int</ret><nametext>enif_thread_type(void)</nametext></name> + <fsummary>Determine type of current thread</fsummary> + <desc> + <p>Determine the type of currently executing thread. A positive value + indicates a scheduler thread while a negative value or zero indicates + another type of thread. Currently the following specific types exist + (which may be extended in the future):</p> + <taglist> + <tag><c>ERL_NIF_THR_UNDEFINED</c></tag> + <value><p>Undefined thread that is not a scheduler thread.</p></value> + <tag><c>ERL_NIF_THR_NORMAL_SCHEDULER</c></tag> + <value><p>A normal scheduler thread.</p></value> + <tag><c>ERL_NIF_THR_DIRTY_CPU_SCHEDULER</c></tag> + <value><p>A dirty CPU scheduler thread.</p></value> + <tag><c>ERL_NIF_THR_DIRTY_IO_SCHEDULER</c></tag> + <value><p>A dirty I/O scheduler thread.</p></value> + </taglist> + </desc> + </func> <func> <name><ret>ErlNifTime</ret><nametext>enif_time_offset(ErlNifTimeUnit time_unit)</nametext></name> <fsummary>Get current Time Offset</fsummary> diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 37f4e1de49..fefa9d8391 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -1411,7 +1411,7 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3) trunc_len = val; goto next_option; case am_line_delimiter: - if (type == TCP_PB_LINE_LF && val >= 0 && val <= 255) { + if (type == TCP_PB_LINE_LF && val <= 255) { delimiter = (char)val; goto next_option; } diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 4fd82bad10..039f97ef43 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -2658,18 +2658,21 @@ done: } int -enif_is_on_dirty_scheduler(ErlNifEnv* env) +enif_thread_type(void) { - int scheduler; - Process *c_p; + ErtsSchedulerData *esdp = erts_get_scheduler_data(); - execution_state(env, &c_p, &scheduler); + if (!esdp) + return ERL_NIF_THR_UNDEFINED; + + if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) + return ERL_NIF_THR_NORMAL_SCHEDULER; - if (!c_p || !scheduler) - erts_exit(ERTS_ABORT_EXIT, "enif_is_on_dirty_scheduler: " - "Invalid env"); + if (ERTS_SCHEDULER_IS_DIRTY_CPU(esdp)) + return ERL_NIF_THR_DIRTY_CPU_SCHEDULER; - return scheduler < 0; + ASSERT(ERTS_SCHEDULER_IS_DIRTY_IO(esdp)); + return ERL_NIF_THR_DIRTY_IO_SCHEDULER; } /* Maps */ diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index da7a754757..494971e118 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -209,6 +209,17 @@ typedef enum { ERL_NIF_BIN2TERM_SAFE = 0x20000000 } ErlNifBinaryToTerm; +/* + * Return values from enif_thread_type(). Negative values + * reserved for specific types of non-scheduler threads. + * Positive values reserved for scheduler thread types. + */ + +#define ERL_NIF_THR_UNDEFINED 0 +#define ERL_NIF_THR_NORMAL_SCHEDULER 1 +#define ERL_NIF_THR_DIRTY_CPU_SCHEDULER 2 +#define ERL_NIF_THR_DIRTY_IO_SCHEDULER 3 + #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS typedef struct { diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index b211ab4b16..9a8f216773 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -173,7 +173,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_get_local_port, (ErlNifEnv* env, ERL_NIF_TERM, E ERL_NIF_API_FUNC_DECL(int, enif_term_to_binary, (ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin)); ERL_NIF_API_FUNC_DECL(size_t, enif_binary_to_term, (ErlNifEnv *env, const unsigned char* data, size_t sz, ERL_NIF_TERM *term, unsigned int opts)); ERL_NIF_API_FUNC_DECL(int, enif_port_command, (ErlNifEnv *env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)); -ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); +ERL_NIF_API_FUNC_DECL(int,enif_thread_type,(void)); ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char *format, ...)); /* @@ -330,7 +330,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char # define enif_term_to_binary ERL_NIF_API_FUNC_MACRO(enif_term_to_binary) # define enif_binary_to_term ERL_NIF_API_FUNC_MACRO(enif_binary_to_term) # define enif_port_command ERL_NIF_API_FUNC_MACRO(enif_port_command) -# define enif_is_on_dirty_scheduler ERL_NIF_API_FUNC_MACRO(enif_is_on_dirty_scheduler) +# define enif_thread_type ERL_NIF_API_FUNC_MACRO(enif_thread_type) # define enif_snprintf ERL_NIF_API_FUNC_MACRO(enif_snprintf) /* diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index c0b1d7246c..5193be85b4 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -10082,7 +10082,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) } } - if (ERTS_IS_GC_DESIRED(p)) { + if (ERTS_IS_GC_DESIRED(p) && !ERTS_SCHEDULER_IS_DIRTY_IO(esdp)) { if (!(state & ERTS_PSFLG_EXITING) && !(p->flags & (F_DELAY_GC|F_DISABLE_GC))) { int cost = scheduler_gc_proc(p, reds); calls += cost; diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 9a205d50d3..dfe82cab44 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -154,8 +154,9 @@ typedef ERTS_SYS_FD_TYPE ErtsSysFdType; # define ERTS_WRITE_UNLIKELY(X) X #endif +/* clang may have too low __GNUC__ versions but can handle it */ #ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined(__clang__) # define ERTS_DECLARE_DUMMY(X) X __attribute__ ((unused)) # else # define ERTS_DECLARE_DUMMY(X) X diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index e38bececde..d92933a096 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -48,7 +48,8 @@ static ERL_NIF_TERM dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ char s[10]; ErlNifBinary b; if (have_dirty_schedulers()) { - assert(enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_DIRTY_CPU_SCHEDULER == enif_thread_type() + || ERL_NIF_THR_DIRTY_IO_SCHEDULER == enif_thread_type()); } assert(argc == 3); enif_get_int(env, argv[0], &n); @@ -65,7 +66,7 @@ static ERL_NIF_TERM call_dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM int n; char s[10]; ErlNifBinary b; - assert(!enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_NORMAL_SCHEDULER == enif_thread_type()); if (argc != 3) return enif_make_badarg(env); if (have_dirty_schedulers()) { @@ -151,7 +152,8 @@ dirty_sleeper(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifPid pid; ErlNifEnv* msg_env = NULL; - assert(enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_DIRTY_CPU_SCHEDULER == enif_thread_type() + || ERL_NIF_THR_DIRTY_IO_SCHEDULER == enif_thread_type()); /* If we get a pid argument, it indicates a process involved in the test wants a message from us. Prior to the sleep we send a 'ready' @@ -221,7 +223,8 @@ static ERL_NIF_TERM dirty_heap_access_nif(ErlNifEnv* env, int argc, const ERL_NI { ERL_NIF_TERM res = enif_make_list(env, 0); int i; - assert(enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_DIRTY_CPU_SCHEDULER == enif_thread_type() + || ERL_NIF_THR_DIRTY_IO_SCHEDULER == enif_thread_type()); for (i = 0; i < 1000; i++) res = enif_make_list_cell(env, enif_make_copy(env, argv[0]), res); diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index eaa4026a8a..4ebc1f5782 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -147,11 +147,7 @@ spawn_with_binaries(Config) when is_list(Config) -> TwoMeg = lists:duplicate(1024, L), Fun = fun() -> spawn(?MODULE, binary_owner, [list_to_binary(TwoMeg)]), receive after 1 -> ok end end, - Iter = case test_server:purify_is_running() of - true -> 10; - false -> 150 - end, - test_server:do_times(Iter, Fun), + test_server:do_times(150, Fun), ok. binary_owner(Bin) when is_binary(Bin) -> diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl index 919526c5d7..bd677e971b 100644 --- a/lib/common_test/src/test_server.erl +++ b/lib/common_test/src/test_server.erl @@ -21,7 +21,7 @@ -define(DEFAULT_TIMETRAP_SECS, 60). %%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([run_test_case_apply/1,init_target_info/0,init_purify/0]). +-export([run_test_case_apply/1,init_target_info/0]). -export([cover_compile/1,cover_analyse/2]). %%% TEST_SERVER_SUP INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -49,10 +49,6 @@ -export([break/1,break/2,break/3,continue/0,continue/1]). -%%% DEBUGGER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([purify_new_leaks/0, purify_format/2, purify_new_fds_inuse/0, - purify_is_running/0]). - %%% PRIVATE EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([]). @@ -73,10 +69,6 @@ init_target_info() -> username=test_server_sup:get_username(), cookie=atom_to_list(erlang:get_cookie())}. -init_purify() -> - purify_new_leaks(). - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% cover_compile(#cover{app=App,incl=Include,excl=Exclude,cross=Cross}) -> %% {ok,#cover{mods=AnalyseModules}} | {error,Reason} @@ -100,7 +92,7 @@ cover_compile(CoverInfo=#cover{app=none,incl=Include,cross=Cross}) -> case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), - cover:start(), % start cover server anyway + {ok, _} = start_cover(), % start cover server anyway {ok,CoverInfo#cover{mods=[]}}; N -> io:fwrite("Cover compiling ~w modules - " @@ -115,7 +107,7 @@ cover_compile(CoverInfo=#cover{app=App,excl=all,incl=Include,cross=Cross}) -> case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), - cover:start(), % start cover server anyway + {ok, _} = start_cover(), % start cover server anyway {ok,CoverInfo#cover{mods=[]}}; N -> io:fwrite("Cover compiling '~w' (~w files) - " @@ -158,7 +150,7 @@ cover_compile(CoverInfo=#cover{app=App,excl=Exclude, case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), - cover:start(), % start cover server anyway + {ok, _} = start_cover(), % start cover server anyway {ok,CoverInfo#cover{mods=[]}}; N -> io:fwrite("Cover compiling '~w' (~w files) - " @@ -175,11 +167,11 @@ module_names(Beams) -> do_cover_compile(Modules) -> - cover:start(), + {ok, _} = start_cover(), Sticky = prepare_cover_compile(Modules,[]), R = cover:compile_beam(Modules), - [warn_compile(Error) || Error <- R,element(1,Error)=/=ok], - [code:stick_mod(M) || M <- Sticky], + _ = [warn_compile(Error) || Error <- R,element(1,Error)=/=ok], + _ = [code:stick_mod(M) || M <- Sticky], ok. warn_compile({error,{Reason,Module}}) -> @@ -366,9 +358,7 @@ stick_all_sticky(Node,Sticky) -> %% compensate timetraps for runtime delays introduced by e.g. tools like %% cover. -run_test_case_apply({CaseNum,Mod,Func,Args,Name, - RunInit,TimetrapData}) -> - purify_format("Test case #~w ~w:~w/1", [CaseNum, Mod, Func]), +run_test_case_apply({Mod,Func,Args,Name,RunInit,TimetrapData}) -> case os:getenv("TS_RUN_VALGRIND") of false -> ok; @@ -380,7 +370,6 @@ run_test_case_apply({CaseNum,Mod,Func,Args,Name, Result = run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData), ProcAft = erlang:system_info(process_count), - purify_new_leaks(), DetFail = get(test_server_detected_fail), {Result,DetFail,ProcBef,ProcAft}. @@ -585,7 +574,8 @@ run_test_case_msgloop(#st{ref=Ref,pid=Pid,end_conf_pid=EndConfPid0}=St0) -> {user_timetrap,Pid,_TrapTime,StartTime,E={user_timetrap_error,_},_} -> case update_user_timetraps(Pid, StartTime) of proceed -> - self() ! {abort_current_testcase,E,Pid}; + self() ! {abort_current_testcase,E,Pid}, + ok; ignore -> ok end, @@ -600,7 +590,8 @@ run_test_case_msgloop(#st{ref=Ref,pid=Pid,end_conf_pid=EndConfPid0}=St0) -> true -> TrapTime end, - timetrap(TrapTime, TotalTime, Pid, Scale); + _ = timetrap(TrapTime, TotalTime, Pid, Scale), + ok; ignore -> ok end, @@ -724,7 +715,7 @@ do_call_end_conf(Starter,Mod,Func,Data,TCExitReason,Conf,TVal) -> Supervisor = self(), EndConfApply = fun() -> - timetrap(TVal), + _ = timetrap(TVal), %% We can't handle fails or skips here %% (neither input nor output). The error can %% be read from Conf though (tc_status). @@ -775,7 +766,8 @@ print_end_conf_result(Mod,Func,Conf,Cause,Error) -> " ~s!\n\tReason: ~ts\n", [Mod,Func,Conf,Cause,ErrorStr]) end, - group_leader() ! {printout,12,Str2Print}. + group_leader() ! {printout,12,Str2Print}, + ok. spawn_fw_call(Mod,IPTC={init_per_testcase,Func},CurrConf,Pid, @@ -1287,7 +1279,9 @@ user_callback({CBMod,CBFunc}, Mod, Func, InitOrEnd, Args) -> init_per_testcase(Mod, Func, Args) -> case code:is_loaded(Mod) of - false -> code:load_file(Mod); + false -> + _ = code:load_file(Mod), + ok; _ -> ok end, case erlang:function_exported(Mod, init_per_testcase, 2) of @@ -1355,7 +1349,8 @@ print_init_conf_result(Line,Cause,Reason) -> "\tLocation: ~ts\n\tReason: ~ts\n", [Cause,FormattedLoc,ReasonStr]) end, - group_leader() ! {printout,12,Str2Print}. + group_leader() ! {printout,12,Str2Print}, + ok. end_per_testcase(Mod, Func, Conf) -> @@ -1426,7 +1421,8 @@ print_end_tc_warning(EndFunc,Reason,Cause,Loc) -> "Reason: ~ts\nLine: ~ts\n", [EndFunc,Cause,ReasonStr,FormattedLoc]) end, - group_leader() ! {printout,12,Str2Print}. + group_leader() ! {printout,12,Str2Print}, + ok. get_loc() -> get(test_server_loc). @@ -1829,7 +1825,6 @@ timetrap_scale_factor() -> timetrap_scale_factor([ { 2, fun() -> has_lock_checking() end}, { 3, fun() -> has_superfluous_schedulers() end}, - { 5, fun() -> purify_is_running() end}, { 6, fun() -> is_debug() end}, {10, fun() -> is_cover() end} ]). @@ -2129,7 +2124,8 @@ timetrap_cancel_all(TCPid, SendToServer) -> ok; Timers -> [timetrap_cancel_one(Handle, false) || - {Handle,Pid,_} <- Timers, Pid == TCPid] + {Handle,Pid,_} <- Timers, Pid == TCPid], + ok end, case get(test_server_user_timetrap) of undefined -> @@ -2139,13 +2135,15 @@ timetrap_cancel_all(TCPid, SendToServer) -> {UserTTSup,_StartTime} -> remove_user_timetrap(UserTTSup), put(test_server_user_timetrap, - proplists:delete(TCPid, UserTTs)); + proplists:delete(TCPid, UserTTs)), + ok; undefined -> ok end end, if SendToServer == true -> - group_leader() ! {timetrap_cancel_all,TCPid,self()}; + group_leader() ! {timetrap_cancel_all,TCPid,self()}, + ok; true -> ok end, @@ -2560,10 +2558,11 @@ run_on_shielded_node(Fun, CArgs) when is_function(Fun), is_list(CArgs) -> -spec start_job_proxy_fun(_, _) -> fun(() -> no_return()). start_job_proxy_fun(Master, Fun) -> fun () -> - start_job_proxy(), + _ = start_job_proxy(), receive Ref -> - Master ! {Ref, Fun()} + Master ! {Ref, Fun()}, + ok end, receive after infinity -> infinity end end. @@ -2729,64 +2728,25 @@ is_commercial() -> _ -> true end. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% DEBUGGER INTERFACE %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_is_running() -> false|true -%% -%% Tests if Purify is currently running. - -purify_is_running() -> - case catch erlang:system_info({error_checker, running}) of - {'EXIT', _} -> false; - Res -> Res - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_new_leaks() -> false|BytesLeaked -%% BytesLeaked = integer() -%% -%% Checks for new memory leaks if Purify is active. -%% Returns the number of bytes leaked, or false if Purify -%% is not running. -purify_new_leaks() -> - case catch erlang:system_info({error_checker, memory}) of - {'EXIT', _} -> false; - Leaked when is_integer(Leaked) -> Leaked - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_new_fds_inuse() -> false|FdsInuse -%% FdsInuse = integer() -%% -%% Checks for new file descriptors in use. -%% Returns the number of new file descriptors in use, or false -%% if Purify is not running. -purify_new_fds_inuse() -> - case catch erlang:system_info({error_checker, fd}) of - {'EXIT', _} -> false; - Inuse when is_integer(Inuse) -> Inuse - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_format(Format, Args) -> ok -%% Format = string() -%% Args = lists() -%% -%% Outputs the formatted string to Purify's logfile,if Purify is active. -purify_format(Format, Args) -> - (catch erlang:system_info({error_checker, io_lib:format(Format, Args)})), - ok. - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Apply given function and reply to caller or proxy. %% do_sync_apply(Proxy, From, {M,F,A}) -> Result = apply(M, F, A), - if is_pid(Proxy) -> Proxy ! {sync_result_proxy,From,Result}; - true -> From ! {sync_result,Result} + if is_pid(Proxy) -> + Proxy ! {sync_result_proxy,From,Result}, + ok; + true -> + From ! {sync_result,Result}, + ok end. + +start_cover() -> + case cover:start() of + {error, {already_started, Pid}} -> + {ok, Pid}; + Else -> + Else + end. + diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl index ff960c22a5..84e35e7371 100644 --- a/lib/common_test/src/test_server_ctrl.erl +++ b/lib/common_test/src/test_server_ctrl.erl @@ -512,7 +512,7 @@ init([]) -> TI = TI0#target_info{host=TargetHost, naming=naming(), master=TargetHost}, - ets:new(slave_tab, [named_table,set,public,{keypos,2}]), + _ = ets:new(slave_tab, [named_table,set,public,{keypos,2}]), set_hosts([TI#target_info.host]), {ok,State#state{target_info=TI}}. @@ -867,7 +867,7 @@ handle_call({create_priv_dir,Value}, _From, State) -> handle_call({testcase_callback,ModFunc}, _From, State) -> case ModFunc of {Mod,Func} -> - case code:is_loaded(Mod) of + _ = case code:is_loaded(Mod) of {file,_} -> ok; false -> @@ -1079,8 +1079,8 @@ terminate(_Reason, State) -> false -> ok; Sock -> test_server_node:stop_tracer_node(Sock) end, - kill_all_jobs(State#state.jobs), - test_server_node:kill_nodes(), + ok = kill_all_jobs(State#state.jobs), + _ = test_server_node:kill_nodes(), ok. kill_all_jobs([{_Name,JobPid}|Jobs]) -> @@ -1125,7 +1125,7 @@ spawn_tester(Mod, Func, Args, Dir, Name, Levels, RejectIoReqs, init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels, RejectIoReqs, CreatePrivDir, TCCallback, ExtraTools) -> process_flag(trap_exit, true), - test_server_io:start_link(), + _ = test_server_io:start_link(), put(test_server_name, Name), put(test_server_dir, Dir), put(test_server_total_time, 0), @@ -1199,8 +1199,7 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels, {UnexpectedIoName,UnexpectedIoFooter} = get(test_server_unexpected_footer), {ok,UnexpectedIoFd} = open_html_file(UnexpectedIoName, [append]), io:put_chars(UnexpectedIoFd, "\n</pre>\n"++UnexpectedIoFooter), - file:close(UnexpectedIoFd), - ok. + ok = file:close(UnexpectedIoFd). report_severe_error(Reason) -> test_server_sup:framework_call(report, [severe_error,Reason]). @@ -1927,7 +1926,7 @@ html_convert_modules([Mod|Mods]) -> Name = atom_to_list(Mod), DestFile = filename:join(DestDir, downcase(Name)++?src_listing_ext), - html_possibly_convert(SrcFile1, SrcFileInfo, DestFile), + _ = html_possibly_convert(SrcFile1, SrcFileInfo, DestFile), html_convert_modules(Mods) end; _Other -> @@ -2066,7 +2065,7 @@ add_init_and_end_per_suite([], LastMod, LastRef, FwMod) -> end. do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod) -> - case code:is_loaded(Mod) of + _ = case code:is_loaded(Mod) of false -> code:load_file(Mod); _ -> ok end, @@ -2140,7 +2139,6 @@ do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod) -> %% Runs the specified tests, then displays/logs the summary. run_test_cases(TestSpec, Config, TimetrapData) -> - test_server:init_purify(), case lists:member(no_src, get(test_server_logopts)) of true -> ok; @@ -2323,7 +2321,7 @@ run_test_cases_loop([{SkipTag,{Type,Ref,Case,Comment},SkipMode}|Cases], Config, TimetrapData, Mode, Status) when ((SkipTag==auto_skip_case) or (SkipTag==skip_case)) and ((Type==conf) or (Type==make)) -> - file:set_cwd(filename:dirname(get(test_server_dir))), + ok = file:set_cwd(filename:dirname(get(test_server_dir))), CurrIOHandler = get(test_server_common_io_handler), ParentMode = tl(Mode), @@ -2339,7 +2337,7 @@ run_test_cases_loop([{SkipTag,{Type,Ref,Case,Comment},SkipMode}|Cases], false -> %% this is a skipped end conf for a top level parallel %% group, buffered io can be flushed - handle_test_case_io_and_status(), + _ = handle_test_case_io_and_status(), set_io_buffering(undefined), {Mod,Func} = skip_case(AutoOrUser, Ref, 0, Case, Comment, false, SkipMode), @@ -2351,7 +2349,7 @@ run_test_cases_loop([{SkipTag,{Type,Ref,Case,Comment},SkipMode}|Cases], _ -> %% this is a skipped end conf for a parallel group nested %% under a parallel group (io buffering is active) - wait_for_cases(Ref), + _ = wait_for_cases(Ref), {Mod,Func} = skip_case(AutoOrUser, Ref, 0, Case, Comment, true, SkipMode), ConfData = {Mod,{Func,get_name(SkipMode)},Comment}, @@ -2459,7 +2457,7 @@ run_test_cases_loop([{auto_skip_case,{Case,Comment},SkipMode}|Cases], run_test_cases_loop([{skip_case,{{Mod,all}=Case,Comment},SkipMode}|Cases], Config, TimetrapData, Mode, Status) -> - skip_case(user, undefined, 0, Case, Comment, false, SkipMode), + _ = skip_case(user, undefined, 0, Case, Comment, false, SkipMode), test_server_sup:framework_call(report, [tc_user_skip, {Mod,{all,get_name(SkipMode)}, Comment}]), @@ -2489,7 +2487,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, %% collect results from the test case processes %% and calc total time OkSkipFail = handle_test_case_io_and_status(), - file:set_cwd(filename:dirname(get(test_server_dir))), + ok = file:set_cwd(filename:dirname(get(test_server_dir))), After = ?now, Before = get(test_server_parallel_start_time), Elapsed = timer:now_diff(After, Before)/1000000, @@ -3582,7 +3580,7 @@ handle_io_and_exit_loop([], [{undefined,CurrPid,CaseNum,Mod,Func}|Ps] = Cases, O handle_io_and_exit_loop(Refs, [{Ref,CurrPid,CaseNum,Mod,Func}|Ps] = Cases, Ok,Skip,Fail) -> receive {started,_,CurrPid,CaseNum,Mod,Func} -> - handle_io_and_exits(self(), CurrPid, CaseNum, Mod, Func, Cases), + _ = handle_io_and_exits(self(), CurrPid, CaseNum, Mod, Func, Cases), Refs1 = case Refs of [Ref|Rs] -> % must be end conf case for subgroup @@ -3658,7 +3656,7 @@ handle_io_and_exits(Main, CurrPid, CaseNum, Mod, Func, Cases) -> %% about the execution time and the return value of the test case function. run_test_case(Ref, Num, Mod, Func, Args, RunInit, TimetrapData) -> - file:set_cwd(filename:dirname(get(test_server_dir))), + ok = file:set_cwd(filename:dirname(get(test_server_dir))), run_test_case1(Ref, Num, Mod, Func, Args, RunInit, TimetrapData, [], self()). @@ -3668,7 +3666,7 @@ run_test_case(Ref, Num, Mod, Func, Args, skip_init, TimetrapData, Mode) -> TimetrapData, Mode, self()); run_test_case(Ref, Num, Mod, Func, Args, RunInit, TimetrapData, Mode) -> - file:set_cwd(filename:dirname(get(test_server_dir))), + ok = file:set_cwd(filename:dirname(get(test_server_dir))), Main = self(), case check_prop(parallel, Mode) of false -> @@ -3682,7 +3680,7 @@ run_test_case(Ref, Num, Mod, Func, Args, RunInit, TimetrapData, Mode) -> spawn_link( fun() -> process_flag(trap_exit, true), - [put(Key, Val) || {Key,Val} <- Dictionary], + _ = [put(Key, Val) || {Key,Val} <- Dictionary], set_io_buffering({tc,Main}), run_test_case1(Ref, Num, Mod, Func, Args, RunInit, TimetrapData, Mode, Main) @@ -3699,7 +3697,8 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, false -> ok; true -> test_server_io:start_transaction(), - Main ! {started,Ref,self(),Num,Mod,Func} + Main ! {started,Ref,self(),Num,Mod,Func}, + ok end, TSDir = get(test_server_dir), @@ -3774,7 +3773,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, %% run the test case {Result,DetectedFail,ProcsBefore,ProcsAfter} = - run_test_case_apply(Num, Mod, Func, [UpdatedArgs], GrName, + run_test_case_apply(Mod, Func, [UpdatedArgs], GrName, RunInit, TimetrapData), {Time,RetVal,Loc,Opts,Comment} = case Result of @@ -3906,7 +3905,8 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, true -> test_server_io:end_transaction(), Main ! {finished,Ref,self(),Num,Mod,Func, - ?mod_result(Status),{Time,RetVal,Opts}} + ?mod_result(Status),{Time,RetVal,Opts}}, + ok end, {Time,RetVal,Opts}. @@ -4329,7 +4329,7 @@ do_format_exception(Reason={Error,Stack}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, +%% run_test_case_apply(Mod, Func, Args, Name, RunInit, %% TimetrapData) -> %% {{Time,RetVal,Loc,Opts,Comment},DetectedFail,ProcessesBefore,ProcessesAfter} | %% {{died,Reason,unknown,Comment},DetectedFail,ProcessesBefore,ProcessesAfter} @@ -4343,9 +4343,9 @@ do_format_exception(Reason={Error,Stack}) -> %% ProcessesBefore = ProcessesAfter = integer() %% -run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, +run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) -> - test_server:run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit, + test_server:run_test_case_apply({Mod,Func,Args,Name,RunInit, TimetrapData}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -5276,7 +5276,8 @@ check_cross([]) -> %% This per application analysis writes the file cover.html in the %% application's run.<timestamp> directory. stop_cover(#cover{}=CoverInfo, TestDir) -> - cover_analyse(CoverInfo, TestDir); + cover_analyse(CoverInfo, TestDir), + ok; stop_cover(_CoverInfo, _TestDir) -> %% Cover is probably controlled by the framework ok. @@ -5315,7 +5316,7 @@ cover_analyse(CoverInfo, TestDir) -> [?cross_coverlog_name]), io:fwrite(CoverLog, "<p>CoverFile: <code>~tp</code>\n", [CoverFile]), - write_cross_cover_info(TestDir,Cross), + ok = write_cross_cover_info(TestDir,Cross), case length(cover:imported_modules()) of Imps when Imps > 0 -> @@ -5329,7 +5330,7 @@ cover_analyse(CoverInfo, TestDir) -> io:fwrite(CoverLog, "<p>Excluded module(s): <code>~tp</code>\n", [Excluded]), Coverage = test_server:cover_analyse(TestDir, CoverInfo), - write_binary_file(filename:join(TestDir,?raw_coverlog_name), + ok = write_binary_file(filename:join(TestDir,?raw_coverlog_name), term_to_binary(Coverage)), case lists:filter(fun({_M,{_,_,_}}) -> false; @@ -5344,8 +5345,8 @@ cover_analyse(CoverInfo, TestDir) -> end, TotPercent = write_cover_result_table(CoverLog, Coverage), - write_binary_file(filename:join(TestDir, ?cover_total), - term_to_binary(TotPercent)). + ok = write_binary_file(filename:join(TestDir, ?cover_total), + term_to_binary(TotPercent)). %% Cover analysis - accumulated over multiple tests %% This can be executed on any node after all tests are finished. @@ -5395,7 +5396,7 @@ write_cross_cover_info(Dir,Cross) -> write_cross_cover_logs([{Tag,Coverage}|T],TagDirMods) -> case lists:keyfind(Tag,1,TagDirMods) of {_,Dir,Mods} when Mods=/=[] -> - write_binary_file(filename:join(Dir,?raw_cross_coverlog_name), + ok = write_binary_file(filename:join(Dir,?raw_cross_coverlog_name), term_to_binary(Coverage)), CoverLogName = filename:join(Dir,?cross_coverlog_name), {ok,CoverLog} = open_html_file(CoverLogName), diff --git a/lib/common_test/src/test_server_gl.erl b/lib/common_test/src/test_server_gl.erl index 333c8fc06e..7d6fe64b92 100644 --- a/lib/common_test/src/test_server_gl.erl +++ b/lib/common_test/src/test_server_gl.erl @@ -185,7 +185,7 @@ handle_info({capture,Cap0}, St) -> end, {noreply,St#st{capture=Cap}}; handle_info({io_request,From,ReplyAs,Req}=IoReq, St) -> - try io_req(Req, From, St) of + _ = try io_req(Req, From, St) of passthrough -> group_leader() ! IoReq; {EscapeHtml,Data} -> @@ -197,7 +197,8 @@ handle_info({io_request,From,ReplyAs,Req}=IoReq, St) -> #st{capture=none} -> ok; #st{capture=CapturePid} -> - CapturePid ! {captured,Data} + CapturePid ! {captured,Data}, + ok end, case EscapeHtml andalso St#st.escape_chars of true -> diff --git a/lib/common_test/src/test_server_io.erl b/lib/common_test/src/test_server_io.erl index 8c5c0aef35..3d5238052b 100644 --- a/lib/common_test/src/test_server_io.erl +++ b/lib/common_test/src/test_server_io.erl @@ -215,7 +215,7 @@ handle_call({set_fd,Tag,Fd}, _From, #st{fds=Fds0,tags=Tags0, true -> %% Fd ready, print anything buffered for associated Tag lists:filtermap(fun({T,From,Str}) when T == Tag -> - output(From, Tag, Str, St1), + _ = output(From, Tag, Str, St1), false; (_) -> true @@ -274,14 +274,15 @@ handle_call(reset_state, _From, #st{fds=Fds,tags=Tags,gls=Gls, end end, Tags), GlList = gb_sets:to_list(Gls), - [test_server_gl:stop(GL) || GL <- GlList], + _ = [test_server_gl:stop(GL) || GL <- GlList], timer:sleep(100), case lists:filter(fun(GlPid) -> is_process_alive(GlPid) end, GlList) of [] -> ok; _ -> timer:sleep(2000), - [exit(GL, kill) || GL <- GlList] + [exit(GL, kill) || GL <- GlList], + ok end, Empty = gb_trees:empty(), {ok,Shared} = test_server_gl:start_link(), @@ -304,7 +305,7 @@ handle_call({stop,FdTags}, From, #st{fds=Fds0,tags=Tags0, none -> {Fds,Tags}; {value,Fd} -> - file:close(Fd), + _ = file:close(Fd), {gb_trees:delete(Tag, Fds), lists:delete(Tag, Tags)} end @@ -333,7 +334,7 @@ handle_info({'EXIT',_Pid,Reason}, _St) -> handle_info(stop_group_leaders, #st{gls=Gls}=St) -> %% Stop the remaining group leaders. GlPids = gb_sets:to_list(Gls), - [test_server_gl:stop(GL) || GL <- GlPids], + _ = [test_server_gl:stop(GL) || GL <- GlPids], timer:sleep(100), Wait = case lists:filter(fun(GlPid) -> is_process_alive(GlPid) end, GlPids) of @@ -344,7 +345,7 @@ handle_info(stop_group_leaders, #st{gls=Gls}=St) -> {noreply,St}; handle_info(kill_group_leaders, #st{gls=Gls,stopping=From, pending_ops=Ops}=St) -> - [exit(GL, kill) || GL <- gb_sets:to_list(Gls)], + _ = [exit(GL, kill) || GL <- gb_sets:to_list(Gls)], if From /= undefined -> gen_server:reply(From, ok); true -> % reply has been sent already @@ -434,7 +435,7 @@ do_print_buffered(Q0, St) -> eot -> Q; {Tag,Str} -> - do_output(Tag, Str, undefined, St), + _ = do_output(Tag, Str, undefined, St), do_print_buffered(Q, St) end. @@ -448,5 +449,5 @@ gc(#st{gls=Gls0}) -> InUse = ordsets:from_list(InUse0), Gls = gb_sets:to_list(Gls0), NotUsed = ordsets:subtract(Gls, InUse), - [test_server_gl:stop(Pid) || Pid <- NotUsed], + _ = [test_server_gl:stop(Pid) || Pid <- NotUsed], ok. diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl index c64399e485..0b406c54cc 100644 --- a/lib/common_test/src/test_server_node.erl +++ b/lib/common_test/src/test_server_node.erl @@ -198,9 +198,9 @@ trc_loop(Sock,Patterns,Type) -> gen_tcp:close(Sock) end. add_nodes(Nodes,Patterns,_Type) -> - ttb:tracer(Nodes,[{file,{local, test_server}}, - {handler, {{?MODULE,handle_debug},initial}}]), - ttb:p(all,[call,timestamp]), + {ok, _} = ttb:tracer(Nodes,[{file,{local, test_server}}, + {handler, {{?MODULE,handle_debug},initial}}]), + {ok, _} = ttb:p(all,[call,timestamp]), lists:foreach(fun({TP,M,F,A,Pat}) -> ttb:TP(M,F,A,Pat); ({CTP,M,F,A}) -> ttb:CTP(M,F,A) end, @@ -360,8 +360,8 @@ start_node_peer(SlaveName, OptList, From, TI) -> -spec wait_for_node_started_fun(_, _, _, _, _) -> fun(() -> no_return()). wait_for_node_started_fun(LSock, Tmo, Cleanup, TI, Self) -> fun() -> - wait_for_node_started(LSock,Tmo,undefined, - Cleanup,TI,Self), + {{ok, _}, _} = wait_for_node_started(LSock,Tmo,undefined, + Cleanup,TI,Self), receive after infinity -> ok end end. @@ -432,7 +432,7 @@ wait_for_node_started(LSock,Timeout,Client,Cleanup,TI,CtrlPid) -> client=Client}); false -> ok end, - gen_tcp:controlling_process(Sock,CtrlPid), + ok = gen_tcp:controlling_process(Sock,CtrlPid), test_server_ctrl:node_started(Nodename), {{ok,Nodename},W} end; diff --git a/lib/common_test/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl index fa2bb33c2d..6922e01fcc 100644 --- a/lib/common_test/src/test_server_sup.erl +++ b/lib/common_test/src/test_server_sup.erl @@ -755,7 +755,7 @@ framework_call(FW,_Func,_Args,DefaultReturn) DefaultReturn; framework_call(Callback,Func,Args,DefaultReturn) -> Mod = list_to_atom(Callback), - case code:is_loaded(Mod) of + _ = case code:is_loaded(Mod) of false -> code:load_file(Mod); _ -> ok end, @@ -851,7 +851,8 @@ util_start() -> spawn_link(fun() -> register(?MODULE, self()), util_loop(#util_state{starter=Starter}) - end); + end), + ok; _Pid -> ok end. diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl index e1c16fbda4..f1c5051164 100644 --- a/lib/common_test/src/vts.erl +++ b/lib/common_test/src/vts.erl @@ -64,7 +64,7 @@ %%%----------------------------------------------------------------- %%% User API start() -> - ct_webtool:start(), + {ok, _} = ct_webtool:start(), ct_webtool:start_tools([],"app=vts"). init_data(ConfigFiles,EvHandlers,LogDir,LogOpts,Tests) -> @@ -169,7 +169,7 @@ loop(State) -> NewState = State#state{config=Config,event_handler=EvHandlers, current_log_dir=LogDir, logopts=LogOpts,tests=Tests}, - ct_install(NewState), + _ = ct_install(NewState), return(From,ok), loop(NewState); {start_page,From} -> @@ -192,12 +192,12 @@ loop(State) -> loop(State); {{add_config_file,Input},From} -> {Return,State1} = add_config_file1(Input,State), - ct_install(State1), + _ = ct_install(State1), return(From,Return), loop(State1); {{remove_config_file,Input},From} -> {Return,State1} = remove_config_file1(Input,State), - ct_install(State1), + _ = ct_install(State1), return(From,Return), loop(State1); {run_frame,From} -> @@ -233,7 +233,7 @@ loop(State) -> return(From,result_summary_frame1(State)), loop(State); stop_reload_results -> - file:set_cwd(State#state.start_dir), + ok = file:set_cwd(State#state.start_dir), loop(State#state{reload_results=false}); {no_result_log_frame,From} -> return(From,no_result_log_frame1()), @@ -277,8 +277,8 @@ call(Msg) -> end. return({To,Ref},Result) -> - To ! {Ref, Result}. - + To ! {Ref, Result}, + ok. run_test1(State=#state{tests=Tests,current_log_dir=LogDir, logopts=LogOpts}) -> @@ -311,7 +311,6 @@ run_test1(State=#state{tests=Tests,current_log_dir=LogDir, ct_install(#state{config=Config,event_handler=EvHandlers, current_log_dir=LogDir}) -> ct_run:install([{config,Config},{event_handler,EvHandlers}],LogDir). - %%%----------------------------------------------------------------- %%% HTML start_page1() -> @@ -549,7 +548,7 @@ case_select(Dir,Suite,Case,N) -> end, case MakeResult of ok -> - code:add_pathz(Dir), + true = code:add_pathz(Dir), case catch apply(Suite,all,[]) of {'EXIT',Reason} -> io:format("\n~p\n",[Reason]), @@ -755,7 +754,7 @@ report1(tests_start,{TestName,_N},State) -> end, State#state{testruns=TestRuns}; report1(tests_done,{_Ok,_Fail,_Skip},State) -> - timer:send_after(5000, self(),stop_reload_results), + {ok, _} = timer:send_after(5000, self(),stop_reload_results), State#state{running=State#state.running-1,reload_results=true}; report1(tc_start,{_Suite,_Case},State) -> State; diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index 1532b6c1f7..b1eddfedd7 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -69,7 +69,8 @@ MODULES= \ erl2html2_SUITE \ test_server_SUITE \ test_server_test_lib \ - ct_release_test_SUITE + ct_release_test_SUITE \ + ct_log_SUITE ERL_FILES= $(MODULES:%=%.erl) HRL_FILES= test_server_test_lib.hrl diff --git a/lib/common_test/test/ct_log_SUITE.erl b/lib/common_test/test/ct_log_SUITE.erl new file mode 100644 index 0000000000..9bdd44cbdf --- /dev/null +++ b/lib/common_test/test/ct_log_SUITE.erl @@ -0,0 +1,328 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File: ct_log_SUITE +%%% +%%% Description: Test that ct:log, ct:pal and io:format print to +%%% the test case log file as expected, with or without special HTML +%%% characters being escaped. +%%% +%%%------------------------------------------------------------------- +-module(ct_log_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [{group,print_and_verify}]. + +groups() -> + [{print_and_verify,[sequence],[print,verify]}]. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +print(Config) -> + TcLogFile = proplists:get_value(tc_logfile, Config), + Pid = self(), + String = atom_to_list(?MODULE), + + %% START mark + io:format("LOGGING START~n"), + + %% io:format + io:format("1. Printing nothing~n", []), + io:format("2. Printing a string: ~s~n", [String]), + io:format("3. Printing a string: ~p~n", [String]), + io:format("4. Printing a tuple: ~w~n", [{module,?MODULE}]), + io:format("5. Printing a pid: ~w~n", [Pid]), + io:format("6. Printing HTML: <pre>~s</pre>~n", [String]), + + %% --- API --- + %% pal(Format) -> + %% = ct:pal(default, 50, Format, []). + %% pal(X1, X2) -> ok + %% X1 = Category | Importance | Format + %% X2 = Format | FormatArgs + %% pal(X1, X2, X3) -> ok + %% X1 = Category | Importance + %% X2 = Importance | Format + %% X3 = Format | FormatArgs + %% pal(Category, Importance, Format, FormatArgs) -> ok + %% ------ + ct:pal("1. Printing nothing"), + ct:pal("2. Printing nothing", []), + ct:pal("3. Printing a string: ~s", [String]), + ct:pal("4. Printing a string: ~p", [String]), + ct:pal("5. Printing a tuple: ~w", [{module,?MODULE}]), + ct:pal("6. Printing a pid: ~w", [Pid]), + ct:pal("7. Printing HTML: <pre>~s</pre>", [String]), + ct:pal(ct_internal, "8. Printing with category"), + ct:pal(ct_internal, "9. Printing with ~s", ["category"]), + ct:pal(50, "10. Printing with importance"), + ct:pal(50, "11. Printing with ~s", ["importance"]), + ct:pal(ct_internal, 50, "12. Printing with ~s", ["category and importance"]), + + %% --- API --- + %% log(Format) -> ok + %% = ct:log(default, 50, Format, [], []). + %% log(X1, X2) -> ok + %% X1 = Category | Importance | Format + %% X2 = Format | FormatArgs + %% log(X1, X2, X3) -> ok + %% X1 = Category | Importance + %% X2 = Importance | Format + %% X3 = Format | FormatArgs | Opts + %% log(X1, X2, X3, X4) -> ok + %% X1 = Category | Importance + %% X2 = Importance | Format + %% X3 = Format | FormatArgs + %% X4 = FormatArgs | Opts + %% log(Category, Importance, Format, FormatArgs, Opts) -> ok + %% ------ + ct:log("1. Printing nothing"), + ct:log("2. Printing nothing", []), + ct:log("3. Printing a string: ~s", [String]), + ct:log("4. Printing a string: ~p", [String]), + ct:log("5. Printing a tuple: ~w", [{module,?MODULE}]), + ct:log("6. Printing a pid: ~w", [Pid]), + ct:log("7. Printing HTML: <pre>~s</pre>", [String]), + ct:log("8. Printing a pid escaped: ~w", [Pid], [esc_chars]), + ct:log("9. Printing a string escaped: ~p", [String], [esc_chars]), + ct:log("10. Printing HTML escaped: <pre>~s</pre>", [String], [esc_chars]), + ct:log("11. Printing a string, no css: ~s", [String], [no_css]), + ct:log("12. Printing a pid escaped, no css: ~w", [Pid], + [esc_chars, no_css]), + ct:log(ct_internal, "13. Printing with category"), + ct:log(ct_internal, "14. Printing with ~s", ["category"]), + ct:log(ct_internal, "15. Printing with ~s, no_css", ["category"], + [no_css]), + ct:log(50, "16. Printing with importance"), + ct:log(50, "17. Printing with ~s", ["importance"]), + ct:log(50, "18. Printing with ~s, no_css", ["importance"], [no_css]), + ct:log(ct_internal, 50, "19. Printing with category and importance"), + ct:log(ct_internal, 50, "20. Printing with ~s", ["category and importance"]), + ct:log(ct_internal, 50, "21. Printing a pid escaped with ~s, no_css: ~w", + ["category and importance",Pid], [esc_chars,no_css]), + + %% END mark + ct:log("LOGGING END", [], [no_css]), + {save_config,[{the_logfile,TcLogFile},{the_pid,Pid},{the_string,String}]}. + + +verify(Config) -> + {print,SavedCfg} = proplists:get_value(saved_config, Config), + TcLogFile = proplists:get_value(the_logfile, SavedCfg), + Pid = proplists:get_value(the_pid, SavedCfg), + StrPid = lists:flatten(io_lib:format("~p",[Pid])), + EscPid = "<" ++ string:substr(StrPid, 2, length(StrPid)-2) ++ ">", + String = proplists:get_value(the_string, SavedCfg), + ct:log("Read from prev testcase: ~p & ~p", [TcLogFile,Pid]), + {ok,Dev} = file:open(TcLogFile, [read]), + ok = read_until(Dev, "LOGGING START\n"), + + %% io:format + match_line(Dev, "1. Printing nothing", []), + read_nl(Dev), + match_line(Dev, "2. Printing a string: ~s", [String]), + read_nl(Dev), + match_line(Dev, "3. Printing a string: ~p", [String]), + read_nl(Dev), + match_line(Dev, "4. Printing a tuple: ~w", [{module,?MODULE}]), + read_nl(Dev), + match_line(Dev, "5. Printing a pid: ~s", [EscPid]), + read_nl(Dev), + match_line(Dev, "6. Printing HTML: <pre>~s</pre>", [String]), + read_nl(Dev), + %% ct:pal + read_header(Dev), + match_line(Dev, "1. Printing nothing", []), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "2. Printing nothing", []), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "3. Printing a string: ~s", [String]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "4. Printing a string: ~p", [String]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "5. Printing a tuple: ~w", [{module,?MODULE}]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "6. Printing a pid: ~s", [EscPid]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "7. Printing HTML: <pre>~s</pre>", [String]), + read_footer(Dev), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "8. Printing with category", []), + read_footer(Dev), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "9. Printing with ~s", ["category"]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "10. Printing with importance", []), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "11. Printing with ~s", ["importance"]), + read_footer(Dev), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "12. Printing with ~s", ["category and importance"]), + read_footer(Dev), + %% ct:log + read_header(Dev), + match_line(Dev, "1. Printing nothing", []), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "2. Printing nothing", []), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "3. Printing a string: ~s", [String]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "4. Printing a string: ~p", [String]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "5. Printing a tuple: ~w", [{module,?MODULE}]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "6. Printing a pid: ~w", [Pid]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "7. Printing HTML: <pre>~s</pre>", [String]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "8. Printing a pid escaped: ~s", [EscPid]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "9. Printing a string escaped: ~p", [String]), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "10. Printing HTML escaped: <pre>~s</pre>", + [String]), + read_footer(Dev), + match_line(Dev, "11. Printing a string, no css: ~s", [String]), + match_line(Dev, "12. Printing a pid escaped, no css: ~s", [EscPid]), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "13. Printing with category", []), + read_footer(Dev), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "14. Printing with ~s", ["category"]), + read_footer(Dev), + match_line(Dev, "15. Printing with ~s, no_css", ["category"]), + read_header(Dev), + match_line(Dev, "16. Printing with importance", []), + read_footer(Dev), + read_header(Dev), + match_line(Dev, "17. Printing with ~s", ["importance"]), + read_footer(Dev), + match_line(Dev, "18. Printing with ~s, no_css", ["importance"]), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "19. Printing with category and importance", []), + read_footer(Dev), + read_header(Dev, "\"ct_internal\""), + match_line(Dev, "20. Printing with ~s", ["category and importance"]), + read_footer(Dev), + match_line(Dev, "21. Printing a pid escaped with ~s, no_css: ~s", + ["category and importance",EscPid]), + + file:close(Dev), + ok. + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +read_until(Dev, Pat) -> + case file:read_line(Dev) of + {ok,Pat} -> + file:read_line(Dev), % \n + ok; + eof -> + file:close(Dev), + {error,{not_found,Pat}}; + _ -> + read_until(Dev, Pat) + end. + +match_line(Dev, Format, Args) -> + Pat = lists:flatten(io_lib:format(Format, Args)), + Line = element(2, file:read_line(Dev)), + case re:run(Line, Pat) of + {match,_} -> + ok; + nomatch -> + ct:pal("ERROR! No match for ~p.\nLine = ~p", [Pat,Line]), + file:close(Dev), + ct:fail({mismatch,Pat,Line}) + end. + +read_header(Dev) -> + read_header(Dev, "\"default\""). + +read_header(Dev, Cat) -> + file:read_line(Dev), % \n + "</pre>\n" = element(2, file:read_line(Dev)), + {match,_} = + re:run(element(2, file:read_line(Dev)), "<div class="++Cat++"><pre><b>" + "\\*\\*\\* User \\d{4}-\\d{2}-\\d{2} " + "\\d{2}:\\d{2}:\\d{2}.\\d{1,} \\*\\*\\*</b>"). + +read_footer(Dev) -> + "</pre></div>\n" = element(2, file:read_line(Dev)), + "<pre>\n" = element(2, file:read_line(Dev)). + +read_nl(Dev) -> + file:read_line(Dev). + + diff --git a/lib/common_test/test/ct_repeat_testrun_SUITE.erl b/lib/common_test/test/ct_repeat_testrun_SUITE.erl index 632597c214..f8b6a379f6 100644 --- a/lib/common_test/test/ct_repeat_testrun_SUITE.erl +++ b/lib/common_test/test/ct_repeat_testrun_SUITE.erl @@ -66,25 +66,47 @@ %% there will be clashes with logging processes etc). %%-------------------------------------------------------------------- init_per_suite(Config0) -> - Config = ct_test_support:init_per_suite(Config0), - DataDir = ?config(data_dir, Config), - Suite1 = filename:join([DataDir,"a_test","r1_SUITE"]), - Suite2 = filename:join([DataDir,"b_test","r2_SUITE"]), - Opts0 = ct_test_support:get_opts(Config), - Opts1 = Opts0 ++ [{suite,Suite1},{testcase,tc2},{label,timing1}], - Opts2 = Opts0 ++ [{suite,Suite2},{testcase,tc2},{label,timing2}], - - %% Make sure both suites are compiled - {1,0,{0,0}} = ct_test_support:run(ct,run_test,[Opts1],Config), - {1,0,{0,0}} = ct_test_support:run(ct,run_test,[Opts2],Config), - - %% Time the shortest testcase to use for offset - {_T0,{1,0,{0,0}}} = timer:tc(ct_test_support,run,[ct,run_test,[Opts1],Config]), - - %% -2 is to ensure we hit inside the target test case and not after -% T = round(T0/1000000)-2, - T=0, - [{offset,T}|Config]. + TTInfo = {_T,{_Scaled,ScaleVal}} = ct:get_timetrap_info(), + ct:pal("Timetrap info = ~w", [TTInfo]), + if ScaleVal > 1 -> + {skip,"Skip on systems running e.g. cover or debug!"}; + ScaleVal =< 1 -> + Config = ct_test_support:init_per_suite(Config0), + DataDir = ?config(data_dir, Config), + Suite1 = filename:join([DataDir,"a_test","r1_SUITE"]), + Suite2 = filename:join([DataDir,"b_test","r2_SUITE"]), + Opts0 = ct_test_support:get_opts(Config), + Opts1 = Opts0 ++ [{suite,Suite1},{testcase,tc2},{label,timing1}], + Opts2 = Opts0 ++ [{suite,Suite2},{testcase,tc2},{label,timing2}], + + %% Make sure both suites are compiled + {1,0,{0,0}} = ct_test_support:run(ct,run_test,[Opts1],Config), + {1,0,{0,0}} = ct_test_support:run(ct,run_test,[Opts2],Config), + + %% Check if file i/o is too slow for correct measurements + Opts3 = Opts0 ++ [{suite,Suite1},{testcase,tc1},{label,timing3}], + {T,_} = + timer:tc( + fun() -> + {1,0,{0,0}} = ct_test_support:run(ct,run_test, + [Opts3],Config), + {1,0,{0,0}} = ct_test_support:run(ct,run_test, + [Opts3],Config) + end), + %% The time to compare with here must match the timeout value + %% in the test suite. Accept 30% logging overhead (26 sec total). + if T > 26000000 -> + ct:pal("Timing test took ~w sec (< 27 sec expected). " + "Skipping the suite!", + [trunc(T/1000000)]), + ct_test_support:end_per_suite(Config), + {skip,"File I/O too slow for this suite"}; + true -> + ct:pal("Timing test took ~w sec. Proceeding...", + [trunc(T/1000000)]), + [{offset,0}|Config] + end + end. end_per_suite(Config) -> ct_test_support:end_per_suite(Config). diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml index 954750fcdd..61e214294e 100644 --- a/lib/compiler/doc/src/compile.xml +++ b/lib/compiler/doc/src/compile.xml @@ -40,6 +40,19 @@ <funcs> <func> + <name>env_compiler_options()</name> + <fsummary> + Compiler options defined via the environment variable + <c>ERL_COMPILER_OPTIONS</c> + </fsummary> + <desc> + <p>Return compiler options given via the environment variable + <c>ERL_COMPILER_OPTIONS</c>. If the value is a list, it is + returned as is. If it is not a list, it is put into a list. + </p> + </desc> + </func> + <func> <name>file(File)</name> <fsummary>Compiles a file.</fsummary> <desc> @@ -768,6 +781,9 @@ module.beam: module.erl \ if you do not want the environment variable to be consulted, for example, if you are calling the compiler recursively from inside a parse transform.</p> + + <p>The list can be retrieved with + <seealso marker="#env_compiler_options/0">env_compiler_options/0</seealso>.</p> </section> <section> diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 149086152a..82ff8a95f3 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -26,6 +26,7 @@ -export([forms/1,forms/2,noenv_forms/2]). -export([output_generated/1,noenv_output_generated/1]). -export([options/0]). +-export([env_compiler_options/0]). %% Erlc interface. -export([compile/3,compile_beam/3,compile_asm/3,compile_core/3]). @@ -131,6 +132,14 @@ noenv_output_generated(Opts) -> end, Passes). %% +%% Retrieve ERL_COMPILER_OPTIONS as a list of terms +%% + +-spec env_compiler_options() -> [term()]. + +env_compiler_options() -> env_default_opts(). + +%% %% Local functions %% diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index a15efc2a00..b0148f7103 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -34,7 +34,7 @@ cover/1, env/1, core/1, core_roundtrip/1, asm/1, sys_pre_attributes/1, dialyzer/1, - warnings/1, pre_load_check/1 + warnings/1, pre_load_check/1, env_compiler_options/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -50,7 +50,8 @@ all() -> other_output, encrypted_abstr, strict_record, cover, env, core, core_roundtrip, asm, - sys_pre_attributes, dialyzer, warnings, pre_load_check]. + sys_pre_attributes, dialyzer, warnings, pre_load_check, + env_compiler_options]. groups() -> []. @@ -1092,6 +1093,23 @@ compiler_modules() -> FN = filename, [list_to_atom(FN:rootname(FN:basename(M), ".beam")) || M <- Ms]. +%% Test that ERL_COMPILER_OPTIONS are correctly retrieved +%% by env_compiler_options/0 + +env_compiler_options(_Config) -> + Cases = [ + {"bin_opt_info", [bin_opt_info]}, + {"'S'", ['S']}, + {"{source, \"test.erl\"}", [{source, "test.erl"}]}, + {"[{d,macro_one,1},{d,macro_two}]", [{d, macro_one, 1}, {d, macro_two}]}, + {"[warn_export_all, warn_export_vars]", [warn_export_all, warn_export_vars]} + ], + F = fun({Env, Expected}) -> + true = os:putenv("ERL_COMPILER_OPTIONS", Env), + Expected = compile:env_compiler_options() + end, + lists:foreach(F, Cases). + %%% %%% Utilities. %%% diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl index 5b1469a10e..e142af4ae0 100644 --- a/lib/debugger/src/dbg_debugged.erl +++ b/lib/debugger/src/dbg_debugged.erl @@ -70,7 +70,10 @@ msg_loop(Meta, Mref, SaveStacktrace) -> %% Meta is evaluating a receive, must be done within context %% of real (=this) process {sys, Meta, {'receive',Msg}} -> - receive Msg -> Meta ! {self(), rec_acked} end, + receive Msg -> + Meta ! {self(), rec_acked}, + ok + end, msg_loop(Meta, Mref, SaveStacktrace); %% Meta needs something evaluated within context of real process diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl index 1b274e20ae..57a3719a50 100644 --- a/lib/debugger/src/dbg_icmd.erl +++ b/lib/debugger/src/dbg_icmd.erl @@ -171,10 +171,10 @@ handle_cmd(Bs, Status, Ieval) -> %% User control of process execution and settings %%==================================================================== -step(Meta) -> Meta ! {user, {cmd, step}}. -next(Meta) -> Meta ! {user, {cmd, next}}. -continue(Meta) -> Meta ! {user, {cmd, continue}}. -finish(Meta) -> Meta ! {user, {cmd, finish}}. +step(Meta) -> Meta ! {user, {cmd, step}}, ok. +next(Meta) -> Meta ! {user, {cmd, next}}, ok. +continue(Meta) -> Meta ! {user, {cmd, continue}}, ok. +finish(Meta) -> Meta ! {user, {cmd, finish}}, ok. skip(Meta) -> Meta ! {user, {cmd, skip}}. timeout(Meta) -> Meta ! {user, timeout}. diff --git a/lib/debugger/src/dbg_iserver.erl b/lib/debugger/src/dbg_iserver.erl index 0ad303d8d9..3561454685 100644 --- a/lib/debugger/src/dbg_iserver.erl +++ b/lib/debugger/src/dbg_iserver.erl @@ -72,17 +72,17 @@ cast(Int, Request) -> gen_server:cast(Int, Request). safe_call(Request) -> - ensure_started(), + {ok, _} = ensure_started(), call(Request). safe_cast(Request) -> - ensure_started(), + {ok, _} = ensure_started(), cast(Request). ensure_started() -> case whereis(?MODULE) of undefined -> start(); - _Pid -> ignore + Pid -> {ok, Pid} end. %%--Module database--------------------------------------------------- @@ -402,8 +402,10 @@ handle_cast({set_status, Meta, Status, Info}, State) -> send_all(subscriber, {new_status, Proc#proc.pid, Status, Info}, State), if Status =:= break -> - auto_attach(break, State#state.auto, Proc); - true -> ignore + _ = auto_attach(break, State#state.auto, Proc), + ok; + true -> + ok end, Proc2 = Proc#proc{status=Status, info=Info}, {noreply, State#state{procs=lists:keyreplace(Meta, #proc.meta, @@ -470,7 +472,7 @@ handle_info({'EXIT',Who,Why}, State) -> [self(),AttPid,Pid,Why,ExitInfo]); undefined -> %% Otherwise, auto attach if necessary - auto_attach(exit, State#state.auto, Pid), + _ = auto_attach(exit, State#state.auto, Pid), Who end, send_all(subscriber, {new_status,Pid,exit,Why}, State), @@ -583,7 +585,8 @@ send_all(Pids, Msg) -> lists:foreach(fun(Pid) -> send(Pid, Msg) end, Pids). send(Pid, Msg) -> - Pid ! {int, Msg}. + Pid ! {int, Msg}, + ok. get_proc({Type, Pid}, Procs) -> Index = case Type of diff --git a/lib/debugger/src/dbg_wx_break_win.erl b/lib/debugger/src/dbg_wx_break_win.erl index cd1e81456f..770681510d 100644 --- a/lib/debugger/src/dbg_wx_break_win.erl +++ b/lib/debugger/src/dbg_wx_break_win.erl @@ -65,18 +65,18 @@ create_win(Parent, Pos, function, Mod, _Line) -> {choices, IntStrs}]), Expand = [{border, 5}, {flag,?wxLEFT bor ?wxRIGHT bor ?wxEXPAND}], - wxSizer:add(MainS, Label, [{border,5}, + _ = wxSizer:add(MainS, Label, [{border,5}, {flag,?wxTOP bor ?wxLEFT bor ?wxRIGHT}]), - wxSizer:add(MainS, Text, Expand), + _ = wxSizer:add(MainS, Text, Expand), FunLabel = wxStaticText:new(Win, ?wxID_ANY, "Function:"), LB = wxListBox:new(Win, ?wxID_ANY, [{size,{-1, 100}},{style,?wxLB_MULTIPLE}]), - wxSizer:add(MainS, FunLabel, Expand), - wxSizer:add(MainS, LB, [{proportion,1}|Expand]), + _ = wxSizer:add(MainS, FunLabel, Expand), + _ = wxSizer:add(MainS, LB, [{proportion,1}|Expand]), wxSizer:setMinSize(MainS, 300, 400), OK = wxDialog:createStdDialogButtonSizer(Win, ?wxOK bor ?wxCANCEL), - wxSizer:add(MainS, OK, [{border,5},{flag,?wxALL}]), + _ = wxSizer:add(MainS, OK, [{border,5},{flag,?wxALL}]), wxDialog:setSizer(Win,MainS), - wxSizer:fit(MainS, Win), + _ = wxSizer:fit(MainS, Win), wxSizer:setSizeHints(MainS,Win), wxComboBox:setFocus(Text), wxDialog:connect(Win, command_button_clicked), @@ -110,11 +110,11 @@ create_win(Parent, Pos, Type, Mod, Line) -> IntStrs = [atom_to_list(M) || M <- Int], ModT = wxComboBox:new(Win, ?wxID_ANY, [{choices,IntStrs}]), ModSz = create_label_of_control(Win, "Module:", ModT, Mod), - wxSizer:add(MainS,ModSz,[{flag, ?wxEXPAND}]), + _ = wxSizer:add(MainS,ModSz,[{flag, ?wxEXPAND}]), %% Create rest of text input fields Add = fun({IType, Label, Def}) -> {Sz, Text} = create_sizer_with_text(Win, Label, Def), - wxSizer:add(MainS, Sz, [{flag, ?wxEXPAND}]), + _ = wxSizer:add(MainS, Sz, [{flag, ?wxEXPAND}]), {Text, IType} end, Inputs = case Type of @@ -129,15 +129,15 @@ create_win(Parent, Pos, Type, Mod, Line) -> Entries = wx:map(Add, Inputs), %% Create and add radio box {TriggerBox,Trigger} = create_trigger_box(Win), - wxSizer:add(MainS, TriggerBox, [{border,5},{flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(MainS, TriggerBox, [{border,5},{flag,?wxALL bor ?wxEXPAND}]), - wxSizer:addStretchSpacer(MainS), + _ = wxSizer:addStretchSpacer(MainS), %% Put it together OK = wxDialog:createStdDialogButtonSizer(Win, ?wxOK bor ?wxCANCEL), - wxSizer:add(MainS, OK, [{border,5},{flag,?wxALL}]), + _ = wxSizer:add(MainS, OK, [{border,5},{flag,?wxALL}]), wxSizer:setMinSize(MainS, 300, -1), wxDialog:setSizer(Win,MainS), - wxSizer:fit(MainS, Win), + _ = wxSizer:fit(MainS, Win), wxSizer:setSizeHints(MainS,Win), wxComboBox:setFocus(ModT), wxDialog:connect(Win, command_button_clicked), @@ -243,8 +243,8 @@ create_label_of_control(Parent, Label, Control, Def) -> Text = wxStaticText:new(Parent, ?wxID_ANY, Label), Border = {border, 5}, Flag = ?wxRIGHT bor ?wxLEFT bor ?wxALIGN_CENTRE_VERTICAL, - wxSizer:add(Sizer, Text, [{proportion,1}, {flag,Flag}, Border]), - wxSizer:add(Sizer, Control, [{proportion,3}, {flag,Flag bor ?wxEXPAND}, Border]), + _ = wxSizer:add(Sizer, Text, [{proportion,1}, {flag,Flag}, Border]), + _ = wxSizer:add(Sizer, Control, [{proportion,3}, {flag,Flag bor ?wxEXPAND}, Border]), wxControl:setLabel(Control, dbg_wx_win:to_string(Def)), Sizer. @@ -252,11 +252,11 @@ create_trigger_box(Win) -> SBox = wxStaticBox:new(Win, ?wxID_ANY, "Trigger Action:"), SBS = wxStaticBoxSizer:new(SBox, ?wxVERTICAL), Ebtn = wxRadioButton:new(Win, ?wxID_ANY, "Enable"), - wxSizer:add(SBS,Ebtn), + _ = wxSizer:add(SBS,Ebtn), Dibtn = wxRadioButton:new(Win, ?wxID_ANY, "Disable"), - wxSizer:add(SBS,Dibtn), + _ = wxSizer:add(SBS,Dibtn), Debtn = wxRadioButton:new(Win, ?wxID_ANY, "Delete"), - wxSizer:add(SBS,Debtn), + _ = wxSizer:add(SBS,Debtn), wxRadioButton:setValue(Ebtn, true), {SBS, [{Ebtn,enable},{Dibtn,disable},{Debtn,delete}]}. diff --git a/lib/debugger/src/dbg_wx_code.erl b/lib/debugger/src/dbg_wx_code.erl index f8fc331a81..473963500a 100644 --- a/lib/debugger/src/dbg_wx_code.erl +++ b/lib/debugger/src/dbg_wx_code.erl @@ -127,20 +127,22 @@ load_code(Ed, Code) -> %%io:format("~p ~p ~p~n", [Lines, Sz, LW]), ?stc:setMarginWidth(Ed, 0, LW+5), ?stc:setReadOnly(Ed, true), - Ed. + ok. unload_code(Ed) -> ?stc:setReadOnly(Ed, false), ?stc:setTextRaw(Ed, <<0:8>>), ?stc:setReadOnly(Ed, true), - Ed. + ok. add_break_to_code(Ed, Line, active) -> ?stc:markerDelete(Ed, Line-1, 1), - ?stc:markerAdd(Ed, Line-1, 0); + ?stc:markerAdd(Ed, Line-1, 0), + ok; add_break_to_code(Ed, Line, inactive) -> ?stc:markerDelete(Ed, Line-1, 0), - ?stc:markerAdd(Ed, Line-1, 1). + ?stc:markerAdd(Ed, Line-1, 1), + ok. del_break_from_code(Ed,Line) -> ?stc:markerDelete(Ed, Line-1, 0), diff --git a/lib/debugger/src/dbg_wx_filedialog_win.erl b/lib/debugger/src/dbg_wx_filedialog_win.erl index 2103536a04..f7b031dc28 100644 --- a/lib/debugger/src/dbg_wx_filedialog_win.erl +++ b/lib/debugger/src/dbg_wx_filedialog_win.erl @@ -118,9 +118,9 @@ init([Parent, Id, Options0]) -> wxTextCtrl:connect(Dir, char, [{callback, IsTab}]), Top = wxBoxSizer:new(?wxHORIZONTAL), - wxSizer:add(Top, Back, [{border, 2},{flag,?wxALL bor ?wxEXPAND}]), - wxSizer:add(Top, Forw, [{border, 2},{flag,?wxALL bor ?wxEXPAND}]), - wxSizer:add(Top, Up, [{border, 2},{flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(Top, Back, [{border, 2},{flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(Top, Forw, [{border, 2},{flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(Top, Up, [{border, 2},{flag,?wxALL bor ?wxEXPAND}]), %% List Ctrl {Art, IconMap} = create_icons(ExtraIcons), @@ -154,13 +154,13 @@ init([Parent, Id, Options0]) -> %% OK done Box = wxBoxSizer:new(?wxVERTICAL), - wxSizer:add(Box, Top, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]), - wxSizer:add(Box, Dir, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]), - wxSizer:add(Box, LC, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}, {proportion, 1}]), - wxSizer:add(Box, Bott, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(Box, Top, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(Box, Dir, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(Box, LC, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}, {proportion, 1}]), + _ = wxSizer:add(Box, Bott, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]), wxWindow:setSizer(Dlg, Box), - wxSizer:fit(Box, Dlg), + _ = wxSizer:fit(Box, Dlg), wxSizer:setSizeHints(Box,Dlg), State = #state{win=Dlg, back=Back, forward=Forw, up=Up, diff --git a/lib/debugger/src/dbg_wx_mon.erl b/lib/debugger/src/dbg_wx_mon.erl index 345367a911..a32a6894b8 100644 --- a/lib/debugger/src/dbg_wx_mon.erl +++ b/lib/debugger/src/dbg_wx_mon.erl @@ -135,7 +135,7 @@ init2(CallingPid, Mode, SFile, GS) -> %% Start other necessary stuff dbg_wx_win:init(), - dbg_wx_winman:start(), % Debugger window manager + _ = dbg_wx_winman:start(), % Debugger window manager %% Create monitor window Title = "Monitor", @@ -339,7 +339,7 @@ gui_cmd('Delete All Modules', State) -> lists:foreach(fun(Mod) -> int:nn(Mod) end, int:interpreted()), State; gui_cmd({module, Mod, What}, State) -> - case What of + _ = case What of delete -> int:nn(Mod); view -> Window = dbg_wx_mon_win:get_window(State#state.win), diff --git a/lib/debugger/src/dbg_wx_mon_win.erl b/lib/debugger/src/dbg_wx_mon_win.erl index 2e48210f55..9737c9e67f 100644 --- a/lib/debugger/src/dbg_wx_mon_win.erl +++ b/lib/debugger/src/dbg_wx_mon_win.erl @@ -107,31 +107,31 @@ create_win_batch(Title, Menus) -> Hlb = 200, Listbox = wxListBox:new(Panel, ?wxID_ANY, [{size,{?Wf,Hlb}}, {style,?wxLB_SINGLE}]), - wxSizer:add(LeftSz,Listbox,[{proportion,1},{border,3},{flag,?wxEXPAND}]), + _ = wxSizer:add(LeftSz,Listbox,[{proportion,1},{border,3},{flag,?wxEXPAND}]), wxListBox:connect(Listbox, command_listbox_doubleclicked), wxListBox:connect(Listbox, right_down), SBox = wxStaticBox:new(Panel, ?wxID_ANY, "Auto Attach:"), SBS = wxStaticBoxSizer:new(SBox, ?wxVERTICAL), Fbtn = wxCheckBox:new(Panel, ?autoId, "First Call"), - wxSizer:add(SBS,Fbtn), + _ = wxSizer:add(SBS,Fbtn), Bbtn = wxCheckBox:new(Panel, ?autoId, "On Break"), - wxSizer:add(SBS,Bbtn), + _ = wxSizer:add(SBS,Bbtn), Ebtn = wxCheckBox:new(Panel, ?autoId, "On Exit"), - wxSizer:add(SBS,Ebtn), + _ = wxSizer:add(SBS,Ebtn), wxFrame:connect(Panel, command_checkbox_clicked), - wxSizer:add(LeftSz,SBS, [{flag,?wxEXPAND}]), + _ = wxSizer:add(LeftSz,SBS, [{flag,?wxEXPAND}]), SLabel = wxStaticText:new(Panel, ?wxID_ANY, "Stack Trace:\n On (with tail)"), - wxSizer:add(LeftSz,SLabel), + _ = wxSizer:add(LeftSz,SLabel), BLabel = wxStaticText:new(Panel, ?wxID_ANY, "Back Trace Size:\n 50000"), - wxSizer:add(LeftSz,BLabel), + _ = wxSizer:add(LeftSz,BLabel), StringsBox = wxStaticBox:new(Panel, ?wxID_ANY, "Strings:"), StringsBS = wxStaticBoxSizer:new(StringsBox, ?wxVERTICAL), Stringsbtn = wxCheckBox:new(Panel, ?stringsId, ?STRTEXT), - wxSizer:add(StringsBS,Stringsbtn), - wxSizer:add(LeftSz,StringsBS, [{flag,?wxEXPAND}]), + _ = wxSizer:add(StringsBS,Stringsbtn), + _ = wxSizer:add(LeftSz,StringsBS, [{flag,?wxEXPAND}]), %% Create list_crtl / grid Grid = wxListCtrl:new(Panel, [{winid, ?GRID}, @@ -169,12 +169,12 @@ create_win_batch(Title, Menus) -> wxWindow:setFocus(Grid), %% Put it in the window - wxSizer:add(MainSz, LeftSz, [{border, 3}, {flag,?wxALL bor ?wxEXPAND}]), - wxSizer:add(MainSz, Grid, [{border, 3}, {flag,?wxALL bor ?wxEXPAND}, + _ = wxSizer:add(MainSz, LeftSz, [{border, 3}, {flag,?wxALL bor ?wxEXPAND}]), + _ = wxSizer:add(MainSz, Grid, [{border, 3}, {flag,?wxALL bor ?wxEXPAND}, {proportion, 1}]), wxWindow:setSizer(Panel,MainSz), - wxSizer:fit(MainSz, Win), + _ = wxSizer:fit(MainSz, Win), wxSizer:setSizeHints(MainSz,Win), IconFile = dbg_wx_win:find_icon("erlang_bug.png"), diff --git a/lib/debugger/src/dbg_wx_src_view.erl b/lib/debugger/src/dbg_wx_src_view.erl index 571c6b01bb..207c407fbc 100644 --- a/lib/debugger/src/dbg_wx_src_view.erl +++ b/lib/debugger/src/dbg_wx_src_view.erl @@ -56,7 +56,7 @@ code_area(Parent, Sizer) -> end, [SetStyle(Style) || Style <- Styles], ?stc:setKeyWords(Ed, 0, keyWords()), - wxSizer:add(Sizer, Ed, [{proportion,1}, {flag, ?wxEXPAND}]), + _ = wxSizer:add(Sizer, Ed, [{proportion,1}, {flag, ?wxEXPAND}]), Ed. diff --git a/lib/debugger/src/dbg_wx_trace.erl b/lib/debugger/src/dbg_wx_trace.erl index f9c60f9b72..6af19af33b 100644 --- a/lib/debugger/src/dbg_wx_trace.erl +++ b/lib/debugger/src/dbg_wx_trace.erl @@ -321,7 +321,7 @@ gui_cmd('Kill', State) -> exit(State#state.pid, kill), State; gui_cmd('Messages', State) -> - case int:meta(State#state.meta, messages) of + _ = case int:meta(State#state.meta, messages) of [] -> dbg_wx_trace_win:eval_output(State#state.win,"< No Messages!\n", bold); Messages -> diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl index 51687ad4e9..972a917728 100644 --- a/lib/debugger/src/dbg_wx_trace_win.erl +++ b/lib/debugger/src/dbg_wx_trace_win.erl @@ -123,7 +123,8 @@ %% GS = term() %%-------------------------------------------------------------------- init() -> - dbg_wx_win:init(). + _ = dbg_wx_win:init(), + ok. stop(#winInfo{window=Win}) -> (catch wxFrame:destroy(Win)), @@ -149,29 +150,29 @@ create_win(Parent, Title, Windows, Menus) -> Sizer = wxBoxSizer:new(?wxVERTICAL), Code = code_area(Panel), - wxSizer:add(Sizer, Code#sub.win, + _ = wxSizer:add(Sizer, Code#sub.win, [{proportion,1}, {border, 2}, {flag, ?wxEXPAND bor ?wxDOWN}]), wxSizer:setVirtualSizeHints(Sizer, Code#sub.win), ExpandWithBorder = [{border, 3},{flag,?wxEXPAND bor ?wxALL}], Search = search_area(Panel), - wxSizer:add(Sizer, Search#sub.win, ExpandWithBorder), + _ = wxSizer:add(Sizer, Search#sub.win, ExpandWithBorder), Bs = button_area(Panel), - wxSizer:add(Sizer, Bs#sub.win, ExpandWithBorder), + _ = wxSizer:add(Sizer, Bs#sub.win, ExpandWithBorder), InfoArea = wxBoxSizer:new(?wxHORIZONTAL), wxSizer:setMinSize(InfoArea, {100, ?EVAL_H}), Eval = eval_area(Panel), - wxSizer:add(InfoArea, Eval#sub.win, [{proportion,1},{flag,?wxEXPAND}]), + _ = wxSizer:add(InfoArea, Eval#sub.win, [{proportion,1},{flag,?wxEXPAND}]), Bind = bind_area(Panel), - wxSizer:add(InfoArea, Bind#sub.win, + _ = wxSizer:add(InfoArea, Bind#sub.win, [{proportion,1},{border, 2}, {flag,?wxEXPAND bor ?wxLEFT}]), - wxSizer:add(Sizer, InfoArea, ExpandWithBorder), + _ = wxSizer:add(Sizer, InfoArea, ExpandWithBorder), Trace = trace_area(Panel), - wxSizer:add(Sizer, Trace#sub.win, ExpandWithBorder), + _ = wxSizer:add(Sizer, Trace#sub.win, ExpandWithBorder), SB = wxFrame:createStatusBar(Win,[]), %% Note id and lastId to get the event when it dragged is complete @@ -192,7 +193,7 @@ create_win(Parent, Title, Windows, Menus) -> Wi = show_windows(enable_windows(Wi0,Windows)), wxWindow:setSizer(Panel, Sizer), - wxSizer:fit(Sizer, Win), + _ = wxSizer:fit(Sizer, Win), wxSizer:setSizeHints(Sizer,Win), IconFile = dbg_wx_win:find_icon("erlang_bug.png"), @@ -230,11 +231,11 @@ get_window(WinInfo) -> %%-------------------------------------------------------------------- configure(Wi=#winInfo{window=Win,m_szr={Panel,Sizer}}) -> wx:batch(fun() -> - show_windows(Wi), + _ = show_windows(Wi), wxSizer:layout(Sizer), %%wxWindow:setSizerAndFit(Panel,Sizer), wxWindow:setSizer(Panel, Sizer), - wxSizer:fit(Sizer, Win), + _ = wxSizer:fit(Sizer, Win), wxSizer:setSizeHints(Sizer,Win), Wi end). @@ -242,10 +243,10 @@ configure(Wi=#winInfo{window=Win,m_szr={Panel,Sizer}}) -> configure(Wi0=#winInfo{window=Win,m_szr={Panel,Sizer}}, Windows) -> wx:batch(fun() -> Wi = enable_windows(Wi0, Windows), - show_windows(Wi), + _ = show_windows(Wi), wxSizer:layout(Sizer), wxWindow:setSizer(Panel, Sizer), - wxSizer:fit(Sizer, Win), + _ = wxSizer:fit(Sizer, Win), wxSizer:setSizeHints(Sizer,Win), Wi end). @@ -348,7 +349,7 @@ add_break(WinInfo, Menu, {{Mod,Line},[Status|_Options]}=Break) -> case WinInfo#winInfo.editor of {Mod, Editor} -> dbg_wx_code:add_break_to_code(Editor, Line, Status); - _ -> ignore + _ -> ok end, add_break_to_menu(WinInfo, Menu, Break). @@ -372,7 +373,7 @@ update_break(WinInfo, {{Mod,Line},[Status|_Options]}=Break) -> case WinInfo#winInfo.editor of {Mod, Editor} -> dbg_wx_code:add_break_to_code(Editor, Line, Status); - _ -> ignore + _ -> ok end, update_break_in_menu(WinInfo, Break). @@ -929,7 +930,7 @@ button_area(Parent) -> B=wxButton:new(Parent, Button, [{label,dbg_wx_win:to_string(Name)}]), Id = wxWindow:getId(B), - wxSizer:add(Sz,B, []), + _ = wxSizer:add(Sz,B, []), wxButton:connect(B, command_button_clicked, [{id,Id}]) end, buttons()), #sub{name='Button Area', win=Sz}. @@ -938,22 +939,22 @@ button_area(Parent) -> search_area(Parent) -> HSz = wxBoxSizer:new(?wxHORIZONTAL), - wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Find:"), + _ = wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Find:"), [{flag,?wxALIGN_CENTER_VERTICAL}]), TC1 = wxTextCtrl:new(Parent, ?SEARCH_ENTRY, [{style, ?wxTE_PROCESS_ENTER}]), - wxSizer:add(HSz, TC1, [{proportion,3}, {flag, ?wxEXPAND}]), + _ = wxSizer:add(HSz, TC1, [{proportion,3}, {flag, ?wxEXPAND}]), Nbtn = wxRadioButton:new(Parent, ?wxID_ANY, "Next"), wxRadioButton:setValue(Nbtn, true), - wxSizer:add(HSz,Nbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]), + _ = wxSizer:add(HSz,Nbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]), Pbtn = wxRadioButton:new(Parent, ?wxID_ANY, "Previous"), - wxSizer:add(HSz,Pbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]), + _ = wxSizer:add(HSz,Pbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]), Cbtn = wxCheckBox:new(Parent, ?wxID_ANY, "Match Case"), - wxSizer:add(HSz,Cbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]), - wxSizer:add(HSz, 15,15, [{proportion,1}, {flag, ?wxEXPAND}]), - wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Goto Line:"), + _ = wxSizer:add(HSz,Cbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]), + _ = wxSizer:add(HSz, 15,15, [{proportion,1}, {flag, ?wxEXPAND}]), + _ = wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Goto Line:"), [{flag,?wxALIGN_CENTER_VERTICAL}]), TC2 = wxTextCtrl:new(Parent, ?GOTO_ENTRY, [{style, ?wxTE_PROCESS_ENTER}]), - wxSizer:add(HSz, TC2, [{proportion,0}, {flag, ?wxEXPAND}]), + _ = wxSizer:add(HSz, TC2, [{proportion,0}, {flag, ?wxEXPAND}]), wxTextCtrl:connect(TC1, command_text_updated), wxTextCtrl:connect(TC1, command_text_enter), wxTextCtrl:connect(TC1, kill_focus), @@ -969,14 +970,14 @@ eval_area(Parent) -> VSz = wxBoxSizer:new(?wxVERTICAL), HSz = wxBoxSizer:new(?wxHORIZONTAL), - wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Evaluator:"), + _ = wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Evaluator:"), [{flag,?wxALIGN_CENTER_VERTICAL}]), TC = wxTextCtrl:new(Parent, ?EVAL_ENTRY, [{style, ?wxTE_PROCESS_ENTER}]), - wxSizer:add(HSz, TC, [{proportion,1}, {flag, ?wxEXPAND}]), - wxSizer:add(VSz, HSz, [{flag, ?wxEXPAND}]), + _ = wxSizer:add(HSz, TC, [{proportion,1}, {flag, ?wxEXPAND}]), + _ = wxSizer:add(VSz, HSz, [{flag, ?wxEXPAND}]), TL = wxTextCtrl:new(Parent, ?EVAL_LOG, [{style, ?wxTE_DONTWRAP bor ?wxTE_MULTILINE bor ?wxTE_READONLY}]), - wxSizer:add(VSz, TL, [{proportion,5}, {flag, ?wxEXPAND}]), + _ = wxSizer:add(VSz, TL, [{proportion,5}, {flag, ?wxEXPAND}]), wxTextCtrl:connect(TC, command_text_enter), #sub{name='Evaluator Area', win=VSz, in=TC, out=TL}. diff --git a/lib/debugger/src/dbg_wx_win.erl b/lib/debugger/src/dbg_wx_win.erl index 1ff8818bbe..25ffc5054c 100644 --- a/lib/debugger/src/dbg_wx_win.erl +++ b/lib/debugger/src/dbg_wx_win.erl @@ -43,7 +43,8 @@ %% GS = term() %%-------------------------------------------------------------------- init() -> - wx:new(). + _ = wx:new(), + ok. %%-------------------------------------------------------------------- %% create_menus(MenuBar, [Menu]) @@ -80,12 +81,12 @@ create_menus(_MB,[], _Win,Id) -> Id. create_menu_item(Menu, [separator|Is], Win, Id,Connect) -> - wxMenu:appendSeparator(Menu), + _ = wxMenu:appendSeparator(Menu), create_menu_item(Menu,Is,Win,Id+1,Connect); create_menu_item(Menu, [{Name, _N, cascade, Items}|Is], Win, Id0,Connect) -> Sub = wxMenu:new([]), Id = create_menu_item(Sub, Items, Win, Id0, false), - wxMenu:append(Menu, ?wxID_ANY, menu_name(Name,ignore), Sub), + _ = wxMenu:append(Menu, ?wxID_ANY, menu_name(Name,ignore), Sub), %% Simulate GS sub checkBox/RadioBox behaviour Self = self(), Butts = [{MI,get(MI)} || {MI,_,_} <- Items], @@ -99,8 +100,8 @@ create_menu_item(Menu, [{Name, _N, cascade, Items}|Is], Win, Id0,Connect) -> Enabled = lists:foldl(IsChecked, [], Butts), Self ! Ev#wx{userData={Name, Enabled}} end, - wxMenu:connect(Win, command_menu_selected, - [{id,Id0},{lastId, Id-1},{callback,Filter}]), + _ = wxMenu:connect(Win, command_menu_selected, + [{id,Id0},{lastId, Id-1},{callback,Filter}]), create_menu_item(Menu, Is, Win, Id, Connect); create_menu_item(Menu, [{Name,Pos}|Is], Win, Id, Connect) -> MenuId = case lists:member(Name, ['Debugger']) of @@ -168,7 +169,7 @@ add_break(Win, MenuName, Point) -> Delete = wxMenu:appendRadioItem(Trigger, ?wxID_ANY,"Delete"), Add(Delete, {break,Point,{trigger,delete}}), - wxMenu:append(Sub, ?wxID_ANY, "Trigger Action", Trigger), + _ = wxMenu:append(Sub, ?wxID_ANY, "Trigger Action", Trigger), MenuBtn = wxMenu:append(Menu,?wxID_ANY, Label, Sub), #break{mb={Menu,MenuBtn}, diff --git a/lib/debugger/src/dbg_wx_winman.erl b/lib/debugger/src/dbg_wx_winman.erl index efa58ae325..ca858fa4bb 100644 --- a/lib/debugger/src/dbg_wx_winman.erl +++ b/lib/debugger/src/dbg_wx_winman.erl @@ -100,11 +100,11 @@ update_windows_menu(Win, [MonInfo|Infos]) -> OldItems = wxMenu:getMenuItems(Menu), [wxMenu:delete(Menu, Item) || Item <- OldItems], menuitem(Win, Menu,MonInfo, 700), - wxMenu:appendSeparator(Menu), + _ = wxMenu:appendSeparator(Menu), wx:foldl(fun(Info,Acc) -> menuitem(Win,Menu,Info,Acc) end, 701, Infos). menuitem(Window, Menu, {Title, Win}, Id) -> - wxMenu:append(Menu, Id, Title), + _ = wxMenu:append(Menu, Id, Title), wxWindow:connect(Window, command_menu_selected, [{id,Id},{userData,{dbg_ui_winman,Win}}]), Id+1. diff --git a/lib/debugger/src/i.erl b/lib/debugger/src/i.erl index 4ed5265bdf..2da3e77618 100644 --- a/lib/debugger/src/i.erl +++ b/lib/debugger/src/i.erl @@ -108,7 +108,7 @@ ib(Module,Function,Arity) -> ib(Module,Function,Arity,Cond) -> Breaks1 = int:all_breaks(Module), - int:break_in(Module,Function,Arity), + ok = int:break_in(Module,Function,Arity), Breaks2 = int:all_breaks(Module), lists:foreach(fun({Mod,Line}) -> int:test_at_break(Mod,Line,Cond) end, Breaks2--Breaks1). diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl index 3906c22afd..e5bade9abe 100644 --- a/lib/debugger/src/int.erl +++ b/lib/debugger/src/int.erl @@ -352,10 +352,10 @@ start() -> dbg_iserver:start(). stop() -> lists:foreach( fun(Mod) -> - everywhere(distributed, - fun() -> + _ = everywhere(distributed, + fun() -> erts_debug:breakpoint({Mod,'_','_'}, false) - end) + end) end, interpreted()), dbg_iserver:stop(). @@ -524,21 +524,21 @@ check(Mod) when is_atom(Mod) -> catch check_module(Mod); check(File) when is_list(File) -> catch check_file(File). load({Mod, Src, Beam, BeamBin, Exp, Abst}, Dist) -> - everywhere(Dist, - fun() -> + _ = everywhere(Dist, + fun() -> code:purge(Mod), erts_debug:breakpoint({Mod,'_','_'}, false), {module,Mod} = code:load_binary(Mod, Beam, BeamBin) - end), + end), case erl_prim_loader:get_file(filename:absname(Src)) of {ok, SrcBin, _} -> MD5 = code:module_md5(BeamBin), Bin = term_to_binary({interpreter_module,Exp,Abst,SrcBin,MD5}), {module, Mod} = dbg_iserver:safe_call({load, Mod, Src, Bin}), - everywhere(Dist, - fun() -> + _ = everywhere(Dist, + fun() -> true = erts_debug:breakpoint({Mod,'_','_'}, true) > 0 - end), + end), {module, Mod}; error -> error @@ -738,9 +738,9 @@ del_mod(AbsMod, Dist) -> list_to_atom(filename:basename(AbsMod,".erl")) end, dbg_iserver:safe_cast({delete, Mod}), - everywhere(Dist, - fun() -> + _ = everywhere(Dist, + fun() -> erts_debug:breakpoint({Mod,'_','_'}, false), erlang:yield() - end), + end), ok. diff --git a/lib/erl_interface/src/misc/ei_portio.h b/lib/erl_interface/src/misc/ei_portio.h index a14fdbd7d1..fbb61b0ccf 100644 --- a/lib/erl_interface/src/misc/ei_portio.h +++ b/lib/erl_interface/src/misc/ei_portio.h @@ -21,6 +21,12 @@ */ #ifndef _EI_PORTIO_H #define _EI_PORTIO_H +#if !defined(__WIN32__) || !defined(VXWORKS) +#ifdef HAVE_WRITEV +/* Declaration of struct iovec *iov should be visible in this scope. */ +#include <sys/uio.h> +#endif +#endif int ei_accept_t(int fd, void *addr, void *addrlen, unsigned ms); int ei_connect_t(int fd, void *sinp, int sin_siz, unsigned ms); @@ -29,8 +35,7 @@ int ei_write_fill(int fd, const char *buf, int len); int ei_read_fill_t(int fd, char* buf, int len, unsigned ms); int ei_write_fill_t(int fd, const char *buf, int len, unsigned ms); #ifdef HAVE_WRITEV -int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, - unsigned ms); +int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned ms); #endif #endif /* _EI_PORTIO_H */ diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index de52e2a995..9268dac180 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -1491,6 +1491,9 @@ get_portinfo(Fd,Port) -> "Port controls linked-in driver" -> Str = lists:flatten(["Linked in driver: " | val(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); + "Port controls forker process" -> + Str = lists:flatten(["Forker process: " | val(Fd)]), + get_portinfo(Fd,Port#port{controls=Str}); "Port controls external process" -> Str = lists:flatten(["External proc: " | val(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl index fe2aa11450..620979dcc9 100644 --- a/lib/observer/src/observer_procinfo.erl +++ b/lib/observer/src/observer_procinfo.erl @@ -317,7 +317,7 @@ fetch_state_info2(Pid, M) -> of {status, _, {module, _}, [_PDict, _SysState, _Parent, _Dbg, - [Header,{data, First},{data, Second}]]} -> + [Header,{data, First},{data, Second}|_]]} -> [{"Behaviour", B}, Header] ++ First ++ Second; {status, _, {module, _}, [_PDict, _SysState, _Parent, _Dbg, diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl index 4dcaec03a7..8134e02221 100644 --- a/lib/sasl/test/release_handler_SUITE.erl +++ b/lib/sasl/test/release_handler_SUITE.erl @@ -1366,7 +1366,7 @@ upgrade_supervisor(Conf) when is_list(Conf) -> ASupBeam2 = rpc:call(Node, code, which, [a_sup]), %% Check that the restart strategy and child spec is updated - {status, _, {module, _}, [_, _, _, _, [_,_,{data,[{"State",State}]}]]} = + {status, _, {module, _}, [_, _, _, _, [_,_,{data,[{"State",State}]}|_]]} = rpc:call(Node,sys,get_status,[a_sup]), {state,_,RestartStrategy,[Child],_,_,_,_,_,_,_} = State, one_for_all = RestartStrategy, % changed from one_for_one diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index a594c66fa7..c81e72689c 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -30,7 +30,7 @@ %% Internal exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + terminate/2, code_change/3, format_status/2]). -export([try_again_restart/2]). %% For release_handler only @@ -264,8 +264,13 @@ cast(Supervisor, Req) -> get_callback_module(Pid) -> {status, _Pid, {module, _Mod}, [_PDict, _SysState, _Parent, _Dbg, Misc]} = sys:get_status(Pid), - [_Header, _Data, {data, [{"State", State}]}] = Misc, - State#state.module. + case lists:keyfind(supervisor, 1, Misc) of + {supervisor, [{"Callback", Mod}]} -> + Mod; + _ -> + [_Header, _Data, {data, [{"State", State}]} | _] = Misc, + State#state.module + end. %%% --------------------------------------------------- %%% @@ -1450,3 +1455,9 @@ report_progress(Child, SupName) -> Progress = [{supervisor, SupName}, {started, extract_child(Child)}], error_logger:info_report(progress, Progress). + +format_status(terminate, [_PDict, State]) -> + State; +format_status(_, [_PDict, State]) -> + [{data, [{"State", State}]}, + {supervisor, [{"Callback", State#state.module}]}]. diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl index 54f452825f..3d4ae1a189 100644 --- a/lib/stdlib/test/id_transform_SUITE.erl +++ b/lib/stdlib/test/id_transform_SUITE.erl @@ -61,13 +61,8 @@ id_transform(Config) when is_list(Config) -> "erl_id_trans.erl"]), {ok,erl_id_trans,Bin} = compile:file(File,[binary]), {module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin), - case test_server:purify_is_running() of - false -> - ct:timetrap({hours,1}), - run_in_test_suite(); - true -> - {skip,"Valgrind (too slow)"} - end. + ct:timetrap({hours,1}), + run_in_test_suite(). run_in_test_suite() -> SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))), diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index 3f1aa0e7a3..cd2c6b0cbb 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -66,7 +66,7 @@ %% Misc tests -export([child_unlink/1, tree/1, count_children/1, - count_restarting_children/1, + count_restarting_children/1, get_callback_module/1, do_not_save_start_parameters_for_temporary_children/1, do_not_save_child_specs_for_temporary_children/1, simple_one_for_one_scale_many_temporary_children/1, @@ -91,7 +91,7 @@ all() -> {group, normal_termination}, {group, shutdown_termination}, {group, abnormal_termination}, child_unlink, tree, - count_children, count_restarting_children, + count_children, count_restarting_children, get_callback_module, do_not_save_start_parameters_for_temporary_children, do_not_save_child_specs_for_temporary_children, simple_one_for_one_scale_many_temporary_children, temporary_bystander, @@ -1507,6 +1507,14 @@ count_restarting_children(Config) when is_list(Config) -> [1,0,0,0] = get_child_counts(SupPid). %%------------------------------------------------------------------------- +%% Test get_callback_module +get_callback_module(Config) when is_list(Config) -> + Child = {child, {supervisor_1, start_child, []}, temporary, 1000, + worker, []}, + {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), + supervisor_SUITE = supervisor:get_callback_module(SupPid). + +%%------------------------------------------------------------------------- %% Temporary children shall not be restarted so they should not save %% start parameters, as it potentially can take up a huge amount of %% memory for no purpose. |