|
@ -14,11 +14,6 @@ |
|
|
|
|
|
|
|
|
-behaviour(gen_emm). |
|
|
-behaviour(gen_emm). |
|
|
|
|
|
|
|
|
-ifdef(TEST). |
|
|
|
|
|
-include_lib("eunit/include/eunit.hrl"). |
|
|
|
|
|
-compile([{parse_transform, lager_transform}]). |
|
|
|
|
|
-endif. |
|
|
|
|
|
|
|
|
|
|
|
-export([configToId/1]). |
|
|
-export([configToId/1]). |
|
|
|
|
|
|
|
|
-export([ |
|
|
-export([ |
|
@ -297,717 +292,3 @@ closeFile(#state{fd = Fd} = State) -> |
|
|
_ = file:close(Fd), |
|
|
_ = file:close(Fd), |
|
|
State#state{fd = undefined} |
|
|
State#state{fd = undefined} |
|
|
end. |
|
|
end. |
|
|
|
|
|
|
|
|
-ifdef(TEST). |
|
|
|
|
|
|
|
|
|
|
|
get_loglevel_test() -> |
|
|
|
|
|
{ok, Level, _} = handleCall(mGetLogLevel, |
|
|
|
|
|
#state{fileName = "bar", level = rumUtil:configToMask(info), fd = 0, inode = 0, ctime = undefined}), |
|
|
|
|
|
?assertEqual(Level, rumUtil:configToMask(info)), |
|
|
|
|
|
{ok, Level2, _} = handleCall(mGetLogLevel, |
|
|
|
|
|
#state{fileName = "foo", level = rumUtil:configToMask(warning), fd = 0, inode = 0, ctime = undefined}), |
|
|
|
|
|
?assertEqual(Level2, rumUtil:configToMask(warning)). |
|
|
|
|
|
|
|
|
|
|
|
rotation_test_() -> |
|
|
|
|
|
{foreach, |
|
|
|
|
|
fun() -> |
|
|
|
|
|
SyncLevel = rumUtil:configToMask(?RumDefSyncLevel), |
|
|
|
|
|
SyncSize = ?RumDefSyncSize, |
|
|
|
|
|
SyncInterval = ?RumDefSyncInterval, |
|
|
|
|
|
Rotator = ?RumDefRotateMod, |
|
|
|
|
|
CheckInterval = 0, %% hard to test delayed mode |
|
|
|
|
|
{ok, TestDir} = rumUtil:create_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
{OsType, _} = os:type(), |
|
|
|
|
|
#state{fileName = TestLog, |
|
|
|
|
|
level = ?DEBUG, |
|
|
|
|
|
syncOn = SyncLevel, |
|
|
|
|
|
syncSize = SyncSize, |
|
|
|
|
|
syncInterval = SyncInterval, |
|
|
|
|
|
checkInterval = CheckInterval, |
|
|
|
|
|
rotator = Rotator, |
|
|
|
|
|
osType = OsType} |
|
|
|
|
|
end, |
|
|
|
|
|
fun(#state{}) -> |
|
|
|
|
|
ok = rumUtil:delete_test_dir() |
|
|
|
|
|
end, [ |
|
|
|
|
|
fun(DefaultState = #state{fileName = TestLog, osType = OsType, syncSize = SyncSize, syncInterval = SyncInterval, rotator = Rotator}) -> |
|
|
|
|
|
{"External rotation should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
case OsType of |
|
|
|
|
|
win32 -> |
|
|
|
|
|
% Note: test is skipped on win32 due to the fact that a file can't be deleted or renamed |
|
|
|
|
|
% while a process has an open file handle referencing it |
|
|
|
|
|
ok; |
|
|
|
|
|
_ -> |
|
|
|
|
|
{ok, FD, Inode, Ctime, _Size} = Rotator:openLogfile(TestLog, {SyncSize, SyncInterval}), |
|
|
|
|
|
State0 = DefaultState#state{fd = FD, inode = Inode, ctime = Ctime}, |
|
|
|
|
|
State1 = writeLog(State0, os:timestamp(), ?DEBUG, "hello world"), |
|
|
|
|
|
?assertMatch(#state{fileName = TestLog, level = ?DEBUG, fd = FD, inode = Inode, ctime = Ctime}, State1), |
|
|
|
|
|
?assertEqual(ok, file:delete(TestLog)), |
|
|
|
|
|
State2 = writeLog(State0, os:timestamp(), ?DEBUG, "hello world"), |
|
|
|
|
|
%% assert file has changed |
|
|
|
|
|
ExpState1 = #state{fileName = TestLog, level = ?DEBUG, fd = FD, inode = Inode, ctime = Ctime}, |
|
|
|
|
|
?assertNotEqual(ExpState1, State2), |
|
|
|
|
|
?assertMatch(#state{fileName = TestLog, level = ?DEBUG}, State2), |
|
|
|
|
|
?assertEqual(ok, file:rename(TestLog, TestLog ++ ".1")), |
|
|
|
|
|
State3 = writeLog(State2, os:timestamp(), ?DEBUG, "hello world"), |
|
|
|
|
|
%% assert file has changed |
|
|
|
|
|
?assertNotEqual(State3, State2), |
|
|
|
|
|
?assertMatch(#state{fileName = TestLog, level = ?DEBUG}, State3), |
|
|
|
|
|
ok |
|
|
|
|
|
end |
|
|
|
|
|
end} |
|
|
|
|
|
end, |
|
|
|
|
|
fun(DefaultState = #state{fileName = TestLog, syncSize = SyncSize, syncInterval = SyncInterval, rotator = Rotator}) -> |
|
|
|
|
|
{"Internal rotation and delayed write", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
TestLog0 = TestLog ++ ".0", |
|
|
|
|
|
CheckInterval = 3000, % 3 sec |
|
|
|
|
|
RotationSize = 15, |
|
|
|
|
|
PreviousCheck = os:timestamp(), |
|
|
|
|
|
|
|
|
|
|
|
{ok, FD, Inode, Ctime, _Size} = Rotator:openLogfile(TestLog, {SyncSize, SyncInterval}), |
|
|
|
|
|
State0 = DefaultState#state{ |
|
|
|
|
|
fd = FD, inode = Inode, ctime = Ctime, size = RotationSize, |
|
|
|
|
|
checkInterval = CheckInterval, lastCheck = PreviousCheck}, |
|
|
|
|
|
|
|
|
|
|
|
%% new message within check interval with sync_on level |
|
|
|
|
|
Msg1Timestamp = add_secs(PreviousCheck, 1), |
|
|
|
|
|
State1 = writeLog(State0, Msg1Timestamp, ?ERROR, "big big message 1"), |
|
|
|
|
|
?assertEqual(State0, State1), |
|
|
|
|
|
|
|
|
|
|
|
%% new message within check interval under sync_on level |
|
|
|
|
|
%% not written to disk yet |
|
|
|
|
|
Msg2Timestamp = add_secs(PreviousCheck, 2), |
|
|
|
|
|
State2 = writeLog(State1, Msg2Timestamp, ?DEBUG, "buffered message 2"), |
|
|
|
|
|
?assertEqual(State0, State2), |
|
|
|
|
|
|
|
|
|
|
|
% Note: we must ensure at least one second (DEFAULT_SYNC_INTERVAL) has passed |
|
|
|
|
|
% for message 1 and 2 to be written to disk |
|
|
|
|
|
ElapsedMs = timer:now_diff(os:timestamp(), PreviousCheck) div 1000, |
|
|
|
|
|
case ElapsedMs > SyncInterval of |
|
|
|
|
|
true -> |
|
|
|
|
|
ok; |
|
|
|
|
|
_ -> |
|
|
|
|
|
S = SyncInterval - ElapsedMs, |
|
|
|
|
|
timer:sleep(S) |
|
|
|
|
|
end, |
|
|
|
|
|
|
|
|
|
|
|
%% although file size is big enough... |
|
|
|
|
|
{ok, FInfo} = file:read_file_info(TestLog, [raw]), |
|
|
|
|
|
?assert(RotationSize < FInfo#file_info.size), |
|
|
|
|
|
%% ...no rotation yet |
|
|
|
|
|
?assertEqual(PreviousCheck, State2#state.lastCheck), |
|
|
|
|
|
?assertNot(filelib:is_regular(TestLog0)), |
|
|
|
|
|
|
|
|
|
|
|
%% new message after check interval |
|
|
|
|
|
Msg3Timestamp = add_secs(PreviousCheck, 4), |
|
|
|
|
|
_State3 = writeLog(State2, Msg3Timestamp, ?DEBUG, "message 3"), |
|
|
|
|
|
|
|
|
|
|
|
%% rotation happened |
|
|
|
|
|
?assert(filelib:is_regular(TestLog0)), |
|
|
|
|
|
|
|
|
|
|
|
{ok, Bin1} = file:read_file(TestLog0), |
|
|
|
|
|
{ok, Bin2} = file:read_file(TestLog), |
|
|
|
|
|
%% message 1-2 written to file |
|
|
|
|
|
?assertEqual(<<"big big message 1buffered message 2">>, Bin1), |
|
|
|
|
|
%% message 3 buffered, not yet written to file |
|
|
|
|
|
?assertEqual(<<"">>, Bin2), |
|
|
|
|
|
ok |
|
|
|
|
|
end} |
|
|
|
|
|
end |
|
|
|
|
|
]}. |
|
|
|
|
|
|
|
|
|
|
|
add_secs({Mega, Secs, Micro}, Add) -> |
|
|
|
|
|
NewSecs = Secs + Add, |
|
|
|
|
|
{Mega + NewSecs div 10000000, NewSecs rem 10000000, Micro}. |
|
|
|
|
|
|
|
|
|
|
|
filesystem_test_() -> |
|
|
|
|
|
{foreach, |
|
|
|
|
|
fun() -> |
|
|
|
|
|
ok = error_logger:tty(false), |
|
|
|
|
|
ok = rumUtil:safe_application_load(lager), |
|
|
|
|
|
ok = application:set_env(lager, handlers, [{lager_test_backend, info}]), |
|
|
|
|
|
ok = application:set_env(lager, errLoggerRedirect, false), |
|
|
|
|
|
ok = application:set_env(lager, asyncThreshold, undefined), |
|
|
|
|
|
{ok, _TestDir} = rumUtil:create_test_dir(), |
|
|
|
|
|
ok = eRum:start(), |
|
|
|
|
|
%% race condition where lager logs its own start up |
|
|
|
|
|
%% makes several tests fail. See test/lager_test_backend |
|
|
|
|
|
%% around line 800 for more information. |
|
|
|
|
|
ok = timer:sleep(5), |
|
|
|
|
|
ok = lager_test_backend:flush() |
|
|
|
|
|
end, |
|
|
|
|
|
fun(_) -> |
|
|
|
|
|
ok = application:stop(lager), |
|
|
|
|
|
ok = application:stop(goldrush), |
|
|
|
|
|
ok = error_logger:tty(true), |
|
|
|
|
|
ok = rumUtil:delete_test_dir() |
|
|
|
|
|
end, [ |
|
|
|
|
|
{"under normal circumstances, file should be opened", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{TestLog, info}, {lager_default_formatter}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Pid = pid_to_list(self()), |
|
|
|
|
|
?assertMatch([_, _, "[error]", Pid, "Test message\n"], |
|
|
|
|
|
re:split(Bin, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"don't choke on unicode", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{TestLog, info}, {lager_default_formatter}]), |
|
|
|
|
|
eRum:log(error, self(), "~ts", [[20013, 25991, 27979, 35797]]), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Pid = pid_to_list(self()), |
|
|
|
|
|
?assertMatch([_, _, "[error]", Pid, |
|
|
|
|
|
[228, 184, 173, 230, 150, 135, 230, 181, 139, 232, 175, 149, $\n]], |
|
|
|
|
|
re:split(Bin, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"don't choke on latin-1", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
%% XXX if this test fails, check that this file is encoded latin-1, not utf-8! |
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{TestLog, info}, {lager_default_formatter}]), |
|
|
|
|
|
eRum:log(error, self(), "~ts", [[76, 198, 221, 206, 78, $-, 239]]), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Pid = pid_to_list(self()), |
|
|
|
|
|
Res = re:split(Bin, " ", [{return, list}, {parts, 5}]), |
|
|
|
|
|
?assertMatch([_, _, "[error]", Pid, |
|
|
|
|
|
[76, 195, 134, 195, 157, 195, 142, 78, 45, 195, 175, $\n]], Res) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"file can't be opened on startup triggers an error message", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
?assertEqual(ok, rumUtil:safe_write_file(TestLog, [])), |
|
|
|
|
|
|
|
|
|
|
|
{ok, FInfo0} = file:read_file_info(TestLog, [raw]), |
|
|
|
|
|
FInfo1 = FInfo0#file_info{mode = 0}, |
|
|
|
|
|
?assertEqual(ok, file:write_file_info(TestLog, FInfo1)), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
{TestLog, info, 10 * 1024 * 1024, "$D0", 5}), |
|
|
|
|
|
|
|
|
|
|
|
% Note: required on win32, do this early to prevent subsequent failures |
|
|
|
|
|
% from preventing cleanup |
|
|
|
|
|
?assertEqual(ok, file:write_file_info(TestLog, FInfo0)), |
|
|
|
|
|
|
|
|
|
|
|
?assertEqual(1, lager_test_backend:count()), |
|
|
|
|
|
{_Level, _Time, Message, _Metadata} = lager_test_backend:pop(), |
|
|
|
|
|
MessageFlat = lists:flatten(Message), |
|
|
|
|
|
?assertEqual( |
|
|
|
|
|
"Failed to open log file " ++ TestLog ++ " with error permission denied", |
|
|
|
|
|
MessageFlat) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"file that becomes unavailable at runtime should trigger an error message", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
case os:type() of |
|
|
|
|
|
{win32, _} -> |
|
|
|
|
|
% Note: test is skipped on win32 due to the fact that a file can't be |
|
|
|
|
|
% deleted or renamed while a process has an open file handle referencing it |
|
|
|
|
|
ok; |
|
|
|
|
|
_ -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{file, TestLog}, {level, info}, {check_interval, 0}]), |
|
|
|
|
|
?assertEqual(0, lager_test_backend:count()), |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
?assertEqual(1, lager_test_backend:count()), |
|
|
|
|
|
?assertEqual(ok, file:delete(TestLog)), |
|
|
|
|
|
?assertEqual(ok, rumUtil:safe_write_file(TestLog, "")), |
|
|
|
|
|
{ok, FInfo0} = file:read_file_info(TestLog, [raw]), |
|
|
|
|
|
FInfo1 = FInfo0#file_info{mode = 0}, |
|
|
|
|
|
?assertEqual(ok, file:write_file_info(TestLog, FInfo1)), |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
lager_test_backend:pop(), |
|
|
|
|
|
lager_test_backend:pop(), |
|
|
|
|
|
{_Level, _Time, Message, _Metadata} = lager_test_backend:pop(), |
|
|
|
|
|
?assertEqual( |
|
|
|
|
|
"Failed to reopen log file " ++ TestLog ++ " with error permission denied", |
|
|
|
|
|
lists:flatten(Message)) |
|
|
|
|
|
end |
|
|
|
|
|
end}, |
|
|
|
|
|
{"unavailable files that are fixed at runtime should start having log messages written", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
?assertEqual(ok, rumUtil:safe_write_file(TestLog, [])), |
|
|
|
|
|
|
|
|
|
|
|
{ok, FInfo} = file:read_file_info(TestLog, [raw]), |
|
|
|
|
|
OldPerms = FInfo#file_info.mode, |
|
|
|
|
|
?assertEqual(ok, file:write_file_info(TestLog, FInfo#file_info{mode = 0})), |
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{file, TestLog}, {check_interval, 0}]), |
|
|
|
|
|
?assertEqual(1, lager_test_backend:count()), |
|
|
|
|
|
{_Level, _Time, Message, _Metadata} = lager_test_backend:pop(), |
|
|
|
|
|
?assertEqual( |
|
|
|
|
|
"Failed to open log file " ++ TestLog ++ " with error permission denied", |
|
|
|
|
|
lists:flatten(Message)), |
|
|
|
|
|
?assertEqual(ok, file:write_file_info(TestLog, FInfo#file_info{mode = OldPerms})), |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Pid = pid_to_list(self()), |
|
|
|
|
|
?assertMatch([_, _, "[error]", Pid, "Test message\n"], |
|
|
|
|
|
re:split(Bin, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"external logfile rotation/deletion should be handled", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
case os:type() of |
|
|
|
|
|
{win32, _} -> |
|
|
|
|
|
% Note: test is skipped on win32 due to the fact that a file can't be deleted or renamed |
|
|
|
|
|
% while a process has an open file handle referencing it |
|
|
|
|
|
ok; |
|
|
|
|
|
_ -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
TestLog0 = TestLog ++ ".0", |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{file, TestLog}, {level, info}, {check_interval, 0}]), |
|
|
|
|
|
?assertEqual(0, lager_test_backend:count()), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
?assertEqual(1, lager_test_backend:count()), |
|
|
|
|
|
?assertEqual(ok, file:delete(TestLog)), |
|
|
|
|
|
?assertEqual(ok, rumUtil:safe_write_file(TestLog, "")), |
|
|
|
|
|
eRum:log(error, self(), "Test message2"), |
|
|
|
|
|
?assertEqual(2, lager_test_backend:count()), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Pid = pid_to_list(self()), |
|
|
|
|
|
?assertMatch([_, _, "[error]", Pid, "Test message2\n"], |
|
|
|
|
|
re:split(Bin, " ", [{return, list}, {parts, 5}])), |
|
|
|
|
|
?assertEqual(ok, file:rename(TestLog, TestLog0)), |
|
|
|
|
|
eRum:log(error, self(), "Test message3"), |
|
|
|
|
|
?assertEqual(3, lager_test_backend:count()), |
|
|
|
|
|
{ok, Bin2} = file:read_file(TestLog), |
|
|
|
|
|
?assertMatch([_, _, "[error]", Pid, "Test message3\n"], |
|
|
|
|
|
re:split(Bin2, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end |
|
|
|
|
|
end}, |
|
|
|
|
|
{"internal size rotation should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
TestLog0 = TestLog ++ ".0", |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{file, TestLog}, {level, info}, {check_interval, 0}, {size, 10}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
?assert(filelib:is_regular(TestLog0)) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"internal time rotation should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
TestLog0 = TestLog ++ ".0", |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{file, TestLog}, {level, info}, {check_interval, 1000}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
whereis(rumEvent) ! {mRotate, TestLog}, |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
?assert(filelib:is_regular(TestLog0)) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"rotation call should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
TestLog0 = TestLog ++ ".0", |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, {lager_file_backend, TestLog}, |
|
|
|
|
|
[{file, TestLog}, {level, info}, {check_interval, 1000}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
gen_event:call(rumEvent, {lager_file_backend, TestLog}, mRotate, infinity), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
?assert(filelib:is_regular(TestLog0)) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"sync_on option should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, [{file, TestLog}, |
|
|
|
|
|
{level, info}, {sync_on, "=info"}, {check_interval, 5000}, {sync_interval, 5000}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
?assertEqual({ok, <<>>}, file:read_file(TestLog)), |
|
|
|
|
|
eRum:log(info, self(), "Test message1"), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
?assert(<<>> /= Bin) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"sync_on none option should work (also tests sync_interval)", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, [{file, TestLog}, |
|
|
|
|
|
{level, info}, {sync_on, "none"}, {check_interval, 5000}, {sync_interval, 1000}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
eRum:log(error, self(), "Test message1"), |
|
|
|
|
|
?assertEqual({ok, <<>>}, file:read_file(TestLog)), |
|
|
|
|
|
eRum:log(info, self(), "Test message1"), |
|
|
|
|
|
?assertEqual({ok, <<>>}, file:read_file(TestLog)), |
|
|
|
|
|
timer:sleep(2000), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
?assert(<<>> /= Bin) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"sync_size option should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, [{file, TestLog}, {level, info}, |
|
|
|
|
|
{sync_on, "none"}, {check_interval, 5001}, {sync_size, 640}, {sync_interval, 5001}]), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
?assertEqual({ok, <<>>}, file:read_file(TestLog)), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
?assertEqual({ok, <<>>}, file:read_file(TestLog)), |
|
|
|
|
|
%% now we've written enough bytes |
|
|
|
|
|
eRum:log(error, self(), "Test messageis64bytes"), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
?assert(<<>> /= Bin) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"runtime level changes", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, {lager_file_backend, TestLog}, {TestLog, info}), |
|
|
|
|
|
?assertEqual(0, lager_test_backend:count()), |
|
|
|
|
|
eRum:log(info, self(), "Test message1"), |
|
|
|
|
|
eRum:log(error, self(), "Test message2"), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Lines = length(re:split(Bin, "\n", [{return, list}, trim])), |
|
|
|
|
|
?assertEqual(Lines, 2), |
|
|
|
|
|
?assertEqual(ok, eRum:setLogLevel(lager_file_backend, TestLog, warning)), |
|
|
|
|
|
eRum:log(info, self(), "Test message3"), %% this won't get logged |
|
|
|
|
|
eRum:log(error, self(), "Test message4"), |
|
|
|
|
|
{ok, Bin2} = file:read_file(TestLog), |
|
|
|
|
|
Lines2 = length(re:split(Bin2, "\n", [{return, list}, trim])), |
|
|
|
|
|
?assertEqual(Lines2, 3) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"invalid runtime level changes", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
TestLog3 = filename:join(TestDir, "test3.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{TestLog, info, 10 * 1024 * 1024, "$D0", 5}, {lager_default_formatter}]), |
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, {TestLog3, info}), |
|
|
|
|
|
?assertEqual({error, bad_module}, eRum:setLogLevel(lager_file_backend, TestLog, warning)) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"tracing should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, {TestLog, critical}), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
?assertEqual({ok, <<>>}, file:read_file(TestLog)), |
|
|
|
|
|
{Level, _} = rumConfig:get({rumEvent, loglevel}), |
|
|
|
|
|
rumConfig:set({rumEvent, loglevel}, {Level, |
|
|
|
|
|
[{[{module, ?MODULE}], ?DEBUG, {lager_file_backend, TestLog}}]}), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
timer:sleep(1000), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
?assertMatch([_, _, "[error]", _, "Test message\n"], |
|
|
|
|
|
re:split(Bin, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"tracing should not duplicate messages", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
case os:type() of |
|
|
|
|
|
{win32, _} -> |
|
|
|
|
|
% Note: test is skipped on win32 due to the fact that a file can't be |
|
|
|
|
|
% deleted or renamed while a process has an open file handle referencing it |
|
|
|
|
|
ok; |
|
|
|
|
|
_ -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
|
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{file, TestLog}, {level, critical}, {check_interval, always}]), |
|
|
|
|
|
timer:sleep(500), |
|
|
|
|
|
eRum:critical("Test message"), |
|
|
|
|
|
{ok, Bin1} = file:read_file(TestLog), |
|
|
|
|
|
?assertMatch([_, _, "[critical]", _, "Test message\n"], |
|
|
|
|
|
re:split(Bin1, " ", [{return, list}, {parts, 5}])), |
|
|
|
|
|
?assertEqual(ok, file:delete(TestLog)), |
|
|
|
|
|
{Level, _} = rumConfig:get({rumEvent, loglevel}), |
|
|
|
|
|
rumConfig:set({rumEvent, loglevel}, |
|
|
|
|
|
{Level, [{[{module, ?MODULE}], ?DEBUG, {lager_file_backend, TestLog}}]}), |
|
|
|
|
|
eRum:critical("Test message"), |
|
|
|
|
|
{ok, Bin2} = file:read_file(TestLog), |
|
|
|
|
|
?assertMatch([_, _, "[critical]", _, "Test message\n"], |
|
|
|
|
|
re:split(Bin2, " ", [{return, list}, {parts, 5}])), |
|
|
|
|
|
?assertEqual(ok, file:delete(TestLog)), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
{ok, Bin3} = file:read_file(TestLog), |
|
|
|
|
|
?assertMatch([_, _, "[error]", _, "Test message\n"], |
|
|
|
|
|
re:split(Bin3, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end |
|
|
|
|
|
end}, |
|
|
|
|
|
{"tracing to a dedicated file should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "foo.log"), |
|
|
|
|
|
|
|
|
|
|
|
{ok, _} = eRum:trace_file(TestLog, [{module, ?MODULE}]), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
%% not eligible for trace |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
{ok, Bin3} = file:read_file(TestLog), |
|
|
|
|
|
?assertMatch([_, _, "[error]", _, "Test message\n"], |
|
|
|
|
|
re:split(Bin3, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"tracing to a dedicated file should work even if root_log is set", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
LogName = "foo.log", |
|
|
|
|
|
LogPath = filename:join(TestDir, LogName), |
|
|
|
|
|
|
|
|
|
|
|
application:set_env(lager, logRoot, TestDir), |
|
|
|
|
|
{ok, _} = eRum:trace_file(LogName, [{module, ?MODULE}]), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
%% not eligible for trace |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
{ok, Bin3} = file:read_file(LogPath), |
|
|
|
|
|
application:unset_env(lager, logRoot), |
|
|
|
|
|
?assertMatch([_, _, "[error]", _, "Test message\n"], |
|
|
|
|
|
re:split(Bin3, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"tracing with options should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "foo.log"), |
|
|
|
|
|
TestLog0 = TestLog ++ ".0", |
|
|
|
|
|
|
|
|
|
|
|
{ok, _} = eRum:trace_file(TestLog, [{module, ?MODULE}], |
|
|
|
|
|
[{size, 20}, {check_interval, 1}]), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
?assertNot(filelib:is_regular(TestLog0)), |
|
|
|
|
|
%% rotation is sensitive to intervals between |
|
|
|
|
|
%% writes so we sleep to exceed the 1 |
|
|
|
|
|
%% millisecond interval specified by |
|
|
|
|
|
%% check_interval above |
|
|
|
|
|
timer:sleep(2), |
|
|
|
|
|
eRum:error("Test message"), |
|
|
|
|
|
timer:sleep(10), |
|
|
|
|
|
?assert(filelib:is_regular(TestLog0)) |
|
|
|
|
|
end}, |
|
|
|
|
|
{"no silent hwm drops", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
MsgCount = 15, |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
TestLog = filename:join(TestDir, "test.log"), |
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, [{file, TestLog}, {level, info}, |
|
|
|
|
|
{high_water_mark, 5}, {flushQueue, false}, {sync_on, "=warning"}]), |
|
|
|
|
|
{_, _, MS} = os:timestamp(), |
|
|
|
|
|
% start close to the beginning of a new second |
|
|
|
|
|
?assertEqual(ok, timer:sleep((1000000 - MS) div 1000 + 1)), |
|
|
|
|
|
[eRum:log(info, self(), "Foo ~p", [K]) || K <- lists:seq(1, MsgCount)], |
|
|
|
|
|
?assertEqual(MsgCount, lager_test_backend:count()), |
|
|
|
|
|
% Note: bumped from 1000 to 1250 to ensure delayed write flushes to disk |
|
|
|
|
|
?assertEqual(ok, timer:sleep(1250)), |
|
|
|
|
|
{ok, Bin} = file:read_file(TestLog), |
|
|
|
|
|
Last = lists:last(re:split(Bin, "\n", [{return, list}, trim])), |
|
|
|
|
|
?assertMatch([_, _, _, _, "lager_file_backend dropped 10 messages in the last second that exceeded the limit of 5 messages/sec"], |
|
|
|
|
|
re:split(Last, " ", [{return, list}, {parts, 5}])) |
|
|
|
|
|
end} |
|
|
|
|
|
]}. |
|
|
|
|
|
|
|
|
|
|
|
trace_files_test_() -> |
|
|
|
|
|
{foreach, |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
Log = filename:join(TestDir, "test.log"), |
|
|
|
|
|
Debug = filename:join(TestDir, "debug.log"), |
|
|
|
|
|
Events = filename:join(TestDir, "events.log"), |
|
|
|
|
|
|
|
|
|
|
|
ok = error_logger:tty(false), |
|
|
|
|
|
ok = rumUtil:safe_application_load(lager), |
|
|
|
|
|
ok = application:set_env(lager, handlers, [ |
|
|
|
|
|
{lager_file_backend, [ |
|
|
|
|
|
{file, Log}, |
|
|
|
|
|
{level, error}, |
|
|
|
|
|
{formatter, lager_default_formatter}, |
|
|
|
|
|
{formatter_config, [message, "\n"]} |
|
|
|
|
|
]} |
|
|
|
|
|
]), |
|
|
|
|
|
ok = application:set_env(lager, traces, [ |
|
|
|
|
|
{ % get default level of debug |
|
|
|
|
|
{lager_file_backend, Debug}, [{module, ?MODULE}] |
|
|
|
|
|
}, |
|
|
|
|
|
{ % Handler Filters Level |
|
|
|
|
|
{lager_file_backend, Events}, [{module, ?MODULE}], notice |
|
|
|
|
|
} |
|
|
|
|
|
]), |
|
|
|
|
|
ok = application:set_env(lager, asyncThreshold, undefined), |
|
|
|
|
|
ok = eRum:start(), |
|
|
|
|
|
{Log, Debug, Events} |
|
|
|
|
|
end, |
|
|
|
|
|
fun({_, _, _}) -> |
|
|
|
|
|
catch ets:delete(lager_config), |
|
|
|
|
|
ok = application:unset_env(lager, traces), |
|
|
|
|
|
ok = application:stop(lager), |
|
|
|
|
|
ok = rumUtil:delete_test_dir(), |
|
|
|
|
|
ok = error_logger:tty(true) |
|
|
|
|
|
end, [ |
|
|
|
|
|
fun({Log, Debug, Events}) -> |
|
|
|
|
|
{"a trace using file backend set up in configuration should work", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
eRum:error("trace test error message"), |
|
|
|
|
|
eRum:info("info message"), |
|
|
|
|
|
%% not eligible for trace |
|
|
|
|
|
eRum:log(error, self(), "Not trace test message"), |
|
|
|
|
|
{ok, BinInfo} = file:read_file(Events), |
|
|
|
|
|
?assertMatch([_, _, "[error]", _, "trace test error message\n"], |
|
|
|
|
|
re:split(BinInfo, " ", [{return, list}, {parts, 5}])), |
|
|
|
|
|
?assert(filelib:is_regular(Log)), |
|
|
|
|
|
{ok, BinInfo2} = file:read_file(Log), |
|
|
|
|
|
?assertMatch(["trace test error message", "Not trace test message\n"], |
|
|
|
|
|
re:split(BinInfo2, "\n", [{return, list}, {parts, 2}])), |
|
|
|
|
|
?assert(filelib:is_regular(Debug)), |
|
|
|
|
|
%% XXX Aughhhh, wish I could force this to flush somehow... |
|
|
|
|
|
% should take about 1 second, try for 3 ... |
|
|
|
|
|
?assertEqual(2, count_lines_until(2, add_secs(os:timestamp(), 3), Debug, 0)) |
|
|
|
|
|
end} |
|
|
|
|
|
end |
|
|
|
|
|
]}. |
|
|
|
|
|
|
|
|
|
|
|
count_lines_until(Lines, Timeout, File, Last) -> |
|
|
|
|
|
case timer:now_diff(Timeout, os:timestamp()) > 0 of |
|
|
|
|
|
true -> |
|
|
|
|
|
timer:sleep(333), |
|
|
|
|
|
{ok, Bin} = file:read_file(File), |
|
|
|
|
|
case erlang:length(re:split(Bin, "\n", [{return, list}, trim])) of |
|
|
|
|
|
Count when Count < Lines -> |
|
|
|
|
|
count_lines_until(Lines, Timeout, File, Count); |
|
|
|
|
|
Count -> |
|
|
|
|
|
Count |
|
|
|
|
|
end; |
|
|
|
|
|
_ -> |
|
|
|
|
|
Last |
|
|
|
|
|
end. |
|
|
|
|
|
|
|
|
|
|
|
formatting_test_() -> |
|
|
|
|
|
{foreach, |
|
|
|
|
|
fun() -> |
|
|
|
|
|
{ok, TestDir} = rumUtil:get_test_dir(), |
|
|
|
|
|
Log1 = filename:join(TestDir, "test.log"), |
|
|
|
|
|
Log2 = filename:join(TestDir, "test2.log"), |
|
|
|
|
|
?assertEqual(ok, rumUtil:safe_write_file(Log1, [])), |
|
|
|
|
|
?assertEqual(ok, rumUtil:safe_write_file(Log2, [])), |
|
|
|
|
|
ok = error_logger:tty(false), |
|
|
|
|
|
ok = rumUtil:safe_application_load(lager), |
|
|
|
|
|
ok = application:set_env(lager, handlers, [{lager_test_backend, info}]), |
|
|
|
|
|
ok = application:set_env(lager, errLoggerRedirect, false), |
|
|
|
|
|
ok = eRum:start(), |
|
|
|
|
|
%% same race condition issue |
|
|
|
|
|
ok = timer:sleep(5), |
|
|
|
|
|
{ok, Log1, Log2} |
|
|
|
|
|
end, |
|
|
|
|
|
fun({ok, _, _}) -> |
|
|
|
|
|
ok = application:stop(lager), |
|
|
|
|
|
ok = application:stop(goldrush), |
|
|
|
|
|
ok = rumUtil:delete_test_dir(), |
|
|
|
|
|
ok = error_logger:tty(true) |
|
|
|
|
|
end, [ |
|
|
|
|
|
fun({ok, Log1, Log2}) -> |
|
|
|
|
|
{"Should have two log files, the second prefixed with 2>", |
|
|
|
|
|
fun() -> |
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{Log1, debug}, {lager_default_formatter, ["[", severity, "] ", message, "\n"]}]), |
|
|
|
|
|
gen_event:add_handler(rumEvent, lager_file_backend, |
|
|
|
|
|
[{Log2, debug}, {lager_default_formatter, ["2> [", severity, "] ", message, "\n"]}]), |
|
|
|
|
|
eRum:log(error, self(), "Test message"), |
|
|
|
|
|
?assertMatch({ok, <<"[error] Test message\n">>}, file:read_file(Log1)), |
|
|
|
|
|
?assertMatch({ok, <<"2> [error] Test message\n">>}, file:read_file(Log2)) |
|
|
|
|
|
end} |
|
|
|
|
|
end |
|
|
|
|
|
]}. |
|
|
|
|
|
|
|
|
|
|
|
config_validation_test_() -> |
|
|
|
|
|
[ |
|
|
|
|
|
{"missing file", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{level, info}, {size, 10}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad level", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {level, blah}, {size, 10}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad size", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {size, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad count", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {count, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad high water mark", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {high_water_mark, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad date", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {date, "midnight"}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"blank date is ok", |
|
|
|
|
|
?_assertMatch([_ | _], |
|
|
|
|
|
checkOpts([{file, "test.log"}, {date, ""}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad sync_interval", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {sync_interval, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad sync_size", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {sync_size, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad check_interval", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {check_interval, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad sync_on level", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {sync_on, infinity}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad formatter module", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {formatter, "io:format"}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"bad formatter config", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {formatter_config, blah}])) |
|
|
|
|
|
}, |
|
|
|
|
|
{"unknown option", |
|
|
|
|
|
?_assertEqual(false, |
|
|
|
|
|
checkOpts([{file, "test.log"}, {rhubarb, spicy}])) |
|
|
|
|
|
} |
|
|
|
|
|
]. |
|
|
|
|
|
|
|
|
|
|
|
-endif. |
|
|
|