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(error_logger_SUITE). 21 22-include_lib("common_test/include/ct.hrl"). 23 24%%----------------------------------------------------------------- 25%% We don't have to test the normal behaviour here, i.e. the tty 26%% handler. 27%% We will add an own error handler in order to verify that the 28%% error_logger deliver the expected events. 29%%----------------------------------------------------------------- 30 31-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 32 init_per_group/2,end_per_group/2, 33 off_heap/1, 34 error_report/1, info_report/1, error/1, info/1, 35 emulator/1, via_logger_process/1, other_node/1, 36 tty/1, logfile/1, add/1, delete/1, format_depth/1]). 37 38-export([generate_error/2]). 39 40-export([init/1, 41 handle_event/2, handle_call/2, handle_info/2, 42 terminate/2]). 43 44 45suite() -> 46 [{ct_hooks,[ts_install_cth]}, 47 {timetrap,{minutes,1}}]. 48 49all() -> 50 [off_heap, error_report, info_report, error, info, emulator, 51 via_logger_process, other_node, tty, logfile, add, delete, 52 format_depth]. 53 54groups() -> 55 []. 56 57init_per_suite(Config) -> 58 logger:add_handler(error_logger,error_logger, 59 #{level=>info,filter_default=>log}), 60 Config. 61 62end_per_suite(_Config) -> 63 logger:remove_handler(error_logger), 64 ok. 65 66init_per_group(_GroupName, Config) -> 67 Config. 68 69end_per_group(_GroupName, Config) -> 70 Config. 71 72 73%%----------------------------------------------------------------- 74 75off_heap(_Config) -> 76 %% The error_logger process may receive a huge amount of 77 %% messages. Make sure that they are stored off heap to 78 %% avoid exessive GCs. 79 MQD = message_queue_data, 80 {MQD,off_heap} = process_info(whereis(error_logger), MQD), 81 ok. 82 83%%----------------------------------------------------------------- 84 85error_report(Config) when is_list(Config) -> 86 error_logger:add_report_handler(?MODULE, self()), 87 Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}], 88 Rep2 = [testing,"testing",{tag1,"tag1"}], 89 Rep3 = "This is a string !", 90 Rep4 = {this,is,a,tuple}, 91 ok = error_logger:error_report(Rep1), 92 reported(error_report, std_error, Rep1), 93 ok = error_logger:error_report(Rep2), 94 reported(error_report, std_error, Rep2), 95 ok = error_logger:error_report(Rep3), 96 reported(error_report, std_error, Rep3), 97 ok = error_logger:error_report(Rep4), 98 reported(error_report, std_error, Rep4), 99 100 ok = error_logger:error_report(test_type, Rep1), 101 reported(error_report, test_type, Rep1), 102 ok = error_logger:error_report(test_type, Rep2), 103 reported(error_report, test_type, Rep2), 104 ok = error_logger:error_report(test_type, Rep3), 105 reported(error_report, test_type, Rep3), 106 ok = error_logger:error_report(test_type, Rep4), 107 reported(error_report, test_type, Rep4), 108 109 ok = error_logger:error_report("test_type", Rep1), 110 reported(error_report, "test_type", Rep1), 111 ok = error_logger:error_report({test,type}, Rep2), 112 reported(error_report, {test,type}, Rep2), 113 ok = error_logger:error_report([test,type], Rep3), 114 reported(error_report, [test,type], Rep3), 115 ok = error_logger:error_report(1, Rep4), 116 reported(error_report, 1, Rep4), 117 118 my_yes = error_logger:delete_report_handler(?MODULE), 119 ok. 120 121%%----------------------------------------------------------------- 122 123info_report(Config) when is_list(Config) -> 124 error_logger:add_report_handler(?MODULE, self()), 125 Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}], 126 Rep2 = [testing,"testing",{tag1,"tag1"}], 127 Rep3 = "This is a string !", 128 Rep4 = {this,is,a,tuple}, 129 ok = error_logger:info_report(Rep1), 130 reported(info_report, std_info, Rep1), 131 ok = error_logger:info_report(Rep2), 132 reported(info_report, std_info, Rep2), 133 ok = error_logger:info_report(Rep3), 134 reported(info_report, std_info, Rep3), 135 ok = error_logger:info_report(Rep4), 136 reported(info_report, std_info, Rep4), 137 138 ok = error_logger:info_report(test_type, Rep1), 139 reported(info_report, test_type, Rep1), 140 ok = error_logger:info_report(test_type, Rep2), 141 reported(info_report, test_type, Rep2), 142 ok = error_logger:info_report(test_type, Rep3), 143 reported(info_report, test_type, Rep3), 144 ok = error_logger:info_report(test_type, Rep4), 145 reported(info_report, test_type, Rep4), 146 147 ok = error_logger:info_report("test_type", Rep1), 148 reported(info_report, "test_type", Rep1), 149 ok = error_logger:info_report({test,type}, Rep2), 150 reported(info_report, {test,type}, Rep2), 151 ok = error_logger:info_report([test,type], Rep3), 152 reported(info_report, [test,type], Rep3), 153 ok = error_logger:info_report(1, Rep4), 154 reported(info_report, 1, Rep4), 155 156 my_yes = error_logger:delete_report_handler(?MODULE), 157 ok. 158 159%%----------------------------------------------------------------- 160 161error(Config) when is_list(Config) -> 162 error_logger:add_report_handler(?MODULE, self()), 163 Msg1 = "This is a plain text string~n", 164 Msg2 = "This is a text with arguments ~p~n", 165 Arg2 = "This is the argument", 166 Msg3 = {erroneous,msg}, 167 168 ok = error_logger:error_msg(Msg1), 169 reported(error, Msg1, []), 170 ok = error_logger:error_msg(Msg2, Arg2), 171 reported(error, Msg2, Arg2), 172 ok = error_logger:error_msg(Msg3), 173 reported(error, Msg3, []), 174 175 ok = error_logger:error_msg(Msg1, []), 176 reported(error, Msg1, []), 177 ok = error_logger:error_msg(Msg2, Arg2), 178 reported(error, Msg2, Arg2), 179 ok = error_logger:error_msg(Msg3, []), 180 reported(error, Msg3, []), 181 182 ok = error_logger:format(Msg1, []), 183 reported(error, Msg1, []), 184 ok = error_logger:format(Msg2, Arg2), 185 reported(error, Msg2, Arg2), 186 ok = error_logger:format(Msg3, []), 187 reported(error, Msg3, []), 188 189 my_yes = error_logger:delete_report_handler(?MODULE), 190 ok. 191 192%%----------------------------------------------------------------- 193 194info(Config) when is_list(Config) -> 195 error_logger:add_report_handler(?MODULE, self()), 196 Msg1 = "This is a plain text string~n", 197 Msg2 = "This is a text with arguments ~p~n", 198 Arg2 = "This is the argument", 199 Msg3 = {erroneous,msg}, 200 201 ok = error_logger:info_msg(Msg1), 202 reported(info_msg, Msg1, []), 203 ok = error_logger:info_msg(Msg2, Arg2), 204 reported(info_msg, Msg2, Arg2), 205 ok = error_logger:info_msg(Msg3), 206 reported(info_msg, Msg3, []), 207 208 ok = error_logger:info_msg(Msg1, []), 209 reported(info_msg, Msg1, []), 210 ok = error_logger:info_msg(Msg2, Arg2), 211 reported(info_msg, Msg2, Arg2), 212 ok = error_logger:info_msg(Msg3, []), 213 reported(info_msg, Msg3, []), 214 215 my_yes = error_logger:delete_report_handler(?MODULE), 216 ok. 217 218%%----------------------------------------------------------------- 219 220emulator(Config) when is_list(Config) -> 221 error_logger:add_report_handler(?MODULE, self()), 222 Msg = "Error in process ~p on node ~p with exit value:~n~p~n", 223 Error = {badmatch,4}, 224 Stack = [{module, function, 2, []}], 225 Pid = spawn(?MODULE, generate_error, [Error, Stack]), 226 reported(error, Msg, [Pid, node(), {Error, Stack}]), 227 my_yes = error_logger:delete_report_handler(?MODULE), 228 ok. 229 230generate_error(Error, Stack) -> 231 erlang:raise(error, Error, Stack). 232 233%%----------------------------------------------------------------- 234 235via_logger_process(Config) -> 236 case os:type() of 237 {win32,_} -> 238 {skip,"Skip on windows - cant change file mode"}; 239 _ -> 240 error_logger:add_report_handler(?MODULE, self()), 241 Dir = filename:join(?config(priv_dir,Config),"dummydir"), 242 Msg = "File operation error: eacces. Target: " ++ 243 Dir ++ ". Function: list_dir. ", 244 ok = file:make_dir(Dir), 245 ok = file:change_mode(Dir,8#0222), 246 error = erl_prim_loader:list_dir(Dir), 247 ok = file:change_mode(Dir,8#0664), 248 _ = file:del_dir(Dir), 249 reported(error_report, std_error, Msg), 250 my_yes = error_logger:delete_report_handler(?MODULE), 251 ok 252 end. 253 254%%----------------------------------------------------------------- 255 256other_node(_Config) -> 257 error_logger:add_report_handler(?MODULE, self()), 258 {ok,Node} = test_server:start_node(?FUNCTION_NAME,slave,[]), 259 ok = rpc:call(Node,logger,add_handler,[error_logger,error_logger, 260 #{level=>info,filter_default=>log}]), 261 rpc:call(Node,error_logger,error_report,[hi_from_remote]), 262 reported(error_report,std_error,hi_from_remote), 263 test_server:stop_node(Node), 264 ok. 265 266 267%%----------------------------------------------------------------- 268%% We don't enables or disables tty error logging here. We do not 269%% want to interact with the test run. 270%%----------------------------------------------------------------- 271 272tty(Config) when is_list(Config) -> 273 {'EXIT', _Reason} = (catch error_logger:tty(dummy)), 274 ok. 275 276%%----------------------------------------------------------------- 277%% If where already exists a logfile we skip this test case !! 278%%----------------------------------------------------------------- 279 280logfile(Config) when is_list(Config) -> 281 case error_logger:logfile(filename) of 282 {error, no_log_file} -> % Ok, we continues. 283 do_logfile(); 284 _ -> 285 ok 286 end. 287 288do_logfile() -> 289 {error, _} = error_logger:logfile(close), 290 {error, _} = error_logger:logfile({open,{error}}), 291 ok = error_logger:logfile({open, "dummy_logfile.log"}), 292 "dummy_logfile.log" = error_logger:logfile(filename), 293 ok = error_logger:logfile(close), 294 {'EXIT',_} = (catch error_logger:logfile(dummy)), 295 ok. 296 297%%----------------------------------------------------------------- 298 299add(Config) when is_list(Config) -> 300 {'EXIT',_} = (catch error_logger:add_report_handler("dummy")), 301 {'EXIT',_} = error_logger:add_report_handler(non_existing), 302 my_error = error_logger:add_report_handler(?MODULE, [error]), 303 ok. 304 305%%----------------------------------------------------------------- 306 307delete(Config) when is_list(Config) -> 308 {'EXIT',_} = (catch error_logger:delete_report_handler("dummy")), 309 {error,_} = error_logger:delete_report_handler(non_existing), 310 ok. 311 312%%----------------------------------------------------------------- 313 314format_depth(_Config) -> 315 ok = application:set_env(kernel,error_logger_format_depth,30), 316 30 = error_logger:get_format_depth(), 317 ok = application:set_env(kernel,error_logger_format_depth,3), 318 10 = error_logger:get_format_depth(), 319 ok = application:set_env(kernel,error_logger_format_depth,11), 320 11 = error_logger:get_format_depth(), 321 ok = application:set_env(kernel,error_logger_format_depth,unlimited), 322 unlimited = error_logger:get_format_depth(), 323 ok = application:unset_env(kernel,error_logger_format_depth), 324 unlimited = error_logger:get_format_depth(), 325 ok. 326 327%%----------------------------------------------------------------- 328%% Check that the report has been received. 329%%----------------------------------------------------------------- 330reported(Tag, Type, Report) -> 331 receive 332 {Tag, Type, Report} -> 333 test_server:messages_get(), 334 ok 335 after 1000 -> 336 ct:fail({no_report_received,test_server:messages_get()}) 337 end. 338 339%%----------------------------------------------------------------- 340%% The error_logger handler (gen_event behaviour). 341%% Sends a notification to the Tester process about the events 342%% generated by the Tester process. 343%%----------------------------------------------------------------- 344init(Tester) when is_pid(Tester) -> 345 {ok, Tester}; 346init(Config) when is_list(Config) -> 347 my_error. 348 349handle_event({Tag, _GL, {_EPid, Type, Report}}, Tester) -> 350 Tester ! {Tag, Type, Report}, 351 {ok, Tester}; 352handle_event(_Event, Tester) -> 353 {ok, Tester}. 354 355handle_info({emulator, _GL, String}, Tester) -> 356 Tester ! {emulator, String}, 357 {ok, Tester}; 358handle_info(_, Tester) -> 359 {ok, Tester}. 360 361handle_call(_Query, Tester) -> {ok, {error, bad_query}, Tester}. 362 363terminate(_Reason, _Tester) -> 364 my_yes. 365