您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

655 行
30 KiB

14 年前
14 年前
14 年前
14 年前
14 年前
14 年前
14 年前
14 年前
14 年前
14 年前
14 年前
  1. %% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
  2. %%
  3. %% This file is provided to you under the Apache License,
  4. %% Version 2.0 (the "License"); you may not use this file
  5. %% except in compliance with the License. You may obtain
  6. %% a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing,
  11. %% software distributed under the License is distributed on an
  12. %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. %% KIND, either express or implied. See the License for the
  14. %% specific language governing permissions and limitations
  15. %% under the License.
  16. -module(lager_test_backend).
  17. -include("lager.hrl").
  18. -behaviour(gen_event).
  19. -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2,
  20. code_change/3]).
  21. -record(state, {level, buffer, ignored}).
  22. -compile([{parse_transform, lager_transform}]).
  23. -ifdef(TEST).
  24. -include_lib("eunit/include/eunit.hrl").
  25. -export([pop/0, count/0, count_ignored/0, flush/0]).
  26. -endif.
  27. init(Level) ->
  28. {ok, #state{level=lager_util:level_to_num(Level), buffer=[], ignored=[]}}.
  29. handle_call(count, #state{buffer=Buffer} = State) ->
  30. {ok, length(Buffer), State};
  31. handle_call(count_ignored, #state{ignored=Ignored} = State) ->
  32. {ok, length(Ignored), State};
  33. handle_call(flush, State) ->
  34. {ok, ok, State#state{buffer=[], ignored=[]}};
  35. handle_call(pop, #state{buffer=Buffer} = State) ->
  36. case Buffer of
  37. [] ->
  38. {ok, undefined, State};
  39. [H|T] ->
  40. {ok, H, State#state{buffer=T}}
  41. end;
  42. handle_call(get_loglevel, #state{level=Level} = State) ->
  43. {ok, Level, State};
  44. handle_call({set_loglevel, Level}, State) ->
  45. {ok, ok, State#state{level=lager_util:level_to_num(Level)}};
  46. handle_call(_Request, State) ->
  47. {ok, ok, State}.
  48. handle_event({log, Level, Time, Message}, #state{level=LogLevel,
  49. buffer=Buffer} = State) when Level =< LogLevel ->
  50. {ok, State#state{buffer=Buffer ++ [{Level, Time, Message}]}};
  51. handle_event({log, _Level, _Time, _Message}, #state{ignored=Ignored} = State) ->
  52. {ok, State#state{ignored=Ignored ++ [ignored]}};
  53. handle_event(_Event, State) ->
  54. {ok, State}.
  55. handle_info(_Info, State) ->
  56. {ok, State}.
  57. terminate(_Reason, _State) ->
  58. ok.
  59. code_change(_OldVsn, State, _Extra) ->
  60. {ok, State}.
  61. -ifdef(TEST).
  62. pop() ->
  63. gen_event:call(lager_event, ?MODULE, pop).
  64. count() ->
  65. gen_event:call(lager_event, ?MODULE, count).
  66. count_ignored() ->
  67. gen_event:call(lager_event, ?MODULE, count_ignored).
  68. flush() ->
  69. gen_event:call(lager_event, ?MODULE, flush).
  70. not_running_test() ->
  71. ?assertEqual({error, lager_not_running}, lager:log(info, self(), "not running")).
  72. lager_test_() ->
  73. {foreach,
  74. fun setup/0,
  75. fun cleanup/1,
  76. [
  77. {"observe that there is nothing up my sleeve",
  78. fun() ->
  79. ?assertEqual(undefined, pop()),
  80. ?assertEqual(0, count())
  81. end
  82. },
  83. {"logging works",
  84. fun() ->
  85. lager:warning("test message"),
  86. ?assertEqual(1, count()),
  87. {Level, _Time, Message} = pop(),
  88. ?assertMatch(Level, lager_util:level_to_num(warning)),
  89. [LevelStr, _LocStr, MsgStr] = re:split(Message, " ", [{return, list}, {parts, 3}]),
  90. ?assertEqual("[warning]", LevelStr),
  91. ?assertEqual("test message", MsgStr),
  92. ok
  93. end
  94. },
  95. {"logging with arguments works",
  96. fun() ->
  97. lager:warning("test message ~p", [self()]),
  98. ?assertEqual(1, count()),
  99. {Level, _Time, Message} = pop(),
  100. ?assertMatch(Level, lager_util:level_to_num(warning)),
  101. [LevelStr, _LocStr, MsgStr] = re:split(Message, " ", [{return, list}, {parts, 3}]),
  102. ?assertEqual("[warning]", LevelStr),
  103. ?assertEqual(lists:flatten(io_lib:format("test message ~p", [self()])), MsgStr),
  104. ok
  105. end
  106. },
  107. {"logging works from inside a begin/end block",
  108. fun() ->
  109. ?assertEqual(0, count()),
  110. begin
  111. lager:warning("test message 2")
  112. end,
  113. ?assertEqual(1, count()),
  114. ok
  115. end
  116. },
  117. {"logging works from inside a list comprehension",
  118. fun() ->
  119. ?assertEqual(0, count()),
  120. [lager:warning("test message") || _N <- lists:seq(1, 10)],
  121. ?assertEqual(10, count()),
  122. ok
  123. end
  124. },
  125. {"logging works from a begin/end block inside a list comprehension",
  126. fun() ->
  127. ?assertEqual(0, count()),
  128. [ begin lager:warning("test message") end || _N <- lists:seq(1, 10)],
  129. ?assertEqual(10, count()),
  130. ok
  131. end
  132. },
  133. {"logging works from a nested list comprehension",
  134. fun() ->
  135. ?assertEqual(0, count()),
  136. [ [lager:warning("test message") || _N <- lists:seq(1, 10)] ||
  137. _I <- lists:seq(1, 10)],
  138. ?assertEqual(100, count()),
  139. ok
  140. end
  141. },
  142. {"log messages below the threshold are ignored",
  143. fun() ->
  144. ?assertEqual(0, count()),
  145. lager:debug("this message will be ignored"),
  146. ?assertEqual(0, count()),
  147. ?assertEqual(0, count_ignored()),
  148. lager_mochiglobal:put(loglevel, ?DEBUG),
  149. lager:debug("this message should be ignored"),
  150. ?assertEqual(0, count()),
  151. ?assertEqual(1, count_ignored()),
  152. lager:set_loglevel(?MODULE, debug),
  153. lager:debug("this message should be logged"),
  154. ?assertEqual(1, count()),
  155. ?assertEqual(1, count_ignored()),
  156. ?assertEqual(debug, lager:get_loglevel(?MODULE)),
  157. ok
  158. end
  159. }
  160. ]
  161. }.
  162. setup() ->
  163. error_logger:tty(false),
  164. application:load(lager),
  165. application:set_env(lager, handlers, [{?MODULE, info}]),
  166. application:set_env(lager, error_logger_redirect, false),
  167. application:start(lager),
  168. gen_event:call(lager_event, ?MODULE, flush).
  169. cleanup(_) ->
  170. application:stop(lager),
  171. error_logger:tty(true).
  172. crash(Type) ->
  173. spawn(fun() -> gen_server:call(crash, Type) end),
  174. timer:sleep(100).
  175. custom_sleep(MSec) ->
  176. timer:sleep(MSec),
  177. [_|_] = gen_event:which_handlers(error_logger),
  178. [_|_] = gen_event:which_handlers(lager_event),
  179. ok.
  180. error_logger_redirect_crash_test_() ->
  181. {foreach,
  182. fun() ->
  183. error_logger:tty(false),
  184. application:load(lager),
  185. application:set_env(lager, error_logger_redirect, true),
  186. application:set_env(lager, handlers, [{?MODULE, error}]),
  187. application:start(lager),
  188. crash:start()
  189. end,
  190. fun(_) ->
  191. application:stop(lager),
  192. case whereis(crash) of
  193. undefined -> ok;
  194. Pid -> exit(Pid, kill)
  195. end,
  196. error_logger:tty(true)
  197. end,
  198. [
  199. {"again, there is nothing up my sleeve",
  200. fun() ->
  201. ?assertEqual(undefined, pop()),
  202. ?assertEqual(0, count())
  203. end
  204. },
  205. {"bad return value",
  206. fun() ->
  207. Pid = whereis(crash),
  208. crash(bad_return),
  209. {_, _, Msg} = pop(),
  210. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad return value: bleh", [Pid])),
  211. ?assertEqual(Expected, lists:flatten(Msg))
  212. end
  213. },
  214. {"case clause",
  215. fun() ->
  216. Pid = whereis(crash),
  217. crash(case_clause),
  218. {_, _, Msg} = pop(),
  219. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no case clause matching {} in crash:handle_call/3", [Pid])),
  220. ?assertEqual(Expected, lists:flatten(Msg))
  221. end
  222. },
  223. {"function clause",
  224. fun() ->
  225. Pid = whereis(crash),
  226. crash(function_clause),
  227. {_, _, Msg} = pop(),
  228. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no function clause matching crash:function({})", [Pid])),
  229. ?assertEqual(Expected, lists:flatten(Msg))
  230. end
  231. },
  232. {"if clause",
  233. fun() ->
  234. Pid = whereis(crash),
  235. crash(if_clause),
  236. {_, _, Msg} = pop(),
  237. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no true branch found while evaluating if expression in crash:handle_call/3", [Pid])),
  238. ?assertEqual(Expected, lists:flatten(Msg))
  239. end
  240. },
  241. {"try clause",
  242. fun() ->
  243. Pid = whereis(crash),
  244. crash(try_clause),
  245. {_, _, Msg} = pop(),
  246. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no try clause matching [] in crash:handle_call/3", [Pid])),
  247. ?assertEqual(Expected, lists:flatten(Msg))
  248. end
  249. },
  250. {"undefined function",
  251. fun() ->
  252. Pid = whereis(crash),
  253. crash(undef),
  254. {_, _, Msg} = pop(),
  255. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: call to undefined function crash:booger/0 from crash:handle_call/3", [Pid])),
  256. ?assertEqual(Expected, lists:flatten(Msg))
  257. end
  258. },
  259. {"bad math",
  260. fun() ->
  261. Pid = whereis(crash),
  262. crash(badarith),
  263. {_, _, Msg} = pop(),
  264. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad arithmetic expression in crash:handle_call/3", [Pid])),
  265. ?assertEqual(Expected, lists:flatten(Msg))
  266. end
  267. },
  268. {"bad match",
  269. fun() ->
  270. Pid = whereis(crash),
  271. crash(badmatch),
  272. {_, _, Msg} = pop(),
  273. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no match of right hand value {} in crash:handle_call/3", [Pid])),
  274. ?assertEqual(Expected, lists:flatten(Msg))
  275. end
  276. },
  277. {"bad arity",
  278. fun() ->
  279. Pid = whereis(crash),
  280. crash(badarity),
  281. {_, _, Msg} = pop(),
  282. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: fun called with wrong arity of 1 instead of 3 in crash:handle_call/3", [Pid])),
  283. ?assertEqual(Expected, lists:flatten(Msg))
  284. end
  285. },
  286. {"bad arg1",
  287. fun() ->
  288. Pid = whereis(crash),
  289. crash(badarg1),
  290. {_, _, Msg} = pop(),
  291. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad argument in crash:handle_call/3", [Pid])),
  292. ?assertEqual(Expected, lists:flatten(Msg))
  293. end
  294. },
  295. {"bad arg2",
  296. fun() ->
  297. Pid = whereis(crash),
  298. crash(badarg2),
  299. {_, _, Msg} = pop(),
  300. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad argument in call to erlang:iolist_to_binary([[102,111,111],bar]) in crash:handle_call/3", [Pid])),
  301. ?assertEqual(Expected, lists:flatten(Msg))
  302. end
  303. },
  304. {"noproc",
  305. fun() ->
  306. Pid = whereis(crash),
  307. crash(noproc),
  308. {_, _, Msg} = pop(),
  309. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no such process or port in call to gen_event:call(foo, bar, baz)", [Pid])),
  310. ?assertEqual(Expected, lists:flatten(Msg))
  311. end
  312. },
  313. {"badfun",
  314. fun() ->
  315. Pid = whereis(crash),
  316. crash(badfun),
  317. {_, _, Msg} = pop(),
  318. Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad function booger in crash:handle_call/3", [Pid])),
  319. ?assertEqual(Expected, lists:flatten(Msg))
  320. end
  321. }
  322. ]
  323. }.
  324. error_logger_redirect_test_() ->
  325. {foreach,
  326. fun() ->
  327. error_logger:tty(false),
  328. application:load(lager),
  329. application:set_env(lager, error_logger_redirect, true),
  330. application:set_env(lager, handlers, [{?MODULE, info}]),
  331. application:start(lager),
  332. timer:sleep(100),
  333. gen_event:call(lager_event, ?MODULE, flush)
  334. end,
  335. fun(_) ->
  336. application:stop(lager),
  337. error_logger:tty(true)
  338. end,
  339. [
  340. {"error reports are printed",
  341. fun() ->
  342. error_logger:error_report([{this, is}, a, {silly, format}]),
  343. custom_sleep(100),
  344. {_, _, Msg} = pop(),
  345. Expected = lists:flatten(io_lib:format("[error] ~w this: is, a, silly: format", [self()])),
  346. ?assertEqual(Expected, lists:flatten(Msg))
  347. end
  348. },
  349. {"string error reports are printed",
  350. fun() ->
  351. error_logger:error_report("this is less silly"),
  352. custom_sleep(100),
  353. {_, _, Msg} = pop(),
  354. Expected = lists:flatten(io_lib:format("[error] ~w this is less silly", [self()])),
  355. ?assertEqual(Expected, lists:flatten(Msg))
  356. end
  357. },
  358. {"error messages are printed",
  359. fun() ->
  360. error_logger:error_msg("doom, doom has come upon you all"),
  361. custom_sleep(100),
  362. {_, _, Msg} = pop(),
  363. Expected = lists:flatten(io_lib:format("[error] ~w doom, doom has come upon you all", [self()])),
  364. ?assertEqual(Expected, lists:flatten(Msg))
  365. end
  366. },
  367. {"error messages are truncated at 4096 characters",
  368. fun() ->
  369. error_logger:error_msg("doom, doom has come upon you all ~p", [string:copies("doom", 10000)]),
  370. custom_sleep(1000),
  371. {_, _, Msg} = pop(),
  372. ?assert(length(lists:flatten(Msg)) < 5100)
  373. end
  374. },
  375. {"info reports are printed",
  376. fun() ->
  377. error_logger:info_report([{this, is}, a, {silly, format}]),
  378. custom_sleep(100),
  379. {_, _, Msg} = pop(),
  380. Expected = lists:flatten(io_lib:format("[info] ~w this: is, a, silly: format", [self()])),
  381. ?assertEqual(Expected, lists:flatten(Msg))
  382. end
  383. },
  384. {"info reports are truncated at 4096 characters",
  385. fun() ->
  386. error_logger:info_report([[{this, is}, a, {silly, format}] || _ <- lists:seq(0, 600)]),
  387. custom_sleep(1000),
  388. {_, _, Msg} = pop(),
  389. ?assert(length(lists:flatten(Msg)) < 5000)
  390. end
  391. },
  392. {"single term info reports are printed",
  393. fun() ->
  394. error_logger:info_report({foolish, bees}),
  395. custom_sleep(100),
  396. {_, _, Msg} = pop(),
  397. Expected = lists:flatten(io_lib:format("[info] ~w {foolish,bees}", [self()])),
  398. ?assertEqual(Expected, lists:flatten(Msg))
  399. end
  400. },
  401. {"single term error reports are printed",
  402. fun() ->
  403. error_logger:error_report({foolish, bees}),
  404. custom_sleep(100),
  405. {_, _, Msg} = pop(),
  406. Expected = lists:flatten(io_lib:format("[error] ~w {foolish,bees}", [self()])),
  407. ?assertEqual(Expected, lists:flatten(Msg))
  408. end
  409. },
  410. {"string info reports are printed",
  411. fun() ->
  412. error_logger:info_report("this is less silly"),
  413. custom_sleep(100),
  414. {_, _, Msg} = pop(),
  415. Expected = lists:flatten(io_lib:format("[info] ~w this is less silly", [self()])),
  416. ?assertEqual(Expected, lists:flatten(Msg))
  417. end
  418. },
  419. {"string info reports are truncated at 4096 characters",
  420. fun() ->
  421. error_logger:info_report(string:copies("this is less silly", 1000)),
  422. custom_sleep(1000),
  423. {_, _, Msg} = pop(),
  424. ?assert(length(lists:flatten(Msg)) < 5100)
  425. end
  426. },
  427. {"info messages are printed",
  428. fun() ->
  429. error_logger:info_msg("doom, doom has come upon you all"),
  430. custom_sleep(100),
  431. {_, _, Msg} = pop(),
  432. Expected = lists:flatten(io_lib:format("[info] ~w doom, doom has come upon you all", [self()])),
  433. ?assertEqual(Expected, lists:flatten(Msg))
  434. end
  435. },
  436. {"info messages are truncated at 4096 characters",
  437. fun() ->
  438. error_logger:info_msg("doom, doom has come upon you all ~p", [string:copies("doom", 10000)]),
  439. custom_sleep(1000),
  440. {_, _, Msg} = pop(),
  441. ?assert(length(lists:flatten(Msg)) < 5100)
  442. end
  443. },
  444. {"warning messages are printed at the correct level",
  445. fun() ->
  446. error_logger:warning_msg("doom, doom has come upon you all"),
  447. Map = error_logger:warning_map(),
  448. custom_sleep(100),
  449. {_, _, Msg} = pop(),
  450. Expected = lists:flatten(io_lib:format("[~w] ~w doom, doom has come upon you all", [Map, self()])),
  451. ?assertEqual(Expected, lists:flatten(Msg))
  452. end
  453. },
  454. {"warning reports are printed at the correct level",
  455. fun() ->
  456. error_logger:warning_report([{i, like}, pie]),
  457. Map = error_logger:warning_map(),
  458. custom_sleep(100),
  459. {_, _, Msg} = pop(),
  460. Expected = lists:flatten(io_lib:format("[~w] ~w i: like, pie", [Map, self()])),
  461. ?assertEqual(Expected, lists:flatten(Msg))
  462. end
  463. },
  464. {"single term warning reports are printed at the correct level",
  465. fun() ->
  466. error_logger:warning_report({foolish, bees}),
  467. Map = error_logger:warning_map(),
  468. custom_sleep(100),
  469. {_, _, Msg} = pop(),
  470. Expected = lists:flatten(io_lib:format("[~w] ~w {foolish,bees}", [Map, self()])),
  471. ?assertEqual(Expected, lists:flatten(Msg))
  472. end
  473. },
  474. {"application stop reports",
  475. fun() ->
  476. error_logger:info_report([{application, foo}, {exited, quittin_time}, {type, lazy}]),
  477. custom_sleep(100),
  478. {_, _, Msg} = pop(),
  479. Expected = lists:flatten(io_lib:format("[info] ~w Application foo exited with reason: quittin_time", [self()])),
  480. ?assertEqual(Expected, lists:flatten(Msg))
  481. end
  482. },
  483. {"supervisor reports",
  484. fun() ->
  485. error_logger:error_report(supervisor_report, [{errorContext, france}, {offender, [{name, mini_steve}, {mfargs, {a, b, [c]}}, {pid, bleh}]}, {reason, fired}, {supervisor, {local, steve}}]),
  486. custom_sleep(100),
  487. {_, _, Msg} = pop(),
  488. Expected = lists:flatten(io_lib:format("[error] ~w Supervisor steve had child mini_steve started with a:b(c) at bleh exit with reason fired in context france", [self()])),
  489. ?assertEqual(Expected, lists:flatten(Msg))
  490. end
  491. },
  492. {"supervisor reports with real error",
  493. fun() ->
  494. error_logger:error_report(supervisor_report, [{errorContext, france}, {offender, [{name, mini_steve}, {mfargs, {a, b, [c]}}, {pid, bleh}]}, {reason, {function_clause,[{crash,handle_info,[foo]}]}}, {supervisor, {local, steve}}]),
  495. custom_sleep(100),
  496. {_, _, Msg} = pop(),
  497. Expected = lists:flatten(io_lib:format("[error] ~w Supervisor steve had child mini_steve started with a:b(c) at bleh exit with reason no function clause matching crash:handle_info(foo) in context france", [self()])),
  498. ?assertEqual(Expected, lists:flatten(Msg))
  499. end
  500. },
  501. {"supervisor_bridge reports",
  502. fun() ->
  503. error_logger:error_report(supervisor_report, [{errorContext, france}, {offender, [{mod, mini_steve}, {pid, bleh}]}, {reason, fired}, {supervisor, {local, steve}}]),
  504. custom_sleep(100),
  505. {_, _, Msg} = pop(),
  506. Expected = lists:flatten(io_lib:format("[error] ~w Supervisor steve had child at module mini_steve at bleh exit with reason fired in context france", [self()])),
  507. ?assertEqual(Expected, lists:flatten(Msg))
  508. end
  509. },
  510. {"application progress report",
  511. fun() ->
  512. error_logger:info_report(progress, [{application, foo}, {started_at, node()}]),
  513. custom_sleep(100),
  514. {_, _, Msg} = pop(),
  515. Expected = lists:flatten(io_lib:format("[info] ~w Application foo started on node ~w", [self(), node()])),
  516. ?assertEqual(Expected, lists:flatten(Msg))
  517. end
  518. },
  519. {"supervisor progress report",
  520. fun() ->
  521. lager:set_loglevel(?MODULE, debug),
  522. error_logger:info_report(progress, [{supervisor, {local, foo}}, {started, [{mfargs, {foo, bar, 1}}, {pid, baz}]}]),
  523. custom_sleep(100),
  524. {_, _, Msg} = pop(),
  525. Expected = lists:flatten(io_lib:format("[debug] ~w Supervisor foo started foo:bar/1 at pid baz", [self()])),
  526. ?assertEqual(Expected, lists:flatten(Msg))
  527. end
  528. },
  529. {"crash report for emfile",
  530. fun() ->
  531. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {emfile, [{stack, trace, 1}]}, []}}], []]),
  532. custom_sleep(100),
  533. {_, _, Msg} = pop(),
  534. Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: maximum number of file descriptors exhausted, check ulimit -n", [self(), self()])),
  535. ?assertEqual(Expected, lists:flatten(Msg))
  536. end
  537. },
  538. {"crash report for system process limit",
  539. fun() ->
  540. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit, [{erlang, spawn, 1}]}, []}}], []]),
  541. custom_sleep(100),
  542. {_, _, Msg} = pop(),
  543. Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of processes exceeded", [self(), self()])),
  544. ?assertEqual(Expected, lists:flatten(Msg))
  545. end
  546. },
  547. {"crash report for system process limit2",
  548. fun() ->
  549. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit, [{erlang, spawn_opt, 1}]}, []}}], []]),
  550. custom_sleep(100),
  551. {_, _, Msg} = pop(),
  552. Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of processes exceeded", [self(), self()])),
  553. ?assertEqual(Expected, lists:flatten(Msg))
  554. end
  555. },
  556. {"crash report for system port limit",
  557. fun() ->
  558. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit, [{erlang, open_port, 1}]}, []}}], []]),
  559. custom_sleep(100),
  560. {_, _, Msg} = pop(),
  561. Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of ports exceeded", [self(), self()])),
  562. ?assertEqual(Expected, lists:flatten(Msg))
  563. end
  564. },
  565. {"crash report for system port limit",
  566. fun() ->
  567. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit, [{erlang, list_to_atom, 1}]}, []}}], []]),
  568. custom_sleep(100),
  569. {_, _, Msg} = pop(),
  570. Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: tried to create an atom larger than 255, or maximum atom count exceeded", [self(), self()])),
  571. ?assertEqual(Expected, lists:flatten(Msg))
  572. end
  573. },
  574. {"crash report for system ets table limit",
  575. fun() ->
  576. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit,[{ets,new,[segment_offsets,[ordered_set,public]]},{mi_segment,open_write,1},{mi_buffer_converter,handle_cast,2},{gen_server,handle_msg,5},{proc_lib,init_p_do_apply,3}]}, []}}], []]),
  577. custom_sleep(100),
  578. {_, _, Msg} = pop(),
  579. Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of ETS tables exceeded", [self(), self()])),
  580. ?assertEqual(Expected, lists:flatten(Msg))
  581. end
  582. },
  583. {"crash report for unknown system limit should be truncated at 500 characters",
  584. fun() ->
  585. error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit,[{wtf,boom,[string:copies("aaaa", 4096)]}]}, []}}], []]),
  586. custom_sleep(1000),
  587. {_, _, Msg} = pop(),
  588. ?assert(length(lists:flatten(Msg)) > 500),
  589. ?assert(length(lists:flatten(Msg)) < 700)
  590. end
  591. },
  592. {"messages should not be generated if they don't satisfy the threshold",
  593. fun() ->
  594. lager:set_loglevel(?MODULE, error),
  595. error_logger:info_report([hello, world]),
  596. custom_sleep(100),
  597. ?assertEqual(0, count()),
  598. ?assertEqual(0, count_ignored()),
  599. lager:set_loglevel(?MODULE, info),
  600. error_logger:info_report([hello, world]),
  601. custom_sleep(100),
  602. ?assertEqual(1, count()),
  603. ?assertEqual(0, count_ignored()),
  604. lager:set_loglevel(?MODULE, error),
  605. lager_mochiglobal:put(loglevel, ?DEBUG),
  606. error_logger:info_report([hello, world]),
  607. custom_sleep(100),
  608. ?assertEqual(1, count()),
  609. ?assertEqual(1, count_ignored())
  610. end
  611. }
  612. ]
  613. }.
  614. safe_format_test() ->
  615. ?assertEqual("foo bar", lists:flatten(lager:safe_format("~p ~p", [foo, bar], 1024))),
  616. ?assertEqual("FORMAT ERROR: \"~p ~p ~p\" [foo,bar]", lists:flatten(lager:safe_format("~p ~p ~p", [foo, bar], 1024))),
  617. ?assertEqual("FORMAT ERROR: \"~s\" [1]", lists:flatten(lager:safe_format("~s", [1], 1024))),
  618. ok.
  619. -endif.