1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-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-module(sys_SUITE). 21-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 22 init_per_group/2,end_per_group/2,log/1,log_to_file/1, 23 stats/1,trace/1,suspend/1,install/1,special_process/1]). 24-export([handle_call/3,terminate/2,init/1]). 25-include_lib("common_test/include/ct.hrl"). 26 27-define(server,sys_SUITE_server). 28 29 30%% Doesn't look into change_code at all 31 32 33suite() -> [{ct_hooks,[ts_install_cth]}]. 34 35all() -> 36 [log, log_to_file, stats, trace, suspend, install, special_process]. 37 38groups() -> 39 []. 40 41init_per_suite(Config) -> 42 Config. 43 44end_per_suite(_Config) -> 45 ok. 46 47init_per_group(_GroupName, Config) -> 48 Config. 49 50end_per_group(_GroupName, Config) -> 51 Config. 52 53 54%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 56log(Config) when is_list(Config) -> 57 {ok,_Server} = start(), 58 ok = sys:log(?server,true), 59 {ok,-44} = public_call(44), 60 ok = sys:log(?server,false), 61 ok = sys:log(?server,print), 62 stop(), 63 ok. 64 65log_to_file(Config) when is_list(Config) -> 66 TempName = test_server:temp_name(proplists:get_value(priv_dir,Config) ++ "sys."), 67 {ok,_Server} = start(), 68 ok = sys:log_to_file(?server,TempName), 69 {ok,-44} = public_call(44), 70 ok = sys:log_to_file(?server,false), 71 {ok,Fd} = file:open(TempName,[read]), 72 Msg1 = io:get_line(Fd,''), 73 Msg2 = io:get_line(Fd,''), 74 file:close(Fd), 75 "*DBG* sys_SUITE_server got call {req,44} from " ++ _ = Msg1, 76 "*DBG* sys_SUITE_server sent {ok,-44} to " ++ _ = Msg2, 77 stop(), 78 ok. 79 80stats(Config) when is_list(Config) -> 81 Self = self(), 82 {ok,_Server} = start(), 83 ok = sys:statistics(?server,true), 84 {ok,-44} = public_call(44), 85 {ok,Stats} = sys:statistics(?server,get), 86 true = lists:member({messages_in,1}, Stats), 87 true = lists:member({messages_out,1}, Stats), 88 ok = sys:statistics(?server,false), 89 {status,_Pid,{module,_Mod},[_PDict,running,Self,_,_]} = 90 sys:get_status(?server), 91 {ok,no_statistics} = sys:statistics(?server,get), 92 stop(), 93 ok. 94 95trace(Config) when is_list(Config) -> 96 {ok,_Server} = start(), 97 ct:sleep(2000), 98 ct:capture_start(), 99 sys:trace(?server,true), 100 {ok,-44} = public_call(44), 101 %% ho, hum, allow for the io to reach us.. 102 ct:sleep(1000), 103 ct:capture_stop(), 104 [Msg1,Msg2] = ct:capture_get(), 105 "*DBG* sys_SUITE_server got call {req,44} from " ++ _ = Msg1, 106 "*DBG* sys_SUITE_server sent {ok,-44} to " ++ _ = Msg2, 107 stop(), 108 ok. 109 110suspend(Config) when is_list(Config) -> 111 {ok,_Server} = start(), 112 sys:suspend(?server,1000), 113 {'EXIT',_} = (catch public_call(48)), 114 {status,_,_,[_,suspended,_,_,_]} = sys:get_status(?server), 115 sys:suspend(?server,1000), %% doing it twice is no error 116 {'EXIT',_} = (catch public_call(48)), 117 sys:resume(?server), 118 {status,_,_,[_,running,_,_,_]} = sys:get_status(?server), 119 {ok,-48} = (catch public_call(48)), 120 sys:resume(?server), %% doing it twice is no error 121 {ok,-48} = (catch public_call(48)), 122 stop(), 123 ok. 124 125install(Config) when is_list(Config) -> 126 {ok,_Server} = start(), 127 Master = self(), 128 SpyFun = 129 fun(func_state,Event,ProcState) -> 130 case Event of 131 {in,{'$gen_call',_From,{req,Arg}}} -> 132 io:format("Trigged\n"), 133 Master ! {spy_got,{request,Arg},ProcState}; 134 Other -> 135 io:format("Trigged other=~p\n",[Other]) 136 end, 137 func_state 138 end, 139 sys:install(?server,{SpyFun,func_state}), 140 {ok,-1} = (catch public_call(1)), 141 sys:no_debug(?server), 142 {ok,-2} = (catch public_call(2)), 143 sys:install(?server,{SpyFun,func_state}), 144 sys:install(?server,{SpyFun,func_state}), 145 {ok,-3} = (catch public_call(3)), 146 {ok,-4} = (catch public_call(4)), 147 sys:remove(?server,SpyFun), 148 {ok,-5} = (catch public_call(5)), 149 [{spy_got,{request,1},sys_SUITE_server}, 150 {spy_got,{request,3},sys_SUITE_server}, 151 {spy_got,{request,4},sys_SUITE_server}] = get_messages(), 152 153 sys:install(?server,{id1, SpyFun, func_state}), 154 sys:install(?server,{id1, SpyFun, func_state}), %% should not be installed 155 sys:install(?server,{id2, SpyFun, func_state}), 156 {ok,-1} = (catch public_call(1)), 157 %% We have two SpyFun installed: 158 [{spy_got,{request,1},sys_SUITE_server}, 159 {spy_got,{request,1},sys_SUITE_server}] = get_messages(), 160 sys:remove(?server, id1), 161 {ok,-1} = (catch public_call(1)), 162 %% We have one SpyFun installed: 163 [{spy_got,{request,1},sys_SUITE_server}] = get_messages(), 164 sys:no_debug(?server), 165 {ok,-1} = (catch public_call(1)), 166 [] = get_messages(), 167 stop(), 168 ok. 169 170get_messages() -> 171 receive 172 Msg -> [Msg|get_messages()] 173 after 1 -> [] 174 end. 175 176special_process(Config) when is_list(Config) -> 177 ok = spec_proc(sys_sp1), 178 ok = spec_proc(sys_sp2). 179 180spec_proc(Mod) -> 181 {ok,_} = Mod:start_link(100), 182 ok = sys:statistics(Mod,true), 183 ok = sys:trace(Mod,true), 184 1 = Ch = Mod:alloc(), 185 Free = lists:seq(2,100), 186 Replace = case sys:get_state(Mod) of 187 {[Ch],Free} -> 188 fun({A,F}) -> 189 Free = F, 190 {A,[2,3,4]} 191 end; 192 {state,[Ch],Free} -> 193 fun({state,A,F}) -> 194 Free = F, 195 {state,A,[2,3,4]} 196 end 197 end, 198 case sys:replace_state(Mod, Replace) of 199 {[Ch],[2,3,4]} -> ok; 200 {state,[Ch],[2,3,4]} -> ok 201 end, 202 ok = Mod:free(Ch), 203 case sys:get_state(Mod) of 204 {[],[1,2,3,4]} -> ok; 205 {state,[],[1,2,3,4]} -> ok 206 end, 207 {ok,[{start_time,_}, 208 {current_time,_}, 209 {reductions,_}, 210 {messages_in,2}, 211 {messages_out,1}]} = sys:statistics(Mod,get), 212 ok = sys:statistics(Mod,false), 213 [] = sys:replace_state(Mod, fun(_) -> [] end), 214 process_flag(trap_exit,true), 215 ok = case catch sys:get_state(Mod) of 216 [] -> 217 ok; 218 {'EXIT',{{callback_failed, 219 {Mod,system_get_state},{throw,fail}},_}} -> 220 ok 221 end, 222 ok = sync_terminate(Mod), 223 {ok,_} = Mod:start_link(4), 224 ok = case catch sys:replace_state(Mod, fun(_) -> {} end) of 225 {} -> 226 ok; 227 {'EXIT',{{callback_failed, 228 {Mod,system_replace_state},{throw,fail}},_}} -> 229 ok 230 end, 231 ok = sync_terminate(Mod), 232 {ok,_} = Mod:start_link(4), 233 StateFun = fun(_) -> error(fail) end, 234 ok = case catch sys:replace_state(Mod, StateFun) of 235 {} -> 236 ok; 237 {'EXIT',{{callback_failed, 238 {Mod,system_replace_state},{error,fail}},_}} -> 239 ok; 240 {'EXIT',{{callback_failed,StateFun,{error,fail}},_}} -> 241 ok 242 end, 243 ok = sync_terminate(Mod). 244 245sync_terminate(Mod) -> 246 P = whereis(Mod), 247 MRef = erlang:monitor(process,P), 248 ok = sys:terminate(Mod, normal), 249 receive 250 {'DOWN',MRef,_,_,normal} -> 251 ok 252 end, 253 undefined = whereis(Mod), 254 ok. 255 256%%%%%%%%%%%%%%%%%%%% 257%% Dummy server 258 259public_call(Arg) -> 260 gen_server:call(?server,{req,Arg},1000). 261 262start() -> 263 gen_server:start_link({local,?server},?MODULE,[],[]). 264 265stop() -> 266 gen_server:call(?server,stop,1000). 267 268init([]) -> 269 {ok,0}. 270 271handle_call({req,Arg},_From,State) -> 272 NewState = State+1, 273 {reply,{ok,-Arg},NewState}; 274handle_call(stop,_From,State) -> 275 {stop,normal,ok,State}. 276 277terminate(_Reason, _State) -> 278 ok. 279 280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 281