25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

370 satır
14 KiB

9 yıl önce
  1. -module(rebar_file_utils_SUITE).
  2. -export([all/0,
  3. groups/0,
  4. init_per_group/2,
  5. end_per_group/2,
  6. init_per_testcase/2,
  7. end_per_testcase/2,
  8. raw_tmpdir/1,
  9. empty_tmpdir/1,
  10. simple_tmpdir/1,
  11. multi_tmpdir/1,
  12. reset_nonexistent_dir/1,
  13. reset_empty_dir/1,
  14. reset_dir/1,
  15. path_from_ancestor/1,
  16. canonical_path/1,
  17. absolute_path/1,
  18. normalized_path/1,
  19. resolve_link/1,
  20. split_dirname/1,
  21. mv_warning_is_ignored/1,
  22. mv_dir/1,
  23. mv_file_same/1,
  24. mv_file_diff/1,
  25. mv_file_dir_same/1,
  26. mv_file_dir_diff/1,
  27. mv_no_clobber/1]).
  28. -include_lib("common_test/include/ct.hrl").
  29. -include_lib("eunit/include/eunit.hrl").
  30. -include_lib("kernel/include/file.hrl").
  31. all() ->
  32. [{group, tmpdir},
  33. {group, reset_dir},
  34. {group, mv},
  35. path_from_ancestor,
  36. canonical_path,
  37. absolute_path,
  38. normalized_path,
  39. resolve_link,
  40. split_dirname,
  41. mv_warning_is_ignored].
  42. groups() ->
  43. [{tmpdir, [], [raw_tmpdir, empty_tmpdir, simple_tmpdir, multi_tmpdir]},
  44. {reset_dir, [], [reset_nonexistent_dir, reset_empty_dir, reset_dir]},
  45. {mv, [], [mv_dir, mv_file_same, mv_file_diff,
  46. mv_file_dir_same, mv_file_dir_diff, mv_no_clobber]}].
  47. init_per_group(reset_dir, Config) ->
  48. TmpDir = rebar_file_utils:system_tmpdir(["rebar_file_utils_SUITE", "resetable"]),
  49. [{tmpdir, TmpDir}|Config];
  50. init_per_group(_, Config) -> Config.
  51. end_per_group(_, Config) -> Config.
  52. init_per_testcase(Test, Config) ->
  53. case os:type() of
  54. {win32, _} ->
  55. case lists:member(Test, [resolve_link, mv_warning_is_ignored]) of
  56. true -> {skip, "broken in windows"};
  57. false -> Config
  58. end;
  59. _ ->
  60. Config
  61. end.
  62. end_per_testcase(_Test, Config) ->
  63. Config.
  64. raw_tmpdir(_Config) ->
  65. case rebar_file_utils:system_tmpdir() of
  66. "/tmp" -> ok;
  67. "./tmp" -> ok
  68. end.
  69. empty_tmpdir(_Config) ->
  70. case rebar_file_utils:system_tmpdir([]) of
  71. "/tmp" -> ok;
  72. "./tmp" -> ok
  73. end.
  74. simple_tmpdir(_Config) ->
  75. case rebar_file_utils:system_tmpdir(["test"]) of
  76. "/tmp/test" -> ok;
  77. "./tmp/test" -> ok
  78. end.
  79. multi_tmpdir(_Config) ->
  80. case rebar_file_utils:system_tmpdir(["a", "b", "c"]) of
  81. "/tmp/a/b/c" -> ok;
  82. "./tmp/a/b/c" -> ok
  83. end.
  84. reset_nonexistent_dir(Config) ->
  85. TmpDir = ?config(tmpdir, Config),
  86. _ = ec_file:remove(TmpDir, [recursive]),
  87. ?assertNot(filelib:is_dir(TmpDir)),
  88. ok = rebar_file_utils:reset_dir(TmpDir),
  89. ?assert(filelib:is_dir(TmpDir)),
  90. {ok, []} = rebar_utils:list_dir(TmpDir).
  91. reset_empty_dir(Config) ->
  92. TmpDir = ?config(tmpdir, Config),
  93. _ = ec_file:remove(TmpDir, [recursive]),
  94. _ = filelib:ensure_dir(filename:join([TmpDir, "dummy.beam"])),
  95. ?assert(filelib:is_dir(TmpDir)),
  96. ok = rebar_file_utils:reset_dir(TmpDir),
  97. ?assert(filelib:is_dir(TmpDir)),
  98. {ok, []} = rebar_utils:list_dir(TmpDir).
  99. reset_dir(Config) ->
  100. TmpDir = ?config(tmpdir, Config),
  101. _ = ec_file:remove(TmpDir, [recursive]),
  102. _ = filelib:ensure_dir(filename:join([TmpDir, "dummy.beam"])),
  103. ?assert(filelib:is_dir(TmpDir)),
  104. lists:foreach(fun(Name) -> file:write_file(filename:join([TmpDir, Name]), <<>>) end,
  105. ["a", "b", "c"]),
  106. lists:foreach(fun(File) -> ?assert(filelib:is_file(filename:join([TmpDir, File]))) end,
  107. ["a", "b", "c"]),
  108. ok = rebar_file_utils:reset_dir(TmpDir),
  109. ?assert(filelib:is_dir(TmpDir)),
  110. {ok, []} = rebar_utils:list_dir(TmpDir).
  111. path_from_ancestor(_Config) ->
  112. ?assertEqual({ok, "foo/bar/baz"}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/")),
  113. ?assertEqual({ok, "bar/baz"}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/foo")),
  114. ?assertEqual({ok, "bar"}, rebar_file_utils:path_from_ancestor("foo/bar", "foo")),
  115. ?assertEqual({ok, "bar"}, rebar_file_utils:path_from_ancestor("foo/bar/", "foo/")),
  116. ?assertEqual({error, badparent}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/qux")),
  117. ?assertEqual({error, badparent}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/foo/bar/baz/qux")).
  118. canonical_path(_Config) ->
  119. %% We find the root so that the name works both on unix-likes and
  120. %% with Windows.
  121. Root = case os:type() of
  122. {win32, _} -> filename:nativename(filename:absname("/")); % C:\, with proper drive
  123. _ -> "/"
  124. end,
  125. ?assertEqual(filename:nativename(Root), rebar_file_utils:canonical_path("/")),
  126. ?assertEqual(filename:nativename(Root), rebar_file_utils:canonical_path("/../../..")),
  127. ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/bar/..")),
  128. ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/../foo")),
  129. ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/.")),
  130. ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/./.")),
  131. ?assertEqual(filename:nativename(Root ++ "foo/bar"),
  132. rebar_file_utils:canonical_path("/foo/./bar")).
  133. absolute_path(_Config) ->
  134. %% We find the root so that the name works both on unix-likes and
  135. %% with Windows. Starting on OTP-22, filename:join/1 drops the drive letter,
  136. %% and split/1 and absname both normalize c:\\ to c:/ -- going onwards, we
  137. %% start normalizing the same way as well to prevent issues.
  138. Root = case os:type() of
  139. {win32, _} -> filename:absname(filename:nativename("/")); % C:\, with proper drive
  140. _ -> "/"
  141. end,
  142. ?assertEqual(filename:absname(Root), rebar_file_utils:absolute_path("/")),
  143. ?assertEqual(Root ++ "foo", rebar_file_utils:absolute_path("/foo")),
  144. % casoscon ../ o ./
  145. {ok, Cwd} = file:get_cwd(),
  146. ?assertEqual(Cwd, rebar_file_utils:absolute_path("./")),
  147. ?assertEqual(Cwd ++ "/foo", rebar_file_utils:absolute_path("./foo")),
  148. ?assertEqual(Cwd ++ "/foo/bar", rebar_file_utils:absolute_path("foo/bar")).
  149. normalized_path(_Config) ->
  150. %% We find the root so that the name works both on unix-likes and
  151. %% with Windows. Starting on OTP-22, filename:join/1 drops the drive letter,
  152. %% and split/1 and absname both normalize c:\\ to c:/ -- going onwards, we
  153. %% start normalizing the same way as well to prevent issues.
  154. Root = case os:type() of
  155. {win32, _} -> filename:absname(filename:nativename("/")); % c:/, with proper drive
  156. _ -> "/"
  157. end,
  158. ?assertEqual(Root, rebar_file_utils:normalized_path("/")),
  159. ?assertEqual("../..", rebar_file_utils:normalized_path("/../../..")),
  160. ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/bar/..")),
  161. ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/../foo")),
  162. ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/.")),
  163. ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/./.")),
  164. ?assertEqual(Root ++ "foo/bar",
  165. rebar_file_utils:normalized_path("/foo/./bar")).
  166. resolve_link(_Config) ->
  167. TmpDir = rebar_file_utils:system_tmpdir(
  168. ["rebar_file_utils_SUITE", "resolve_link"]),
  169. Link = filename:join(TmpDir, "link"),
  170. Target = filename:join(TmpDir, "link-target"),
  171. ec_file:remove(TmpDir, [recursive]),
  172. ok = filelib:ensure_dir(Target),
  173. ok = file:write_file(Target, <<>>),
  174. ok = file:make_symlink(Target, Link),
  175. ?assertEqual(Target, rebar_file_utils:resolve_link(Link)).
  176. split_dirname(_Config) ->
  177. ?assertEqual({".", ""}, rebar_file_utils:split_dirname("")),
  178. ?assertEqual({"/", ""}, rebar_file_utils:split_dirname("/")),
  179. ?assertEqual({"/", "foo"}, rebar_file_utils:split_dirname("/foo")),
  180. ?assertEqual({".", "foo"}, rebar_file_utils:split_dirname("foo")),
  181. ?assertEqual({"/foo", "bar"}, rebar_file_utils:split_dirname("/foo/bar")),
  182. ?assertEqual({"foo", "bar"}, rebar_file_utils:split_dirname("foo/bar")).
  183. mv_warning_is_ignored(_Config) ->
  184. meck:new(rebar_utils, [passthrough]),
  185. meck:expect(rebar_utils, sh, fun("mv ding dong", _) -> {ok, "Warning"} end),
  186. ok = rebar_file_utils:mv("ding", "dong"),
  187. meck:unload(rebar_utils).
  188. %%% Ensure Windows & Unix operations to move files
  189. mv_dir(Config) ->
  190. %% Move a directory to another one location
  191. PrivDir = ?config(priv_dir, Config),
  192. BaseDir = mk_base_dir(PrivDir, mv_dir),
  193. SrcDir = filename:join(BaseDir, "src/"),
  194. ec_file:mkdir_p(SrcDir),
  195. ?assert(filelib:is_dir(SrcDir)),
  196. %% empty dir movement
  197. DstDir1 = filename:join(BaseDir, "dst1/"),
  198. ?assertNot(filelib:is_dir(DstDir1)),
  199. ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir1)),
  200. ?assert(filelib:is_dir(DstDir1)),
  201. %% move files from dir to empty dir
  202. F1 = filename:join(SrcDir, "file1"),
  203. F2 = filename:join(SrcDir, "subdir/file2"),
  204. filelib:ensure_dir(F2),
  205. file:write_file(F1, "hello"),
  206. file:write_file(F2, "world"),
  207. DstDir2 = filename:join(BaseDir, "dst2/"),
  208. D2F1 = filename:join(DstDir2, "file1"),
  209. D2F2 = filename:join(DstDir2, "subdir/file2"),
  210. ?assertNot(filelib:is_dir(DstDir2)),
  211. ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir2)),
  212. ?assert(filelib:is_file(D2F1)),
  213. ?assert(filelib:is_file(D2F2)),
  214. %% move files from dir to existing dir moves it to
  215. %% a subdir
  216. filelib:ensure_dir(F2),
  217. file:write_file(F1, "hello"),
  218. file:write_file(F2, "world"),
  219. DstDir3 = filename:join(BaseDir, "dst3/"),
  220. D3F1 = filename:join(DstDir3, "src/file1"),
  221. D3F2 = filename:join(DstDir3, "src/subdir/file2"),
  222. ec_file:mkdir_p(DstDir3),
  223. ?assert(filelib:is_dir(DstDir3)),
  224. ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir3)),
  225. ?assertNot(filelib:is_file(F1)),
  226. ?assertNot(filelib:is_file(F2)),
  227. ?assert(filelib:is_file(D3F1)),
  228. ?assert(filelib:is_file(D3F2)),
  229. ?assertNot(filelib:is_dir(SrcDir)),
  230. ok.
  231. mv_file_same(Config) ->
  232. %% Move a file from a directory to the other without renaming
  233. PrivDir = ?config(priv_dir, Config),
  234. BaseDir = mk_base_dir(PrivDir, mv_file_same),
  235. SrcDir = filename:join(BaseDir, "src/"),
  236. ec_file:mkdir_p(SrcDir),
  237. ?assert(filelib:is_dir(SrcDir)),
  238. F = filename:join(SrcDir, "file"),
  239. file:write_file(F, "hello"),
  240. DstDir = filename:join(BaseDir, "dst/"),
  241. ec_file:mkdir_p(DstDir),
  242. Dst = filename:join(DstDir, "file"),
  243. ?assertEqual(ok, rebar_file_utils:mv(F, Dst)),
  244. ?assert(filelib:is_file(Dst)),
  245. ?assertNot(filelib:is_file(F)),
  246. ok.
  247. mv_file_diff(Config) ->
  248. %% Move a file from a directory to another one while renaming
  249. %% into a pre-existing file
  250. PrivDir = ?config(priv_dir, Config),
  251. BaseDir = mk_base_dir(PrivDir, mv_file_diff),
  252. SrcDir = filename:join(BaseDir, "src/"),
  253. ec_file:mkdir_p(SrcDir),
  254. ?assert(filelib:is_dir(SrcDir)),
  255. F = filename:join(SrcDir, "file"),
  256. file:write_file(F, "hello"),
  257. DstDir = filename:join(BaseDir, "dst/"),
  258. ec_file:mkdir_p(DstDir),
  259. Dst = filename:join(DstDir, "file-rename"),
  260. file:write_file(Dst, "not-the-right-content"),
  261. ?assert(filelib:is_file(Dst)),
  262. ?assertEqual(ok, rebar_file_utils:mv(F, Dst)),
  263. ?assert(filelib:is_file(Dst)),
  264. ?assertEqual({ok, <<"hello">>}, file:read_file(Dst)),
  265. ?assertNot(filelib:is_file(F)),
  266. ok.
  267. mv_file_dir_same(Config) ->
  268. %% Move a file to a directory without renaming
  269. PrivDir = ?config(priv_dir, Config),
  270. BaseDir = mk_base_dir(PrivDir, mv_file_dir_same),
  271. SrcDir = filename:join(BaseDir, "src/"),
  272. ec_file:mkdir_p(SrcDir),
  273. ?assert(filelib:is_dir(SrcDir)),
  274. F = filename:join(SrcDir, "file"),
  275. file:write_file(F, "hello"),
  276. DstDir = filename:join(BaseDir, "dst/"),
  277. ec_file:mkdir_p(DstDir),
  278. Dst = filename:join(DstDir, "file"),
  279. ?assert(filelib:is_dir(DstDir)),
  280. ?assertEqual(ok, rebar_file_utils:mv(F, DstDir)),
  281. ?assert(filelib:is_file(Dst)),
  282. ?assertNot(filelib:is_file(F)),
  283. ok.
  284. mv_file_dir_diff(Config) ->
  285. %% Move a file to a directory while renaming
  286. PrivDir = ?config(priv_dir, Config),
  287. BaseDir = mk_base_dir(PrivDir, mv_file_dir_diff),
  288. SrcDir = filename:join(BaseDir, "src/"),
  289. ec_file:mkdir_p(SrcDir),
  290. ?assert(filelib:is_dir(SrcDir)),
  291. F = filename:join(SrcDir, "file"),
  292. file:write_file(F, "hello"),
  293. DstDir = filename:join(BaseDir, "dst/"),
  294. ec_file:mkdir_p(DstDir),
  295. Dst = filename:join(DstDir, "file-rename"),
  296. ?assert(filelib:is_dir(DstDir)),
  297. ?assertNot(filelib:is_file(Dst)),
  298. ?assertEqual(ok, rebar_file_utils:mv(F, Dst)),
  299. ?assert(filelib:is_file(Dst)),
  300. ?assertNot(filelib:is_file(F)),
  301. ok.
  302. mv_no_clobber(Config) ->
  303. %% Moving a file while renaming does not clobber other files
  304. PrivDir = ?config(priv_dir, Config),
  305. BaseDir = mk_base_dir(PrivDir, mv_no_clobber),
  306. SrcDir = filename:join(BaseDir, "src/"),
  307. ec_file:mkdir_p(SrcDir),
  308. ?assert(filelib:is_dir(SrcDir)),
  309. F = filename:join(SrcDir, "file"),
  310. file:write_file(F, "hello"),
  311. FBad = filename:join(SrcDir, "file-alt"),
  312. file:write_file(FBad, "wrong-data"),
  313. DstDir = filename:join(BaseDir, "dst/"),
  314. ec_file:mkdir_p(DstDir),
  315. Dst = filename:join(DstDir, "file-alt"),
  316. DstBad = filename:join(DstDir, "file"),
  317. file:write_file(DstBad, "wrong-data"),
  318. ?assert(filelib:is_file(F)),
  319. ?assert(filelib:is_file(FBad)),
  320. ?assert(filelib:is_dir(DstDir)),
  321. ?assertNot(filelib:is_file(Dst)),
  322. ?assert(filelib:is_file(DstBad)),
  323. ?assertEqual(ok, rebar_file_utils:mv(F, Dst)),
  324. ?assert(filelib:is_file(Dst)),
  325. ?assertNot(filelib:is_file(F)),
  326. ?assert(filelib:is_file(DstBad)),
  327. ?assert(filelib:is_file(FBad)),
  328. ?assertEqual({ok, <<"hello">>}, file:read_file(Dst)),
  329. ?assertEqual({ok, <<"wrong-data">>}, file:read_file(FBad)),
  330. ?assertEqual({ok, <<"wrong-data">>}, file:read_file(DstBad)),
  331. ok.
  332. mk_base_dir(BasePath, Name) ->
  333. {_,_,Micro} = os:timestamp(),
  334. Index = integer_to_list(Micro),
  335. Path = filename:join(BasePath, atom_to_list(Name) ++ Index),
  336. ec_file:mkdir_p(Path),
  337. Path.