diff options
Diffstat (limited to 'lib/wx/test')
-rw-r--r-- | lib/wx/test/wx_app_SUITE.erl | 9 | ||||
-rw-r--r-- | lib/wx/test/wx_basic_SUITE.erl | 51 | ||||
-rw-r--r-- | lib/wx/test/wx_class_SUITE.erl | 19 | ||||
-rw-r--r-- | lib/wx/test/wx_event_SUITE.erl | 172 | ||||
-rw-r--r-- | lib/wx/test/wx_obj_test.erl | 72 | ||||
-rw-r--r-- | lib/wx/test/wx_test_lib.erl | 20 | ||||
-rw-r--r-- | lib/wx/test/wx_xtra_SUITE.erl | 16 |
7 files changed, 284 insertions, 75 deletions
diff --git a/lib/wx/test/wx_app_SUITE.erl b/lib/wx/test/wx_app_SUITE.erl index 162923eaa3..6331180ece 100644 --- a/lib/wx/test/wx_app_SUITE.erl +++ b/lib/wx/test/wx_app_SUITE.erl @@ -26,6 +26,7 @@ -compile(export_all). -include("wx_test_lib.hrl"). +-include_lib("common_test/include/ct.hrl"). t() -> wx_test_lib:t(?MODULE). @@ -50,7 +51,7 @@ end_per_testcase(Func,Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [fields, modules, exportall, app_depend, undef_funcs]. + [fields, modules, exportall, app_depend, undef_funcs, appup]. groups() -> []. @@ -281,3 +282,9 @@ key1search(Key, L) -> {value, {Key, Value}} -> Value end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Test that the wx appup file is ok +appup(Config) when is_list(Config) -> + ok = ?t:appup_test(wx). diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl index d55a037599..7bdbd4594c 100644 --- a/lib/wx/test/wx_basic_SUITE.erl +++ b/lib/wx/test/wx_basic_SUITE.erl @@ -1,8 +1,7 @@ -%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -99,8 +98,23 @@ several_apps(Config) -> Pids = [spawn_link(fun() -> several_apps(Parent, N, Config) end) || N <- lists:seq(1,4)], process_flag(trap_exit,true), - ?m_multi_receive([{complete,Pid} || Pid <- Pids]), + Wait = fun(Pid,Acc) -> + receive {complete, Pid} -> Acc + after 20000 -> [Pid|Acc] + end + end, + Res = lists:foldl(Wait, [], Pids), [Pid ! quit || Pid <- Pids], + + Dbg = fun(Pid) -> + io:format("Stack ~p~n",[erlang:process_info(Pid, current_stacktrace)]), + io:format("Stack ~p~n",[erlang:process_info(Pid)]) + end, + case Res of + [] -> ok; + Failed -> + [Dbg(Pid)|| Pid <- Failed] + end, case wx_test_lib:user_available(Config) of true -> receive {'EXIT',_,foo} -> ok end; @@ -217,7 +231,7 @@ create_menus(Frame) -> %% Test the wx_misc.erl api functionality. wx_misc(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); -wx_misc(Config) -> +wx_misc(_Config) -> wx:new([{debug, trace}]), put(wx_test_verbose, true), ?m(ok, wx_misc:bell()), @@ -242,21 +256,6 @@ wx_misc(Config) -> %% wx:shutdown() %% How do you test this? - case os:type() of - {win32, _} -> %% These hangs when running automatic tests - skip; %% through ssh on windows. Works otherwise - _ -> - wx_misc:shell([{command,"echo TESTING close the popup shell"}]) - end, - - case wx_test_lib:user_available(Config) of - true -> - wx_misc:shell(); - false -> - %% Don't want to spawn a shell if no user - skip %% is available - end, - ?m(false, wx_misc:isBusy()), ?m(ok, wx_misc:beginBusyCursor([])), ?m(true, wx_misc:isBusy()), @@ -324,7 +323,18 @@ data_types(_Config) -> wx_object(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); wx_object(Config) -> wx:new(), - Frame = ?mt(wxFrame, wx_obj_test:start([])), + Me = self(), + Init = fun() -> + Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Test wx_object", [{size, {500, 400}}]), + Sz = wxBoxSizer:new(?wxHORIZONTAL), + Panel = wxPanel:new(Frame), + wxSizer:add(Sz, Panel, [{flag, ?wxEXPAND}, {proportion, 1}]), + wxPanel:connect(Panel, size, [{skip, true}]), + wxPanel:connect(Panel, paint, [callback, {userData, Me}]), + wxWindow:show(Frame), + {Frame, {Frame, Panel}} + end, + Frame = ?mt(wxFrame, wx_obj_test:start([{init, Init}])), timer:sleep(500), ?m(ok, check_events(flush())), @@ -346,6 +356,7 @@ wx_object(Config) -> %% Which it did in my buggy handling of the sync_callback wxWindow:refresh(Frame), ?m([{sync_event, #wx{event=#wxPaint{}}, _}], flush()), + timer:sleep(500), ?m([{cast, slept}], flush()), Monitor = erlang:monitor(process, FramePid), diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index 7c3eda0be1..0e151ccc9b 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -50,7 +50,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [calendarCtrl, treeCtrl, notebook, staticBoxSizer, clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual, - radioBox, systemSettings, taskBarIcon]. + radioBox, systemSettings, taskBarIcon, toolbar]. groups() -> []. @@ -493,3 +493,20 @@ taskBarIcon(Config) -> wxTaskBarIcon:connect(TBI, taskbar_left_down, [{callback, fun(Ev,_) -> io:format("Left clicked: ~p~n",[Ev]) end}]), wxTaskBarIcon:connect(TBI, taskbar_right_down, [{callback,fun(Ev,_) -> io:format("Right clicked: ~p~n",[Ev]) end}]), wx_test_lib:wx_destroy(Frame,Config). + +toolbar(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); +toolbar(Config) -> + Wx = wx:new(), + Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"), + TB = wxFrame:createToolBar(Frame), + wxToolBar:addTool(TB, 747, "PressMe", wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}]), + [{shortHelp, "Press Me"}]), + + Add = fun(#wx{}, _) -> + wxToolBar:addTool(TB, -1, "Added", wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}]), + [{shortHelp, "Test 2 popup text"}]) + end, + + wxFrame:connect(Frame, command_menu_selected, [{callback, Add}, {id, 747}]), + wxFrame:show(Frame), + wx_test_lib:wx_destroy(Frame,Config). diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl index 53a2ee7d7b..076f16ba16 100644 --- a/lib/wx/test/wx_event_SUITE.erl +++ b/lib/wx/test/wx_event_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. 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 @@ -47,7 +47,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [connect, disconnect, connect_msg_20, connect_cb_20, - mouse_on_grid, spin_event, connect_in_callback, recursive]. + mouse_on_grid, spin_event, connect_in_callback, recursive, + dialog, char_events, callback_clean + ]. groups() -> []. @@ -147,7 +149,7 @@ disconnect(Config) -> timer:sleep(1000), wx_test_lib:flush(), - ?m({'EXIT', {{badarg,_},_}}, wxEvtHandler:disconnect(Panel, non_existing_event_type)), + ?m(false, wxEvtHandler:disconnect(Panel, non_existing_event_type)), ?m(true, wxEvtHandler:disconnect(Panel, size)), ?m(ok, wxWindow:setSize(Panel, {200,102})), timer:sleep(1000), @@ -398,3 +400,167 @@ recursive(Config) -> wx_test_lib:flush(), wx_test_lib:wx_destroy(Frame, Config). + + +dialog(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); +dialog(Config) -> + Wx = wx:new(), + Frame = wxFrame:new(Wx, ?wxID_ANY, "Testing"), + wxFrame:show(Frame), + Env = wx:get_env(), + Tester = self(), + PD = wxProgressDialog:new("Dialog","Testing", + [%%{parent, Frame}, + {maximum,101}, + {style, ?wxPD_SMOOTH bor ?wxPD_AUTO_HIDE}]), + Forward = fun(#wx{event=#wxInitDialog{}}, Ev) -> + ?mt(wxInitDialogEvent, Ev), + io:format("Heyhoo~n", []), + wxEvent:skip(Ev), + Tester ! {progress_dialog,PD} + end, + wxDialog:connect(PD, init_dialog, [{callback, Forward}]), + Recurse = fun(Recurse, N) -> + true = wxProgressDialog:update(PD, min(N,100)), + timer:sleep(5), + Recurse(Recurse,N+1) + end, + Run = fun() -> + wx:set_env(Env), + Recurse(Recurse, 0) + end, + Worker = spawn_link(Run), + timer:sleep(500), + io:format("Got ~p~n", [wx_test_lib:flush()]), + unlink(Worker), + wxProgressDialog:destroy(PD), + wx_test_lib:wx_destroy(Frame, Config). + + + +char_events(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); +char_events(Config) -> + Wx = wx:new(), + Frame = wxFrame:new(Wx, ?wxID_ANY, "Press any key"), + Panel = wxPanel:new(Frame, []), + wxFrame:connect(Frame, enter_window, [{callback, fun(_,_) -> + io:format("Set focus~n"), + wxWindow:setFocus(Panel) + end}]), + KeyEvent = fun(Ev,Obj) -> io:format("Got ~p~n",[Ev]), wxEvent:skip(Obj) end, + [wxWindow:connect(Panel, Types, [{callback,KeyEvent}]) + || Types <- [key_down, key_up, char]], + wxWindow:connect(Frame, char_hook, [{callback,KeyEvent}]), + + wxFrame:show(Frame), + wx_test_lib:flush(), + + wx_test_lib:wx_destroy(Frame, Config). + +callback_clean(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); +callback_clean(Config) -> + %% Be sure that event handling are cleanup up correctly and don't keep references to old + %% fun's and event listeners + Wx = wx:new(), + Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame Window"), + wxFrame:show(Frame), + + %% wx:debug([verbose,driver]), + Dlg = wxDialog:new(Frame, ?wxID_ANY, "Testing"), + Panel = wxPanel:new(Dlg, []), + Sizer = wxBoxSizer:new(?wxVERTICAL), + Button = wxButton:new(Panel, 600, [{label, "Foobar"}]), + wxSizer:add(Sizer, Button, [{proportion,1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, wxDialog:createStdDialogButtonSizer(Dlg,?wxOK bor ?wxCANCEL)), + wxDialog:setSizerAndFit(Dlg, Sizer), + + Env = wx:get_env(), + SetupEventHandlers = + fun() -> + wx:set_env(Env), + Me = self(), + Print = fun(#wx{id=ID, event=#wxCommand{}},Ev) -> + io:format("~p Clicked ~p~n", [self(), ID]), + Me ! #wx{event=#wxClose{}}, + wxEvent:skip(Ev, [{skip, true}]); + (#wx{id=ID, event=#wxClose{}},Ev) -> + io:format("~p Closed ~p~n", [self(), ID]), + wxEvent:skip(Ev, [{skip, true}]) + end, + + wxDialog:connect(Dlg, command_button_clicked,[{callback,Print}]), + wxDialog:connect(Dlg, close_window, [{skip, true}]) + end, + ?m({[],[],[]}, white_box_check_event_handlers()), + Pid = spawn_link(fun() -> + SetupEventHandlers(), + receive #wx{event=#wxClose{}} -> ok; + remove -> ok + end + end), + timer:sleep(500), %% Give it time to remove it + ?m({[{Pid,_}],[_],[_]}, white_box_check_event_handlers()), + + Pid ! remove, + timer:sleep(500), %% Give it time to remove it + ?m({[],[],[]}, white_box_check_event_handlers()), + + SetupEventHandlers(), + ?m({[{_,_}],[_],[_]}, white_box_check_event_handlers()), + + wxDialog:show(Dlg), + wx_test_lib:wx_close(Dlg, Config), + wxDialog:destroy(Dlg), + timer:sleep(500), %% Give it time to remove it + ?m({[],[],[]}, white_box_check_event_handlers()), + + wx_test_lib:flush(), + io:format("**Deleting Frame**~n",[]), + wx_test_lib:wx_destroy(Frame, Config). + %% timer:sleep(infinity), + %% ok. + + +white_box_check_event_handlers() -> + {_,_,Server,_} = wx:get_env(), + {status, _, _, [Env, _, _, _, Data]} = sys:get_status(Server), + [_H, _data, {data, [{_, Record}]}] = Data, + {state, _Port1, _Port2, Users, [], CBs, _Next} = Record, + {[{Pid, Evs} || + {Pid, {user, Evs}} <- gb_trees:to_list(Users), + Evs =/= []], %% Ignore empty + gb_trees:to_list(CBs), + [Funs || Funs = {Id, {Fun,_}} <- Env, is_integer(Id), is_function(Fun)] + }. + +handler_clean(TestInfo) when is_atom(TestInfo) -> + wx_test_lib:tc_info(TestInfo); +handler_clean(_Config) -> + wx:new(), + Init = fun() -> create_window() end, + Frame1 = wx_obj_test:start([{init, Init}]), + ?mt(wxFrame, Frame1), + wxWindow:show(Frame1), + ?m([_|_], lists:sort(wx_test_lib:flush())), + ?m({stop,_}, wx_obj_test:stop(Frame1, fun(_) -> normal end)), + ?m([{terminate,normal}], lists:sort(wx_test_lib:flush())), + + Frame2 = wx_obj_test:start([{init, Init}]), + wxWindow:show(Frame2), + ?m([_|_], lists:sort(wx_test_lib:flush())), + ?m({stop,_}, wx_obj_test:stop(Frame2, fun(_) -> wxWindow:destroy(Frame2), normal end)), + ?m([{terminate,normal}], lists:sort(wx_test_lib:flush())), + timer:sleep(104), + ?m({[],[],[]}, white_box_check_event_handlers()), + ?m(ok, wx:destroy()), + ok. + +create_window() -> + Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Test wx_object", [{size, {500, 400}}]), + Sz = wxBoxSizer:new(?wxHORIZONTAL), + Panel = wxPanel:new(Frame), + wxSizer:add(Sz, Panel, [{flag, ?wxEXPAND}, {proportion, 1}]), + wxWindow:connect(Frame, show), + %% wxPanel:connect(Panel, paint, [callback, {userData, foobar}]), + wxWindow:connect(Panel, size, [callback]), + {Frame, {Frame, Panel}}. diff --git a/lib/wx/test/wx_obj_test.erl b/lib/wx/test/wx_obj_test.erl index b4d7640c7e..f47f2fbc46 100644 --- a/lib/wx/test/wx_obj_test.erl +++ b/lib/wx/test/wx_obj_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011. All Rights Reserved. +%% Copyright Ericsson AB 2011-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,69 +18,71 @@ -module(wx_obj_test). -include_lib("wx/include/wx.hrl"). --export([start/1]). +-export([start/1, stop/2]). %% wx_object callbacks -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3, handle_sync_event/3, handle_event/2, handle_cast/2]). --record(state, {frame, panel, opts}). +-record(state, {parent, opts, user_state}). start(Opts) -> - wx_object:start_link(?MODULE, [{parent, self()}, Opts], []). + wx_object:start_link(?MODULE, [{parent, self()}| Opts], []). + +stop(Object, Fun) -> + wx_object:call(Object, {stop, Fun}). init(Opts) -> - put(parent_pid, proplists:get_value(parent, Opts)), - Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Test wx_object", [{size, {500, 400}}]), - Sz = wxBoxSizer:new(?wxHORIZONTAL), - Panel = wxPanel:new(Frame), - wxSizer:add(Sz, Panel, [{flag, ?wxEXPAND}, {proportion, 1}]), - wxPanel:connect(Panel, size, [{skip, true}]), - wxPanel:connect(Panel, paint, [callback, {userData, proplists:get_value(parent, Opts)}]), - wxWindow:show(Frame), - {Frame, #state{frame=Frame, panel=Panel, opts=Opts}}. + Parent = proplists:get_value(parent, Opts), + put(parent_pid, Parent), + Init = proplists:get_value(init, Opts), + {Obj, UserState} = Init(), + {Obj, #state{parent=Parent, opts=Opts, user_state=UserState}}. -handle_sync_event(Event = #wx{obj=Panel}, WxEvent, #state{opts=Opts}) -> - DC=wxPaintDC:new(Panel), %% We must create & destroy paintDC, or call wxEvent:skip(WxEvent)) - wxPaintDC:destroy(DC), %% in sync_event. Otherwise wx on windows keeps sending the events. - Pid = proplists:get_value(parent, Opts), - true = is_pid(Pid), - Pid ! {sync_event, Event, WxEvent}, +handle_sync_event(Event = #wx{obj=Panel, event=#wxPaint{}}, + WxEvent, #state{parent=Parent, user_state=US, opts=Opts}) -> + case proplists:get_value(redraw, Opts) of + undefined -> + DC=wxPaintDC:new(Panel), %% We must create & destroy paintDC, or call wxEvent:skip(WxEvent)) + wxPaintDC:destroy(DC), %% in sync_event. Otherwise wx on windows keeps sending the events. + Parent ! {sync_event, Event, WxEvent}; + Redraw -> + Redraw(Event, WxEvent, US) + end, + ok; +handle_sync_event(Event, WxEvent, #state{parent=Parent}) -> + Parent ! {sync_event, Event, WxEvent}, ok. -handle_event(Event, State = #state{opts=Opts}) -> - Pid = proplists:get_value(parent, Opts), - Pid ! {event, Event}, +handle_event(Event, State = #state{parent=Parent}) -> + Parent ! {event, Event}, {noreply, State}. -handle_call(What, From, State) when is_function(What) -> - Result = What(State), +handle_call(What, From, State = #state{user_state=US}) when is_function(What) -> + Result = What(US), {reply, {call, Result, From}, State}; +handle_call({stop, Fun}, From, State = #state{user_state=US}) -> + {stop, Fun(US), {stop, From}, State}; handle_call(What, From, State) -> {reply, {call, What, From}, State}. -handle_cast(What, State = #state{opts=Opts}) when is_function(What) -> - Result = What(State), - Pid = proplists:get_value(parent, Opts), +handle_cast(What, State = #state{parent=Pid, user_state=US}) when is_function(What) -> + Result = What(US), Pid ! {cast, Result}, {noreply, State}; -handle_cast(What, State = #state{opts=Opts}) -> - Pid = proplists:get_value(parent, Opts), +handle_cast(What, State = #state{parent=Pid}) -> Pid ! {cast, What}, {noreply, State}. -handle_info(What, State = #state{opts=Opts}) -> - Pid = proplists:get_value(parent, Opts), +handle_info(What, State = #state{parent=Pid}) -> Pid ! {info, What}, {noreply, State}. -terminate(What, #state{opts=Opts}) -> - Pid = proplists:get_value(parent, Opts), +terminate(What, #state{parent=Pid}) -> Pid ! {terminate, What}, ok. -code_change(Ver1, Ver2, State = #state{opts=Opts}) -> - Pid = proplists:get_value(parent, Opts), +code_change(Ver1, Ver2, State = #state{parent=Pid}) -> Pid ! {code_change, Ver1, Ver2}, State. diff --git a/lib/wx/test/wx_test_lib.erl b/lib/wx/test/wx_test_lib.erl index 8509d6be6f..9b65a50864 100644 --- a/lib/wx/test/wx_test_lib.erl +++ b/lib/wx/test/wx_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% 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 @@ -129,28 +129,30 @@ pick_msg() -> user_available(Config) -> false /= proplists:get_value(user, Config, false). - wx_destroy(Frame, Config) -> + wx_close(Frame, Config), + ?m(ok, wx:destroy()). + +wx_close(Frame, Config) -> case proplists:get_value(user, Config, false) of false -> timer:sleep(100), - ?m(ok, wxFrame:destroy(Frame)), - ?m(ok, wx:destroy()); + ?m(ok, wxWindow:destroy(Frame)); true -> timer:sleep(500), - ?m(ok, wxFrame:destroy(Frame)), - ?m(ok, wx:destroy()); + ?m(ok, wxWindow:destroy(Frame)); step -> %% Wait for user to close window ?m(ok, wxEvtHandler:connect(Frame, close_window, [{skip,true}])), - wait_for_close() + wait_for_close(), + catch wxEvtHandler:disconnect(Frame, close_window), + ok end. wait_for_close() -> receive #wx{event=#wxClose{}} -> - ?log("Got close~n",[]), - ?m(ok, wx:destroy()); + ?log("Got close~n",[]); #wx{obj=Obj, event=Event} -> try Name = wxTopLevelWindow:getTitle(Obj), diff --git a/lib/wx/test/wx_xtra_SUITE.erl b/lib/wx/test/wx_xtra_SUITE.erl index a2d4c26319..8d5d7ddb6a 100644 --- a/lib/wx/test/wx_xtra_SUITE.erl +++ b/lib/wx/test/wx_xtra_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. 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 @@ -129,15 +129,19 @@ app_dies(_Config) -> app_dies2(Test, N) -> spawn_link(fun() -> Test(N) end), - receive - {'EXIT', _, {oops, last}} -> ok; - {'EXIT', _, {oops, _}} -> app_dies2(Test, N+1) + receive + {'EXIT', _, {oops, Server, What}} -> + Ref = erlang:monitor(process, Server), + receive {'DOWN', Ref, _, _, _} -> ok end, + timer:sleep(100), + What =/= last andalso app_dies2(Test, N+1) end. oops(Die, Line) when (Die =:= last) orelse (Die =< Line) -> - timer:sleep(300), + timer:sleep(200), ?log(" Exits at line ~p~n",[Line]), - exit({oops, Die}); + Server = element(3, wx:get_env()), + exit({oops, Server, Die}); oops(_,_) -> ok. |