Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

295 строки
13 KiB

8 лет назад
8 лет назад
8 лет назад
8 лет назад
8 лет назад
8 лет назад
8 лет назад
  1. -module(rebar_pkg_alias_SUITE).
  2. -compile(export_all).
  3. -include_lib("common_test/include/ct.hrl").
  4. -include_lib("eunit/include/eunit.hrl").
  5. -include_lib("kernel/include/file.hrl").
  6. -include("rebar.hrl").
  7. all() -> [same_alias, diff_alias, diff_alias_vsn, transitive_alias%% ,
  8. %% transitive_hash_mismatch
  9. ].
  10. %% {uuid, {pkg, uuid}} = uuid
  11. %% {uuid, {pkg, alias}} = uuid on disk
  12. %% another run should yield the same lock file without error
  13. init_per_suite(Config) ->
  14. Config.
  15. %% mock_config(?MODULE, Config).
  16. end_per_suite(Config) ->
  17. Config.
  18. %% unmock_config(Config).
  19. init_per_testcase(same_alias, Config0) ->
  20. mock_config(?MODULE, Config0),
  21. Config = rebar_test_utils:init_rebar_state(Config0,"same_alias_"),
  22. AppDir = ?config(apps, Config),
  23. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  24. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, {pkg, fakelib}}]}]),
  25. [{rebarconfig, RebarConf} | Config];
  26. init_per_testcase(diff_alias, Config0) ->
  27. mock_config(?MODULE, Config0),
  28. Config = rebar_test_utils:init_rebar_state(Config0,"diff_alias_"),
  29. AppDir = ?config(apps, Config),
  30. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  31. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, {pkg, goodpkg}}]}]),
  32. [{rebarconfig, RebarConf} | Config];
  33. init_per_testcase(diff_alias_vsn, Config0) ->
  34. mock_config(?MODULE, Config0),
  35. Config = rebar_test_utils:init_rebar_state(Config0,"diff_alias_vsn_"),
  36. AppDir = ?config(apps, Config),
  37. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  38. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, "1.0.0", {pkg, goodpkg}}]}]),
  39. [{rebarconfig, RebarConf} | Config];
  40. init_per_testcase(transitive_alias, Config0) ->
  41. mock_config(?MODULE, Config0),
  42. Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"),
  43. AppDir = ?config(apps, Config),
  44. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  45. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{topdep, "1.0.0", {pkg, topdep}}]}]),
  46. [{rebarconfig, RebarConf} | Config];
  47. init_per_testcase(transitive_hash_mismatch, Config0) ->
  48. mock_config(?MODULE, Config0),
  49. Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"),
  50. AppDir = ?config(apps, Config),
  51. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  52. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{topdep, "1.0.0", {pkg, topdep}}]}]),
  53. [{rebarconfig, RebarConf} | Config].
  54. end_per_testcase(_, Config) ->
  55. unmock_config(Config),
  56. Config.
  57. same_alias(Config) ->
  58. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  59. rebar_test_utils:run_and_check(
  60. Config, RebarConfig, ["lock"],
  61. {ok, [{lock, "fakelib"}, {dep, "fakelib"}]}
  62. ).
  63. diff_alias(Config) ->
  64. %% even though the dep is 'fakelib' aliased as 'goodpkg' all
  65. %% internal records use 'fakelib' as a value. Just make sure
  66. %% the lock actually maintains the proper source as 'goodpkg'
  67. AppDir = ?config(apps, Config),
  68. Lockfile = filename:join([AppDir, "rebar.lock"]),
  69. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  70. rebar_test_utils:run_and_check(
  71. Config, RebarConfig, ["lock"],
  72. {ok, [{lock, "fakelib"},{dep, "fakelib"}]}
  73. ),
  74. {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
  75. ?assert(lists:any(fun({<<"fakelib">>,{pkg,<<"goodpkg">>,_},_}) -> true
  76. ; (_) -> false end, LockData)),
  77. %% An second run yields the same
  78. rebar_test_utils:run_and_check(
  79. Config, RebarConfig, ["lock"],
  80. {ok, [{lock, "fakelib"},{dep, "fakelib"}]}
  81. ),
  82. {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
  83. %% So does an upgrade
  84. rebar_test_utils:run_and_check(
  85. Config, RebarConfig, ["upgrade"],
  86. {ok, [{lock, "fakelib"},{dep, "fakelib"}]}
  87. ),
  88. {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile).
  89. diff_alias_vsn(Config) -> diff_alias(Config).
  90. transitive_alias(Config) ->
  91. %% ensure that the apps fetched under transitive aliases are
  92. %% locked properly, but also that they are stored in the right
  93. %% directory in the build dir to avoid breaking includes and
  94. %% static analysis tools that rely on the location to work
  95. AppDir = ?config(apps, Config),
  96. Lockfile = filename:join([AppDir, "rebar.lock"]),
  97. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  98. rebar_test_utils:run_and_check(
  99. Config, RebarConfig, ["lock"],
  100. {ok, [{lock, "topdep"},{dep, "topdep"},
  101. {lock,"transitive_app"},{dep,"transitive_app"}]}
  102. ),
  103. {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
  104. ?assert(lists:any(fun({<<"transitive_app">>,{pkg,<<"transitive">>,_},_}) -> true
  105. ; (_) -> false end, LockData)),
  106. AppDir = ?config(apps, Config),
  107. AliasedName = filename:join([AppDir, "_build", "default", "lib", "transitive_app"]),
  108. PkgName = filename:join([AppDir, "_build", "default", "lib", "transitive"]),
  109. ?assert(filelib:is_dir(AliasedName)),
  110. ?assertNot(filelib:is_dir(PkgName)),
  111. %% An second run yields the same
  112. rebar_test_utils:run_and_check(
  113. Config, RebarConfig, ["lock"],
  114. {ok, [{lock, "topdep"},{dep, "topdep"},
  115. {lock,"transitive_app"},{dep,"transitive_app"}]}
  116. ),
  117. {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
  118. ?assert(filelib:is_dir(AliasedName)),
  119. ?assertNot(filelib:is_dir(PkgName)),
  120. %% So does an upgrade
  121. rebar_test_utils:run_and_check(
  122. Config, RebarConfig, ["upgrade"],
  123. {ok, [{lock, "topdep"},{dep, "topdep"},
  124. {lock,"transitive_app"},{dep,"transitive_app"}]}
  125. ),
  126. {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
  127. ?assert(filelib:is_dir(AliasedName)),
  128. ?assertNot(filelib:is_dir(PkgName)),
  129. ok.
  130. transitive_hash_mismatch(Config) ->
  131. %% ensure that the apps fetched under transitive aliases are
  132. %% locked properly, but also that they are stored in the right
  133. %% directory in the build dir to avoid breaking includes and
  134. %% static analysis tools that rely on the location to work
  135. AppDir = ?config(apps, Config),
  136. Lockfile = filename:join([AppDir, "rebar.lock"]),
  137. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  138. rebar_test_utils:run_and_check(
  139. Config, RebarConfig, ["lock"],
  140. {ok, [{lock, "topdep"},{dep, "topdep"},
  141. {lock,"transitive_app"},{dep,"transitive_app"}]}
  142. ),
  143. {ok, [LockData|Attrs]} = file:consult(Lockfile),
  144. %% Change Lock hash data to cause a failure next time, but on transitive
  145. %% deps only
  146. NewLock = [LockData|lists:map(
  147. fun([{pkg_hash, Hashes}|Rest]) ->
  148. [{pkg_hash, [{<<"transitive_app">>, <<"fakehash">>}
  149. | lists:keydelete(<<"transitive_app">>, 1, Hashes)]}
  150. | Rest]
  151. ; (Attr) ->
  152. Attr
  153. end, Attrs)],
  154. {ok, Io} = file:open(Lockfile, [write]),
  155. [io:format(Io, "~p.~n", [Attr]) || Attr <- NewLock],
  156. file:close(Io),
  157. ct:pal("lock: ~p", [file:consult(Lockfile)]),
  158. ec_file:remove(filename:join([AppDir, "_build"]), [recursive]),
  159. ?assertMatch(
  160. {error, {rebar_fetch, {unexpected_hash, _, _, _}}},
  161. rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], return)
  162. ),
  163. ok.
  164. parse_deps(Deps) ->
  165. [{maps:get(app, D, Name), {pkg, Name, Constraint, undefined}} || D=#{package := Name,
  166. requirement := Constraint} <- Deps].
  167. mock_config(Name, Config) ->
  168. {ChkFake, Etag} = create_lib(Name, Config, "fakelib"),
  169. {ChkTop, _} = create_lib(Name, Config, "topdep"),
  170. {ChkTrans, _} = create_lib(Name, Config, "transitive_app", "transitive"),
  171. ct:pal("{~p, _}",[ChkTop]),
  172. ct:pal("{~p, _}",[ChkTrans]),
  173. Priv = ?config(priv_dir, Config),
  174. TmpDir = filename:join([Priv, "tmp", atom_to_list(Name)]),
  175. %% Add an alias for goodpkg -> fakelib by hand
  176. AppDir = filename:join([Priv, "fakelib"]),
  177. CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]),
  178. CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]),
  179. rebar_test_utils:create_app(AppDir, "fakelib", "1.0.0", [kernel, stdlib]),
  180. ct:pal("{~p, ~p}",[ChkFake, Etag]),
  181. {ChkFake, Etag} = rebar_test_utils:package_app(AppDir, CacheDir, "goodpkg-1.0.0"),
  182. AllDeps = [
  183. {<<"fakelib">>,[[<<"1.0.0">>]]},
  184. {<<"goodpkg">>,[[<<"1.0.0">>]]},
  185. {<<"topdep">>,[[<<"1.0.0">>]]},
  186. {<<"transitive">>, [[<<"1.0.0">>]]},
  187. {{<<"fakelib">>,<<"1.0.0">>}, [[], ChkFake, [<<"rebar3">>]]},
  188. {{<<"goodpkg">>,<<"1.0.0">>}, [[], ChkFake, [<<"rebar3">>]]},
  189. {{<<"topdep">>,<<"1.0.0">>},
  190. [[
  191. {<<"transitive">>, <<"1.0.0">>, false, <<"transitive_app">>}
  192. ], ChkTop, [<<"rebar3">>]]},
  193. {{<<"transitive">>,<<"1.0.0">>}, [[], ChkTrans, [<<"rebar3">>]]}
  194. ],
  195. Tid = ets:new(registry_table, [public]),
  196. ets:insert_new(Tid, AllDeps),
  197. ok = ets:tab2file(Tid, filename:join([CacheDir, "registry"])),
  198. %% ets:delete(Tid),
  199. %% The state returns us a fake registry
  200. meck:new(rebar_dir, [passthrough, no_link]),
  201. meck:expect(rebar_dir, global_cache_dir, fun(_) -> CacheRoot end),
  202. meck:new(rebar_packages, [passthrough, no_link]),
  203. meck:expect(rebar_packages, registry_dir, fun(_) -> {ok, CacheDir} end),
  204. meck:expect(rebar_packages, package_dir, fun(_, _) -> {ok, CacheDir} end),
  205. %% TODO: is something else wrong that we need this for transitive_alias to pass
  206. meck:expect(rebar_packages, update_package, fun(_, _, _) -> ok end),
  207. meck:new(rebar_prv_update, [passthrough]),
  208. meck:expect(rebar_prv_update, do, fun(State) -> {ok, State} end),
  209. catch ets:delete(?PACKAGE_TABLE),
  210. rebar_packages:new_package_table(),
  211. lists:foreach(fun({{N, Vsn}, [Deps, Checksum, _]}) ->
  212. case ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(N), Vsn, <<"hexpm">>}) of
  213. false ->
  214. ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(N), Vsn, <<"hexpm">>},
  215. dependencies=[{DAppName, {pkg, DN, DV, undefined}} || {DN, DV, _, DAppName} <- Deps],
  216. retired=false,
  217. checksum=Checksum});
  218. true ->
  219. ok
  220. end;
  221. ({_N, _Vsns}) ->
  222. ok
  223. end, AllDeps),
  224. meck:expect(rebar_packages, registry_checksum,
  225. fun(N, V, _, _) ->
  226. case ets:match_object(Tid, {{N, V}, '_'}) of
  227. [{{_, _}, [_, Checksum, _]}] ->
  228. Checksum
  229. %% _ ->
  230. %% {ok, {200, #{}, #{releases => []}}}
  231. end
  232. end),
  233. meck:new(hex_repo, [passthrough]),
  234. meck:expect(hex_repo, get_package,
  235. fun(_Config, PkgName) ->
  236. case ets:match_object(Tid, {{PkgName,'_'}, '_'}) of
  237. Matches ->
  238. Releases =
  239. [#{checksum => Checksum,
  240. version => Vsn,
  241. dependencies => [{DAppName, {pkg, DN, DV, undefined}} || {DN, DV, _, DAppName} <- Deps]} ||
  242. {{_, Vsn}, [Deps, Checksum, _]} <- Matches],
  243. {ok, {200, #{}, #{releases => Releases}}}%% ;
  244. %% _ ->
  245. %% {ok, {200, #{}, #{releases => []}}}
  246. end
  247. end),
  248. meck:expect(hex_repo, get_tarball, fun(_, _, _) ->
  249. {ok, {304, #{<<"etag">> => Etag}, <<>>}}
  250. end),
  251. %% Move all packages to cache
  252. NewConf = [{cache_root, CacheRoot},
  253. {cache_dir, CacheDir},
  254. {tmp_dir, TmpDir},
  255. {mock_table, Tid} | Config],
  256. NewConf.
  257. unmock_config(Config) ->
  258. meck:unload(),
  259. Config.
  260. create_lib(Name, Config, PkgName) ->
  261. create_lib(Name, Config, PkgName, PkgName).
  262. create_lib(Name, Config, AppName, PkgName) ->
  263. Priv = ?config(priv_dir, Config),
  264. AppDir = filename:join([Priv, PkgName]),
  265. CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]),
  266. CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]),
  267. filelib:ensure_dir(filename:join([CacheDir, "registry"])),
  268. rebar_test_utils:create_app(AppDir, AppName, "1.0.0", [kernel, stdlib]),
  269. rebar_test_utils:package_app(AppDir, CacheDir, PkgName++"-1.0.0").