diff options
Diffstat (limited to 'lib/kernel/test/wrap_log_reader_SUITE.erl')
-rw-r--r-- | lib/kernel/test/wrap_log_reader_SUITE.erl | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl new file mode 100644 index 0000000000..1d1570fbd9 --- /dev/null +++ b/lib/kernel/test/wrap_log_reader_SUITE.erl @@ -0,0 +1,550 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(wrap_log_reader_SUITE). + +%-define(debug, true). + +-ifdef(debug). +-define(format(S, A), io:format(S, A)). +-define(line, put(line, ?LINE), ). +-define(privdir(_), "./disk_log_SUITE_priv"). +-define(config(X,Y), foo). +-define(t,test_server). +-else. +-include("test_server.hrl"). +-define(format(S, A), ok). +-define(privdir(Conf), ?config(priv_dir, Conf)). +-endif. + +-export([all/1, + no_file/1, + one/1, one_empty/1, one_filled/1, + two/1, two_filled/1, + four/1, four_filled/1, + wrap/1, wrap_filled/1, + wrapping/1, + external/1, + error/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +all(suite) -> + [no_file, one, two, four, wrap, wrapping, external, error]. + +init_per_testcase(Func, Config) when atom(Func), list(Config) -> + Dog=?t:timetrap(?t:seconds(60)), + [{watchdog, Dog} | Config]. + +fin_per_testcase(_Func, _Config) -> + Dog=?config(watchdog, _Config), + ?t:timetrap_cancel(Dog). + +no_file(suite) -> []; +no_file(doc) -> ["No log file exists"]; +no_file(Conf) when list(Conf) -> + ?line code:add_path(?config(data_dir,Conf)), + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + wlt ! {open, self(), File}, + ?line rec({error, {index_file_not_found, File}}, ?LINE), + wlt ! {open, self(), File, 1}, + ?line rec({error, {index_file_not_found, File}}, ?LINE), + wlt ! {open, self(), File, 4}, + ?line rec({error, {index_file_not_found, File}}, ?LINE), + + stop(), + delete_files(File), + ok. + +one(suite) -> [one_empty, one_filled]; +one(doc) -> ["One index file"]. + +one_empty(suite) -> []; +one_empty(doc) -> ["One empty index file"]; +one_empty(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + ?line open(sune, File, ?LINE), + %% open + ?line do_chunk([{open,File}, eof], wlt, ?LINE), + ?line do_chunk([{open,File,1}, eof], wlt, ?LINE), + wlt ! {open, self(), File, 2}, + ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), + ?line close(sune), + + %% closed + ?line do_chunk([{open,File}, eof], wlt, ?LINE), + ?line do_chunk([{open,File,1}, eof], wlt, ?LINE), + wlt ! {open, self(), File, 2}, + ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), + + stop(), + delete_files(File), + ok. + +one_filled(suite) -> []; +one_filled(doc) -> ["One filled index file"]; +one_filled(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + ?line open(sune, File, ?LINE), + ?line log_terms(sune, ["first round, one", "first round, two"]), + ?line sync(sune), + %% open + test_one(File), + ?line close(sune), + %% closed + test_one(File), + + stop(), + delete_files(File), + ok. + +test_one(File) -> + ?line do_chunk([{open,File}, + {chunk, ["first round, one", "first round, two"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,1}, + {chunk, ["first round, one", "first round, two"]}, + eof], wlt, ?LINE), + wlt ! {open, self(), File, 2}, + ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE), + ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, one"]}, + {chunk, 1, ["first round, two"]}, eof], wlt, ?LINE), + ok. + +two(suite) -> [two_filled]; +two(doc) -> ["Two index files"]. + +two_filled(suite) -> []; +two_filled(doc) -> ["Two filled index files"]; +two_filled(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = list_to_atom(join(Dir, "sune.LOG")), + delete_files(File), + start(), + + ?line open(sune, File, ?LINE), + ?line log_terms(sune, ["first round, 11", "first round, 12"]), + ?line log_terms(sune, ["first round, 21", "first round, 22"]), + ?line sync(sune), + %% open + test_two(File), + ?line close(sune), + %% closed + test_two(File), + + stop(), + delete_files(File), + ok. + +test_two(File) -> + ?line do_chunk([{open,File}, + {chunk, infinity, ["first round, 11", "first round, 12"]}, + {chunk, ["first round, 21", "first round, 22"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,1}, + {chunk, ["first round, 11", "first round, 12"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,2}, + {chunk, ["first round, 21", "first round, 22"]}, + eof], wlt, ?LINE), + wlt ! {open, self(), File, 3}, + ?line rec({error, {file_not_found, add_ext(File, 3)}}, ?LINE), + ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]}, + {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE), + ok. + +four(suite) -> [four_filled]; +four(doc) -> ["Four index files"]. + +four_filled(suite) -> []; +four_filled(doc) -> ["Four filled index files"]; +four_filled(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + ?line open(sune, File, ?LINE), + ?line init_files(0), + ?line sync(sune), + %% open + test_four(File), + ?line close(sune), + %% closed + test_four(File), + + stop(), + delete_files(File), + ok. + +test_four(File) -> + ?line do_chunk([{open,File}, + {chunk, ["first round, 11", "first round, 12"]}, + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,1}, + {chunk, ["first round, 11", "first round, 12"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,4}, + {chunk, ["first round, 41", "first round, 42"]}, + eof], wlt, ?LINE), + wlt ! {open, self(), File, 5}, + ?line rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE), + ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]}, + {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE), + ?line do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]}, + {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE), + ok. + +wrap(suite) -> [wrap_filled]; +wrap(doc) -> ["Wrap index file, first wrapping"]. + +wrap_filled(suite) -> []; +wrap_filled(doc) -> ["First wrap, open, filled index file"]; +wrap_filled(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + ?line open(sune, File, ?LINE), + ?line init_files(0), + ?line log_terms(sune, ["second round, 11", "second round, 12"]), + ?line sync(sune), + %% open + test_wrap(File), + ?line close(sune), + %% closed + test_wrap(File), + + stop(), + delete_files(File), + ok. + +test_wrap(File) -> + ?line do_chunk([{open,File}, + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, + {chunk, ["second round, 11", "second round, 12"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,1}, + {chunk, ["second round, 11", "second round, 12"]}, + eof], wlt, ?LINE), + ?line do_chunk([{open,File,2}, + {chunk, ["first round, 21", "first round, 22"]}, + eof], wlt, ?LINE), + wlt ! {open, self(), File, 5}, + ?line rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE), + ?line do_chunk([{open,File,1}, {chunk, 1, ["second round, 11"]}, + {chunk, 2, ["second round, 12"]}, eof], wlt, ?LINE), + ?line do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]}, + {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE), + ok. + +wrapping(suite) -> []; +wrapping(doc) -> ["Wrapping at the same time as reading"]; +wrapping(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + ?line open(sune, File, ?LINE), + ?line init_files(1100), + ?line sync(sune), + ?line C1 = + do_chunk([{open,File}, {chunk, 1, ["first round, 11"]}], wlt, ?LINE), + ?line log_terms(sune, ["second round, 11", "second round, 12"]), + ?line sync(sune), + ?line do_chunk([{chunk, 1, ["first round, 12"]}, + %% Here two bad bytes are found. + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, eof], + wlt, ?LINE, C1), + start(), + delete_files(File), + ?line open(sune, File, ?LINE), + ?line init_files(1100), + ?line sync(sune), + ?line C2 = + do_chunk([{open,File}, {chunk, 1, ["first round, 11"]}], wlt, ?LINE), + ?line log_terms(sune, ["second round, 11", "second round, 12"]), + ?line close(sune), + ?line do_chunk([{chunk, 1, ["first round, 12"]}, + %% Here two bad bytes are found. + {chunk, ["first round, 21", "first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, eof], + wlt, ?LINE, C2), + start(), + delete_files(File), + ?line open(sune, File, ?LINE), + ?line init_files(1100), + ?line sync(sune), + ?line C3 = do_chunk([{open,File}], wlt, ?LINE), + ?line log_terms(sune, ["second round, 11"]), + ?line sync(sune), + ?line do_chunk([{chunk, 1, ["second round, 11"]}, + {chunk, 1, ["first round, 21"]}, + {chunk, 1, ["first round, 22"]}, + {chunk, ["first round, 31", "first round, 32"]}, + {chunk, ["first round, 41", "first round, 42"]}, eof], + wlt, ?LINE, C3), + + stop(), + delete_files(File), + ok. + +external(suite) -> []; +external(doc) -> ["External format"]; +external(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + ?line open_ext(sune, File, ?FILE), + ?line init_files_ext(0), + ?line close(sune), + P0 = pps(), + wlt ! {open, self(), File}, + ?line rec({error, {not_a_log_file, add_ext(File, 1)}}, ?LINE), + ?line true = (P0 == pps()), + + stop(), + delete_files(File), + ok. + +error(suite) -> []; +error(doc) -> ["Error situations"]; +error(Conf) when list(Conf) -> + Dir = ?privdir(Conf), + File = join(Dir, "sune.LOG"), + delete_files(File), + start(), + + P0 = pps(), + wlt ! {open, self(), File, 1}, + ?line rec({error, {index_file_not_found, File}}, ?LINE), + wlt ! {open, self(), File}, + ?line rec({error, {index_file_not_found, File}}, ?LINE), + ?line true = (P0 == pps()), + + ?line open(sune, File, ?LINE), + ?line close(sune), + P1 = pps(), + ?line First = add_ext(File, 1), + ?line ok = file:delete(First), + wlt ! {open, self(), File}, + ?line rec({error, {not_a_log_file, First}}, ?LINE), + ?line true = (P1 == pps()), + + delete_files(File), + ?line open(sune, File, ?LINE), + ?line init_files(0), + ?line close(sune), + P2 = pps(), + ?line C = do_chunk([{open,File}, + {chunk, ["first round, 11", "first round, 12"]}], + wlt, ?LINE), + ?line Second = add_ext(File, 2), + ?line ok = file:delete(Second), + wlt ! {chunk, self(), C}, + ?line rec({error, {file_error, Second, {error, enoent}}}, ?LINE), + ?line ok = file:write_file(Second, <<17:(3*8)>>), % three bytes + wlt ! {chunk, self(), C}, + ?line rec({error, {not_a_log_file, Second}}, ?LINE), + ?line do_chunk([close], wlt, ?LINE, C), + ?line true = (P2 == pps()), + + delete_files(File), + ?line open(sune, File, ?LINE), + ?line init_files(0), + ?line close(sune), + P3 = pps(), + timer:sleep(1100), + Now = calendar:local_time(), + ?line ok = file:change_time(First, Now), + ?line C2 = do_chunk([{open,File}, + {chunk, ["first round, 11", "first round, 12"]}], + wlt, ?LINE), + wlt ! {chunk, self(), C2}, + ?line rec({error,{is_wrapped,First}}, ?LINE), + ?line do_chunk([close], wlt, ?LINE, C2), + IndexFile = add_ext(File, idx), + ?line ok = file:write_file(IndexFile, <<17:(3*8)>>), + wlt ! {open, self(), File, 1}, + ?line rec({error, {index_file_not_found, File}}, ?LINE), + ?line true = (P3 == pps()), + + stop(), + delete_files(File), + ok. + +start() -> + ?line ok = wrap_log_test:stop(), + dl_wait(), + ?line ok = wrap_log_test:init(). + +stop() -> + ?line ok = wrap_log_test:stop(), + dl_wait(). + +%% Give disk logs opened by 'logger' and 'wlt' time to close after +%% receiving EXIT signals. +dl_wait() -> + case disk_log:accessible_logs() of + {[], []} -> + ok; + _ -> + timer:sleep(100), + dl_wait() + end. + +delete_files(File) -> + file:delete(add_ext(File, idx)), + file:delete(add_ext(File, siz)), + file:delete(add_ext(File, 1)), + file:delete(add_ext(File, 2)), + file:delete(add_ext(File, 3)), + file:delete(add_ext(File, 4)), + ok. + +init_files(Delay) -> + ?line log_terms(sune, ["first round, 11", "first round, 12"]), + timer:sleep(Delay), + ?line log_terms(sune, ["first round, 21", "first round, 22"]), + timer:sleep(Delay), + ?line log_terms(sune, ["first round, 31", "first round, 32"]), + timer:sleep(Delay), + ?line log_terms(sune, ["first round, 41", "first round, 42"]), + timer:sleep(Delay), + ok. + +init_files_ext(Delay) -> + ?line blog_terms(sune, ["first round, 11", "first round, 12"]), + timer:sleep(Delay), + ?line blog_terms(sune, ["first round, 21", "first round, 22"]), + timer:sleep(Delay), + ?line blog_terms(sune, ["first round, 31", "first round, 32"]), + timer:sleep(Delay), + ?line blog_terms(sune, ["first round, 41", "first round, 42"]), + timer:sleep(Delay), + ok. + +join(A, B) -> + filename:nativename(filename:join(A, B)). + +do_chunk(Commands, Server, Where) -> + do_chunk(Commands, Server, Where, foo). + +do_chunk([{open, File, One} | Cs], S, W, _C) -> + S ! {open, self(), File, One}, + ?line NC = rec1(ok, {W,?LINE}), + do_chunk(Cs, S, W, NC); +do_chunk([{open, File} | Cs], S, W, _C) -> + S ! {open, self(), File}, + ?line NC = rec1(ok, {W,?LINE}), + do_chunk(Cs, S, W, NC); +do_chunk([{chunk, Terms} | Cs], S, W, C) -> + S ! {chunk, self(), C}, + ?line NC = rec2(Terms, {W,?LINE}), + do_chunk(Cs, S, W, NC); +do_chunk([{chunk, N, Terms} | Cs], S, W, C) -> + S ! {chunk, self(), C, N}, + ?line NC = rec2(Terms, {W,?LINE}), + do_chunk(Cs, S, W, NC); +do_chunk([eof], S, W, C) -> + S ! {chunk, self(), C}, + ?line C1 = rec2(eof, {W,?LINE}), + do_chunk([close], S, W, C1); +do_chunk([close], S, W, C) -> + S ! {close, self(), C}, + ?line rec(ok, {W,?LINE}); +do_chunk([], _S, _W, C) -> + C. + +add_ext(Name, Ext) -> + lists:concat([Name, ".", Ext]). + +%% disk_log. +open(Log, File, Where) -> + logger ! {open, self(), Log, File}, + rec1(ok, Where). + +open_ext(Log, File, Where) -> + logger ! {open_ext, self(), Log, File}, + rec1(ok, Where). + +close(Log) -> + logger ! {close, self(), Log}, + rec(ok, ?LINE). + +sync(Log) -> + logger ! {sync, self(), Log}, + rec(ok, ?LINE). + +log_terms(File, Terms) -> + logger ! {log_terms, self(), File, Terms}, + rec(ok, ?LINE). + +blog_terms(File, Terms) -> + logger ! {blog_terms, self(), File, Terms}, + rec(ok, ?LINE). + +rec1(M, Where) -> + receive + {M, C} -> C; + Else -> test_server:fail({error, {Where, Else}}) + after 1000 -> test_server:fail({error, {Where, time_out}}) + end. + +rec2(M, Where) -> + receive + {C, M} -> C; + Else -> test_server:fail({error, {Where, Else}}) + after 1000 -> test_server:fail({error, {Where, time_out}}) + end. + +rec(M, Where) -> + receive + M -> + ok; + Else -> ?t:fail({error, {Where, Else}}) + after 1000 -> ?t:fail({error, {Where, time_out}}) + end. + +pps() -> + {erlang:ports(), lists:filter({erlang, is_process_alive}, processes())}. |