1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2009-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(cth_auto_clean). 22 23%% CTH Callbacks 24-export([id/1, init/2, 25 pre_init_per_suite/3, post_init_per_suite/4, 26 pre_end_per_suite/3, post_end_per_suite/4, 27 pre_init_per_group/4, post_init_per_group/5, 28 pre_end_per_group/4, post_end_per_group/5, 29 pre_init_per_testcase/4, post_init_per_testcase/5, 30 pre_end_per_testcase/4, post_end_per_testcase/5]). 31 32id(_Opts) -> 33 ?MODULE. 34 35init(?MODULE, _Opts) -> 36 ok. 37 38pre_init_per_suite(_Suite, Config, State) -> 39 identify(?FUNCTION_NAME), 40 SharedGL = test_server_io:get_gl(true), 41 SharedGL = find_and_kill(), 42 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 43 %% get status of processes at startup, to be compared with end result 44 {Config, [{all_procs,processes()} | State]}. 45 46post_init_per_suite(_Suite, _Config, Return, State) -> 47 identify(?FUNCTION_NAME), 48 SharedGL = find_and_kill(), 49 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 50 {Return, State}. 51 52pre_end_per_suite(_Suite, Config, State) -> 53 identify(?FUNCTION_NAME), 54 SharedGL = find_and_kill(), 55 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 56 {Config, State}. 57 58post_end_per_suite(_Suite, _Config, Return, State) -> 59 identify(?FUNCTION_NAME), 60 SharedGL = find_and_kill(), 61 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 62 AllProcs = processes(), 63 Remaining = AllProcs--proplists:get_value(all_procs, State), 64 ct:pal("Final remaining processes = ~p", [Remaining]), 65 %% only the end_per_suite process shoud remain at this point! 66 Remaining = [self()], 67 {Return, State}. 68 69pre_init_per_group(_Suite, _Group, Config, State) -> 70 identify(?FUNCTION_NAME), 71 SharedGL = find_and_kill(procs_and_gls), 72 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 73 {Config, State}. 74 75post_init_per_group(_Suite, _Group, _Config, Result, State) -> 76 identify(?FUNCTION_NAME), 77 SharedGL = find_and_kill(procs_and_gls), 78 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 79 {Result, State}. 80 81pre_init_per_testcase(_Suite, _TC, Config, State) -> 82 identify(?FUNCTION_NAME), 83 ThisGL = group_leader(), 84 find_and_kill(proc, ThisGL), 85 case proplists:get_value(tc_group_properties, Config) of 86 [{name,_},parallel] -> 87 timer:sleep(1000); 88 _ -> 89 do_until(fun() -> element(1,ct:remaining_test_procs()) end, []) 90 end, 91 {Config, State}. 92 93post_init_per_testcase(_Suite, _TC, Config, Return, State) -> 94 identify(?FUNCTION_NAME), 95 ThisGL = group_leader(), 96 find_and_kill(proc, ThisGL), 97 case proplists:get_value(tc_group_properties, Config) of 98 [{name,_},parallel] -> 99 timer:sleep(1000); 100 _ -> 101 do_until(fun() -> element(1,ct:remaining_test_procs()) end, []) 102 end, 103 {Return, State}. 104 105pre_end_per_testcase(_Suite, _TC, Config, State) -> 106 identify(?FUNCTION_NAME), 107 ThisGL = group_leader(), 108 find_and_kill(proc, ThisGL), 109 case proplists:get_value(tc_group_properties, Config) of 110 [{name,_},parallel] -> 111 timer:sleep(1000); 112 _ -> 113 do_until(fun() -> element(1,ct:remaining_test_procs()) end, []) 114 end, 115 {Config, State}. 116 117post_end_per_testcase(_Suite, _TC, Config, Result, State) -> 118 identify(?FUNCTION_NAME), 119 ThisGL = group_leader(), 120 find_and_kill(proc, ThisGL), 121 case proplists:get_value(tc_group_properties, Config) of 122 [{name,_},parallel] -> 123 timer:sleep(1000); 124 _ -> 125 do_until(fun() -> element(1,ct:remaining_test_procs()) end, []) 126 end, 127 {Result, State}. 128 129pre_end_per_group(_Suite, _Group, Config, State) -> 130 identify(?FUNCTION_NAME), 131 SharedGL = find_and_kill(procs_and_gls), 132 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 133 {Config, State}. 134 135post_end_per_group(_Suite, _Group, _Config, Return, State) -> 136 identify(?FUNCTION_NAME), 137 SharedGL = find_and_kill(procs_and_gls), 138 do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}), 139 {Return, State}. 140 141 142%%%----------------------------------------------------------------- 143%%% HELP FUNCTIONS 144%%%----------------------------------------------------------------- 145 146identify(Func) -> 147 ct:pal("********** THIS IS ~w on ~w", [Func, self()]), 148 ok. 149 150find_and_kill() -> 151 find_and_kill(procs). 152 153find_and_kill(procs) -> 154 {Procs,SharedGL,_ParallelGLs} = ct:remaining_test_procs(), 155 ct:pal("Remaining test processes = ~p", [pi(Procs)]), 156 [pkill(P, kill) || {P,_GL} <- Procs], 157 SharedGL; 158 159find_and_kill(procs_and_gls) -> 160 {Procs,SharedGL,GLs} = ct:remaining_test_procs(), 161 ct:pal("Remaining test processes = ~p", [pi(Procs)]), 162 [pkill(P, kill) || {P,_GL} <- Procs], 163 ct:pal("Remaining group leaders = ~p", [pi(GLs)]), 164 [pkill(GL, kill) || GL <- GLs, GL /= SharedGL], 165 SharedGL. 166 167find_and_kill(proc, ProcGL) -> 168 {Procs,SharedGL,GLs} = ct:remaining_test_procs(), 169 ct:pal("Remaining test processes = ~p", [pi(Procs++GLs)]), 170 [pkill(P, kill) || {P,GL} <- Procs, GL == ProcGL], 171 SharedGL. 172 173pi([{P,_GL}|Ps]) -> 174 pi([P|Ps]); 175pi([P|Ps]) -> 176 case node() == node(P) of 177 true -> 178 {_,GL} = process_info(P,group_leader), 179 {_,CF} = process_info(P,current_function), 180 {_,IC} = process_info(P,initial_call), 181 {_,D} = process_info(P,dictionary), 182 Shared = test_server_io:get_gl(true), 183 User = whereis(user), 184 if (GL /= P) and (GL /= Shared) and (GL /= User) -> 185 [{P,GL,CF,IC,D} | pi([GL|Ps])]; 186 true -> 187 [{P,GL,CF,IC,D} | pi(Ps)] 188 end; 189 false -> 190 pi(Ps) 191 end; 192pi([]) -> 193 []. 194 195do_until(Fun, Until) -> 196 io:format("Will do until ~p~n", [Until]), 197 do_until(Fun, Until, 1000). 198 199do_until(_, Until, 0) -> 200 io:format("Couldn't get ~p~n", [Until]), 201 exit({not_reached,Until}); 202 203do_until(Fun, Until, N) -> 204 case Fun() of 205 Until -> 206 ok; 207 _Tmp -> 208 do_until(Fun, Until, N-1) 209 end. 210 211pkill(P, How) -> 212 ct:pal("KILLING ~w NOW!", [P]), 213 exit(P, How). 214 215