1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2005-2013. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: 20: -module(filelib_SUITE). 21: 22: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 23: init_per_group/2,end_per_group/2, 24: init_per_testcase/2,end_per_testcase/2, 25: wildcard_one/1,wildcard_two/1,wildcard_errors/1, 26: fold_files/1,otp_5960/1,ensure_dir_eexist/1]). 27: 28: -import(lists, [foreach/2]). 29: 30: -include_lib("test_server/include/test_server.hrl"). 31: -include_lib("kernel/include/file.hrl"). 32: 33: init_per_testcase(_Case, Config) -> 34: ?line Dog = ?t:timetrap(?t:minutes(5)), 35: [{watchdog,Dog}|Config]. 36: 37: end_per_testcase(_Case, Config) -> 38: Dog = ?config(watchdog, Config), 39: test_server:timetrap_cancel(Dog), 40: ok. 41: 42: suite() -> [{ct_hooks,[ts_install_cth]}]. 43: 44: all() -> 45: [wildcard_one, wildcard_two, wildcard_errors, 46: fold_files, otp_5960, ensure_dir_eexist]. 47: 48: groups() -> 49: []. 50: 51: init_per_suite(Config) -> 52: Config. 53: 54: end_per_suite(_Config) -> 55: ok. 56: 57: init_per_group(_GroupName, Config) -> 58: Config. 59: 60: end_per_group(_GroupName, Config) -> 61: Config. 62: 63: 64: wildcard_one(Config) when is_list(Config) -> 65: ?line {ok,OldCwd} = file:get_cwd(), 66: ?line Dir = filename:join(?config(priv_dir, Config), "wildcard_one"), 67: ?line ok = file:make_dir(Dir), 68: do_wildcard_1(Dir, 69: fun(Wc) -> 70: filelib:wildcard(Wc, Dir, erl_prim_loader) 71: end), 72: ?line file:set_cwd(Dir), 73: do_wildcard_1(Dir, 74: fun(Wc) -> 75: L = filelib:wildcard(Wc), 76: L = filelib:wildcard(Wc, erl_prim_loader), 77: L = filelib:wildcard(Wc, "."), 78: L = filelib:wildcard(Wc, Dir) 79: end), 80: ?line file:set_cwd(OldCwd), 81: ?line ok = file:del_dir(Dir), 82: ok. 83: 84: wildcard_two(Config) when is_list(Config) -> 85: ?line Dir = filename:join(?config(priv_dir, Config), "wildcard_two"), 86: ?line ok = file:make_dir(Dir), 87: ?line do_wildcard_1(Dir, fun(Wc) -> io:format("~p~n",[{Wc,Dir, X = filelib:wildcard(Wc, Dir)}]),X end), 88: ?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/") end), 89: case os:type() of 90: {win32,_} -> 91: ok; 92: _ -> 93: ?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, "//"++Dir) end) 94: end, 95: ?line ok = file:del_dir(Dir), 96: ok. 97: 98: wildcard_errors(Config) when is_list(Config) -> 99: ?line wcc("{", missing_delimiter), 100: ?line wcc("{a", missing_delimiter), 101: ?line wcc("{a,", missing_delimiter), 102: ?line wcc("{a,b", missing_delimiter), 103: ok. 104: 105: wcc(Wc, Error) -> 106: {'EXIT',{{badpattern,Error}, 107: [{filelib,compile_wildcard,1,_}|_]}} = 108: (catch filelib:compile_wildcard(Wc)), 109: {'EXIT',{{badpattern,Error}, 110: [{filelib,wildcard,1,_}|_]}} = (catch filelib:wildcard(Wc)), 111: {'EXIT',{{badpattern,Error}, 112: [{filelib,wildcard,2,_}|_]}} = (catch filelib:wildcard(Wc, ".")). 113: 114: do_wildcard_1(Dir, Wcf0) -> 115: do_wildcard_2(Dir, Wcf0), 116: Wcf = fun(Wc0) -> 117: Wc = filename:join(Dir, Wc0), 118: L = Wcf0(Wc), 119: [subtract_dir(N, Dir) || N <- L] 120: end, 121: do_wildcard_2(Dir, Wcf). 122: 123: subtract_dir([C|Cs], [C|Dir]) -> subtract_dir(Cs, Dir); 124: subtract_dir("/"++Cs, []) -> Cs. 125: 126: do_wildcard_2(Dir, Wcf) -> 127: %% Basic wildcards. 128: All = ["abc","abcdef","glurf"], 129: ?line Files = mkfiles(lists:reverse(All), Dir), 130: ?line All = Wcf("*"), 131: ?line ["abc","abcdef"] = Wcf("a*"), 132: ?line ["abc","abcdef"] = Wcf("abc*"), 133: ?line ["abcdef"] = Wcf("abc???"), 134: ?line ["abcdef"] = Wcf("abcd*"), 135: ?line ["abcdef"] = Wcf("*def"), 136: ?line ["abcdef","glurf"] = Wcf("{*def,gl*}"), 137: ?line ["abc","abcdef"] = Wcf("a*{def,}"), 138: ?line ["abc","abcdef"] = Wcf("a*{,def}"), 139: 140: %% Constant wildcard. 141: ["abcdef"] = Wcf("abcdef"), 142: 143: %% Negative tests. 144: ?line [] = Wcf("b*"), 145: ?line [] = Wcf("bufflig"), 146: 147: ?line del(Files), 148: do_wildcard_3(Dir, Wcf). 149: 150: do_wildcard_3(Dir, Wcf) -> 151: %% Some character sets. 152: All = ["a01","a02","a03","b00","c02","d19"], 153: ?line Files = mkfiles(lists:reverse(All), Dir), 154: ?line All = Wcf("[a-z]*"), 155: ?line All = Wcf("[a-d]*"), 156: ?line All = Wcf("[adbc]*"), 157: ?line All = Wcf("?[0-9][0-9]"), 158: ?line All = Wcf("?[0-1][0-39]"), 159: ?line All = Wcf("[abcdefgh][10][01239]"), 160: ?line ["a01","a02","a03","b00","c02"] = Wcf("[a-z]0[0-3]"), 161: ?line [] = Wcf("?[a-z][0-39]"), 162: ?line del(Files), 163: do_wildcard_4(Dir, Wcf). 164: 165: do_wildcard_4(Dir, Wcf) -> 166: %% More character sets: tricky characters. 167: All = ["a-","aA","aB","aC","a[","a]"], 168: ?line Files = mkfiles(lists:reverse(All), Dir), 169: ?line All = Wcf("a[][A-C-]"), 170: ["a-"] = Wcf("a[-]"), 171: ["a["] = Wcf("a["), 172: ?line del(Files), 173: do_wildcard_5(Dir, Wcf). 174: 175: do_wildcard_5(Dir, Wcf) -> 176: Dirs = ["xa","blurf","yyy"], 177: ?line foreach(fun(D) -> ok = file:make_dir(filename:join(Dir, D)) end, Dirs), 178: All = ["blurf/nisse","xa/arne","xa/kalle","yyy/arne"], 179: ?line Files = mkfiles(lists:reverse(All), Dir), 180: 181: %% Test. 182: ?line All = Wcf("*/*"), 183: ?line ["blurf/nisse","xa/arne","xa/kalle"] = Wcf("{blurf,xa}/*"), 184: ?line ["xa/arne","yyy/arne"] = Wcf("*/arne"), 185: ?line ["blurf/nisse"] = Wcf("*/nisse"), 186: ?line [] = Wcf("mountain/*"), 187: ?line [] = Wcf("xa/gurka"), 188: ["blurf/nisse"] = Wcf("blurf/nisse"), 189: 190: %% Cleanup 191: ?line del(Files), 192: ?line foreach(fun(D) -> ok = file:del_dir(filename:join(Dir, D)) end, Dirs), 193: do_wildcard_6(Dir, Wcf). 194: 195: do_wildcard_6(Dir, Wcf) -> 196: ok = file:make_dir(filename:join(Dir, "xbin")), 197: All = ["xbin/a.x","xbin/b.x","xbin/c.x"], 198: Files = mkfiles(All, Dir), 199: All = Wcf("xbin/*.x"), 200: All = Wcf("xbin/*"), 201: ["xbin"] = Wcf("*"), 202: All = Wcf("*/*"), 203: del(Files), 204: ok = file:del_dir(filename:join(Dir, "xbin")), 205: do_wildcard_7(Dir, Wcf). 206: 207: do_wildcard_7(Dir, Wcf) -> 208: Dirs = ["blurf","xa","yyy"], 209: SubDirs = ["blurf/nisse"], 210: foreach(fun(D) -> 211: ok = file:make_dir(filename:join(Dir, D)) 212: end, Dirs ++ SubDirs), 213: All = ["blurf/nisse/baz","xa/arne","xa/kalle","yyy/arne"], 214: Files = mkfiles(lists:reverse(All), Dir), 215: 216: %% Test. 217: Listing = Wcf("**"), 218: ["blurf","blurf/nisse","blurf/nisse/baz", 219: "xa","xa/arne","xa/kalle","yyy","yyy/arne"] = Listing, 220: Listing = Wcf("**/*"), 221: ["xa/arne","yyy/arne"] = Wcf("**/arne"), 222: ["blurf/nisse"] = Wcf("**/nisse"), 223: [] = Wcf("mountain/**"), 224: 225: %% Cleanup 226: del(Files), 227: foreach(fun(D) -> 228: ok = file:del_dir(filename:join(Dir, D)) 229: end, SubDirs ++ Dirs), 230: do_wildcard_8(Dir, Wcf). 231: 232: do_wildcard_8(Dir, Wcf) -> 233: Dirs0 = ["blurf"], 234: Dirs1 = ["blurf/nisse"], 235: Dirs2 = ["blurf/nisse/a", "blurf/nisse/b"], 236: foreach(fun(D) -> 237: ok = file:make_dir(filename:join(Dir, D)) 238: end, Dirs0 ++ Dirs1 ++ Dirs2), 239: All = ["blurf/nisse/a/1.txt", "blurf/nisse/b/2.txt", "blurf/nisse/b/3.txt"], 240: Files = mkfiles(lists:reverse(All), Dir), 241: 242: %% Test. 243: All = Wcf("**/blurf/**/*.txt"), 244: 245: %% Cleanup 246: del(Files), 247: foreach(fun(D) -> 248: ok = file:del_dir(filename:join(Dir, D)) 249: end, Dirs2 ++ Dirs1 ++ Dirs0), 250: do_wildcard_9(Dir, Wcf). 251: 252: do_wildcard_9(Dir, Wcf) -> 253: Dirs0 = ["lib","lib/app","lib/app/ebin"], 254: Dirs = [filename:join(Dir, D) || D <- Dirs0], 255: [ok = file:make_dir(D) || D <- Dirs], 256: Files0 = [filename:join("lib/app/ebin", F++".bar") || 257: F <- ["abc","foo","foobar"]], 258: Files = [filename:join(Dir, F) || F <- Files0], 259: [ok = file:write_file(F, <<"some content\n">>) || F <- Files], 260: Files0 = Wcf("lib/app/ebin/*.bar"), 261: 262: %% Cleanup. 263: del(Files), 264: [ok = file:del_dir(D) || D <- lists:reverse(Dirs)], 265: ok. 266: 267: 268: fold_files(Config) when is_list(Config) -> 269: ?line Dir = filename:join(?config(priv_dir, Config), "fold_files"), 270: ?line ok = file:make_dir(Dir), 271: ?line Dirs = [filename:join(Dir, D) || D <- ["blurf","blurf/blarf"]], 272: ?line foreach(fun(D) -> ok = file:make_dir(D) end, Dirs), 273: All = ["fb.txt","ko.txt", 274: "blurf/nisse.text","blurf/blarf/aaa.txt","blurf/blarf/urfa.txt"], 275: ?line Files = mkfiles(lists:reverse(All), Dir), 276: 277: %% Test. 278: ?line Files0 = filelib:fold_files(Dir, "^", false, 279: fun(H, T) -> [H|T] end, []), 280: ?line same_lists(["fb.txt","ko.txt"], Files0, Dir), 281: 282: ?line Files1 = filelib:fold_files(Dir, "^", true, 283: fun(H, T) -> [H|T] end, []), 284: ?line same_lists(All, Files1, Dir), 285: 286: ?line Files2 = filelib:fold_files(Dir, "[.]text$", true, 287: fun(H, T) -> [H|T] end, []), 288: ?line same_lists(["blurf/nisse.text"], Files2, Dir), 289: 290: 291: ?line Files3 = filelib:fold_files(Dir, "^..[.]", true, 292: fun(H, T) -> [H|T] end, []), 293: ?line same_lists(["fb.txt","ko.txt"], Files3, Dir), 294: 295: ?line Files4 = filelib:fold_files(Dir, "^ko[.]txt$", true, 296: fun(H, T) -> [H|T] end, []), 297: ?line same_lists(["ko.txt"], Files4, Dir), 298: ?line Files4 = filelib:fold_files(Dir, "^ko[.]txt$", false, 299: fun(H, T) -> [H|T] end, []), 300: 301: ?line [] = filelib:fold_files(Dir, "^$", true, 302: fun(H, T) -> [H|T] end, []), 303: 304: %% Cleanup 305: ?line del(Files), 306: ?line foreach(fun(D) -> ok = file:del_dir(D) end, lists:reverse(Dirs)), 307: ?line ok = file:del_dir(Dir). 308: 309: same_lists(Expected0, Actual0, BaseDir) -> 310: Expected = [filename:absname(N, BaseDir) || N <- lists:sort(Expected0)], 311: Actual = lists:sort(Actual0), 312: Expected = Actual. 313: 314: mkfiles([H|T], Dir) -> 315: Name = filename:join(Dir, H), 316: Garbage = [31+random:uniform(95) || _ <- lists:seq(1, random:uniform(1024))], 317: file:write_file(Name, Garbage), 318: [Name|mkfiles(T, Dir)]; 319: mkfiles([], _) -> []. 320: 321: del([H|T]) -> 322: ok = file:delete(H), 323: del(T); 324: del([]) -> ok. 325: 326: otp_5960(suite) -> 327: []; 328: otp_5960(doc) -> 329: ["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"]; 330: otp_5960(Config) when is_list(Config) -> 331: ?line PrivDir = ?config(priv_dir, Config), 332: ?line Dir = filename:join(PrivDir, "otp_5960_dir"), 333: ?line Name1 = filename:join(Dir, name1), 334: ?line Name2 = filename:join(Dir, name2), 335: ?line ok = filelib:ensure_dir(Name1), % parent is created 336: ?line ok = filelib:ensure_dir(Name1), % repeating it should be OK 337: ?line ok = filelib:ensure_dir(Name2), % parent already exists 338: ?line ok = filelib:ensure_dir(Name2), % repeating it should be OK 339: ?line Name3 = filename:join(Name1, name3), 340: ?line {ok, FileInfo} = file:read_file_info(Dir), 341: case os:type() of 342: {win32,_} -> 343: %% Not possibly to write protect directories on Windows 344: %% (at least not using file:write_file_info/2). 345: ok; 346: _ -> 347: ?line Mode = FileInfo#file_info.mode, 348: ?line NoWriteMode = Mode - 8#00200 - 8#00020 - 8#00002, 349: ?line ok = file:write_file_info(Dir, #file_info{mode=NoWriteMode}), 350: ?line {error, _} = filelib:ensure_dir(Name3), 351: ?line ok = file:write_file_info(Dir, #file_info{mode=Mode}), 352: ok 353: end. 354: 355: ensure_dir_eexist(Config) when is_list(Config) -> 356: ?line PrivDir = ?config(priv_dir, Config), 357: ?line Dir = filename:join(PrivDir, "ensure_dir_eexist"), 358: ?line Name = filename:join(Dir, "same_name_as_file_and_dir"), 359: ?line ok = filelib:ensure_dir(Name), 360: ?line ok = file:write_file(Name, <<"some string\n">>), 361: 362: %% There already is a file with the name of the directory 363: %% we want to create. 364: ?line NeedFile = filename:join(Name, "file"), 365: ?line NeedFileB = filename:join(Name, <<"file">>), 366: ?line {error, eexist} = filelib:ensure_dir(NeedFile), 367: ?line {error, eexist} = filelib:ensure_dir(NeedFileB), 368: ok.