%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2005-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(filelib_SUITE).
-export([all/1,init_per_testcase/2,fin_per_testcase/2,
wildcard_one/1,wildcard_two/1,wildcard_errors/1,
fold_files/1,otp_5960/1]).
-import(lists, [foreach/2]).
-include("test_server.hrl").
-include_lib("kernel/include/file.hrl").
init_per_testcase(_Case, Config) ->
?line Dog = ?t:timetrap(?t:minutes(5)),
[{watchdog,Dog}|Config].
fin_per_testcase(_Case, Config) ->
Dog = ?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
ok.
all(suite) ->
[wildcard_one,wildcard_two,wildcard_errors,fold_files,otp_5960].
wildcard_one(Config) when is_list(Config) ->
?line {ok,OldCwd} = file:get_cwd(),
?line Dir = filename:join(?config(priv_dir, Config), "wildcard_one"),
?line ok = file:make_dir(Dir),
?line file:set_cwd(Dir),
?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc) end),
?line file:set_cwd(OldCwd),
?line ok = file:del_dir(Dir),
ok.
wildcard_two(Config) when is_list(Config) ->
?line Dir = filename:join(?config(priv_dir, Config), "wildcard_two"),
?line ok = file:make_dir(Dir),
?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir) end),
?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/") end),
case os:type() of
{win32,_} ->
ok;
_ ->
?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, "//"++Dir) end)
end,
?line ok = file:del_dir(Dir),
ok.
wildcard_errors(Config) when is_list(Config) ->
?line wcc("{", missing_delimiter),
?line wcc("{a", missing_delimiter),
?line wcc("{a,", missing_delimiter),
?line wcc("{a,b", missing_delimiter),
ok.
wcc(Wc, Error) ->
{'EXIT',{{badpattern,Error},
[{filelib,compile_wildcard,1}|_]}} = (catch filelib:compile_wildcard(Wc)),
{'EXIT',{{badpattern,Error},
[{filelib,wildcard,1}|_]}} = (catch filelib:wildcard(Wc)),
{'EXIT',{{badpattern,Error},
[{filelib,wildcard,2}|_]}} = (catch filelib:wildcard(Wc, ".")).
do_wildcard_1(Dir, Wcf0) ->
do_wildcard_2(Dir, Wcf0),
Wcf = fun(Wc0) ->
Wc = filename:join(Dir, Wc0),
L = Wcf0(Wc),
[subtract_dir(N, Dir) || N <- L]
end,
do_wildcard_2(Dir, Wcf).
subtract_dir([C|Cs], [C|Dir]) -> subtract_dir(Cs, Dir);
subtract_dir("/"++Cs, []) -> Cs.
do_wildcard_2(Dir, Wcf) ->
%% Basic wildcards.
All = ["abc","abcdef","glurf"],
?line Files = mkfiles(lists:reverse(All), Dir),
?line All = Wcf("*"),
?line ["abc","abcdef"] = Wcf("a*"),
?line ["abc","abcdef"] = Wcf("abc*"),
?line ["abcdef"] = Wcf("abc???"),
?line ["abcdef"] = Wcf("abcd*"),
?line ["abcdef"] = Wcf("*def"),
?line ["abcdef","glurf"] = Wcf("{*def,gl*}"),
?line ["abc","abcdef"] = Wcf("a*{def,}"),
?line ["abc","abcdef"] = Wcf("a*{,def}"),
%% Negative tests.
?line [] = Wcf("b*"),
?line [] = Wcf("bufflig"),
?line del(Files),
do_wildcard_3(Dir, Wcf).
do_wildcard_3(Dir, Wcf) ->
%% Some character sets.
All = ["a01","a02","a03","b00","c02","d19"],
?line Files = mkfiles(lists:reverse(All), Dir),
?line All = Wcf("[a-z]*"),
?line All = Wcf("[a-d]*"),
?line All = Wcf("[adbc]*"),
?line All = Wcf("?[0-9][0-9]"),
?line All = Wcf("?[0-1][0-39]"),
?line All = Wcf("[abcdefgh][10][01239]"),
?line ["a01","a02","a03","b00","c02"] = Wcf("[a-z]0[0-3]"),
?line [] = Wcf("?[a-z][0-39]"),
?line del(Files),
do_wildcard_4(Dir, Wcf).
do_wildcard_4(Dir, Wcf) ->
%% More character sets: tricky characters.
All = ["a-","aA","aB","aC","a[","a]"],
?line Files = mkfiles(lists:reverse(All), Dir),
?line All = Wcf("a[][A-C-]"),
?line del(Files),
do_wildcard_5(Dir, Wcf).
do_wildcard_5(Dir, Wcf) ->
Dirs = ["xa","blurf","yyy"],
?line foreach(fun(D) -> ok = file:make_dir(filename:join(Dir, D)) end, Dirs),
All = ["blurf/nisse","xa/arne","xa/kalle","yyy/arne"],
?line Files = mkfiles(lists:reverse(All), Dir),
%% Test.
?line All = Wcf("*/*"),
?line ["blurf/nisse","xa/arne","xa/kalle"] = Wcf("{blurf,xa}/*"),
?line ["xa/arne","yyy/arne"] = Wcf("*/arne"),
?line ["blurf/nisse"] = Wcf("*/nisse"),
?line [] = Wcf("mountain/*"),
?line [] = Wcf("xa/gurka"),
%% Cleanup
?line del(Files),
?line foreach(fun(D) -> ok = file:del_dir(filename:join(Dir, D)) end, Dirs).
fold_files(Config) when is_list(Config) ->
?line Dir = filename:join(?config(priv_dir, Config), "fold_files"),
?line ok = file:make_dir(Dir),
?line Dirs = [filename:join(Dir, D) || D <- ["blurf","blurf/blarf"]],
?line foreach(fun(D) -> ok = file:make_dir(D) end, Dirs),
All = ["fb.txt","ko.txt",
"blurf/nisse.text","blurf/blarf/aaa.txt","blurf/blarf/urfa.txt"],
?line Files = mkfiles(lists:reverse(All), Dir),
%% Test.
?line Files0 = filelib:fold_files(Dir, "^", false,
fun(H, T) -> [H|T] end, []),
?line same_lists(["fb.txt","ko.txt"], Files0, Dir),
?line Files1 = filelib:fold_files(Dir, "^", true,
fun(H, T) -> [H|T] end, []),
?line same_lists(All, Files1, Dir),
?line Files2 = filelib:fold_files(Dir, "[.]text$", true,
fun(H, T) -> [H|T] end, []),
?line same_lists(["blurf/nisse.text"], Files2, Dir),
?line Files3 = filelib:fold_files(Dir, "^..[.]", true,
fun(H, T) -> [H|T] end, []),
?line same_lists(["fb.txt","ko.txt"], Files3, Dir),
?line Files4 = filelib:fold_files(Dir, "^ko[.]txt$", true,
fun(H, T) -> [H|T] end, []),
?line same_lists(["ko.txt"], Files4, Dir),
?line Files4 = filelib:fold_files(Dir, "^ko[.]txt$", false,
fun(H, T) -> [H|T] end, []),
?line [] = filelib:fold_files(Dir, "^$", true,
fun(H, T) -> [H|T] end, []),
%% Cleanup
?line del(Files),
?line foreach(fun(D) -> ok = file:del_dir(D) end, lists:reverse(Dirs)),
?line ok = file:del_dir(Dir).
same_lists(Expected0, Actual0, BaseDir) ->
Expected = [filename:absname(N, BaseDir) || N <- lists:sort(Expected0)],
Actual = lists:sort(Actual0),
Expected = Actual.
mkfiles([H|T], Dir) ->
Name = filename:join(Dir, H),
Garbage = [31+random:uniform(95) || _ <- lists:seq(1, random:uniform(1024))],
file:write_file(Name, Garbage),
[Name|mkfiles(T, Dir)];
mkfiles([], _) -> [].
del([H|T]) ->
ok = file:delete(H),
del(T);
del([]) -> ok.
otp_5960(suite) ->
[];
otp_5960(doc) ->
["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"];
otp_5960(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
?line Dir = filename:join(PrivDir, otp_5960_dir),
?line Name1 = filename:join(Dir, name1),
?line Name2 = filename:join(Dir, name2),
?line ok = filelib:ensure_dir(Name1), % parent is created
?line ok = filelib:ensure_dir(Name2), % parent already exists
?line Name3 = filename:join(Name1, name3),
?line {ok, FileInfo} = file:read_file_info(Dir),
case os:type() of
{win32,_} ->
%% Not possibly to write protect directories on Windows
%% (at least not using file:write_file_info/2).
ok;
_ ->
?line Mode = FileInfo#file_info.mode,
?line NoWriteMode = Mode - 8#00200 - 8#00020 - 8#00002,
?line ok = file:write_file_info(Dir, #file_info{mode=NoWriteMode}),
?line {error, _} = filelib:ensure_dir(Name3),
?line ok = file:write_file_info(Dir, #file_info{mode=Mode}),
ok
end.