You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
14 KiB

  1. %% Test suite for the handling hexpm repo configurations
  2. -module(rebar_pkg_repos_SUITE).
  3. -compile(export_all).
  4. -include_lib("common_test/include/ct.hrl").
  5. -include_lib("eunit/include/eunit.hrl").
  6. -include("rebar.hrl").
  7. all() ->
  8. [default_repo, repo_merging, repo_replacing,
  9. auth_merging, organization_merging, {group, resolve_version}].
  10. groups() ->
  11. [{resolve_version, [use_first_repo_match, use_exact_with_hash, fail_repo_update,
  12. ignore_match_in_excluded_repo]}].
  13. init_per_group(resolve_version, Config) ->
  14. Repo1 = <<"test-repo-1">>,
  15. Repo2 = <<"test-repo-2">>,
  16. Repo3 = <<"test-repo-3">>,
  17. Hexpm = <<"hexpm">>,
  18. Repos = [Repo1, Repo2, Repo3, Hexpm],
  19. Deps = [{"A", "0.1.1", <<"good checksum">>, Repo1},
  20. {"A", "0.1.1", <<"good checksum">>, Repo2},
  21. {"B", "1.0.0", Repo1},
  22. {"B", "2.0.0", Repo2},
  23. {"B", "1.4.0", Repo3},
  24. {"B", "1.4.3", Hexpm},
  25. {"C", "1.3.1", <<"bad checksum">>, Repo1},
  26. {"C", "1.3.1", <<"good checksum">>, Repo2}],
  27. [{deps, Deps}, {repos, Repos} | Config];
  28. init_per_group(_, Config) ->
  29. Config.
  30. end_per_group(_, _) ->
  31. ok.
  32. init_per_testcase(use_first_repo_match, Config) ->
  33. Deps = ?config(deps, Config),
  34. Repos = ?config(repos, Config),
  35. State = setup_deps_and_repos(Deps, Repos),
  36. meck:new(rebar_packages, [passthrough, no_link]),
  37. %% fail when the first repo is updated since it doesn't have a matching package
  38. %% should continue anyway
  39. meck:expect(rebar_packages, update_package,
  40. fun(_, _, _State) -> ok end),
  41. meck:expect(rebar_packages, verify_table,
  42. fun(_State) -> true end),
  43. [{state, State} | Config];
  44. init_per_testcase(use_exact_with_hash, Config) ->
  45. Deps = ?config(deps, Config),
  46. Repos = ?config(repos, Config),
  47. State = setup_deps_and_repos(Deps, Repos),
  48. meck:new(rebar_packages, [passthrough, no_link]),
  49. %% fail when the first repo is updated since it doesn't have a matching package
  50. %% should continue anyway
  51. meck:expect(rebar_packages, update_package,
  52. fun(_, _, _State) -> ok end),
  53. meck:expect(rebar_packages, verify_table,
  54. fun(_State) -> true end),
  55. [{state, State} | Config];
  56. init_per_testcase(fail_repo_update, Config) ->
  57. Deps = ?config(deps, Config),
  58. Repos = ?config(repos, Config),
  59. State = setup_deps_and_repos(Deps, Repos),
  60. meck:new(rebar_packages, [passthrough, no_link]),
  61. %% fail when the first repo is updated since it doesn't have a matching package
  62. %% should continue anyway
  63. [Repo1 | _] = Repos,
  64. meck:expect(rebar_packages, update_package,
  65. fun(_, #{name := Repo}, _State) when Repo =:= Repo1 -> fail;
  66. (_, _, _State) -> ok end),
  67. meck:expect(rebar_packages, verify_table,
  68. fun(_State) -> true end),
  69. [{state, State} | Config];
  70. init_per_testcase(ignore_match_in_excluded_repo, Config) ->
  71. Deps = ?config(deps, Config),
  72. Repos = [Repo1, _, Repo3 | _] = ?config(repos, Config),
  73. %% drop repo1 and repo2 from the repos to be used by the pkg resource
  74. State = setup_deps_and_repos(Deps, [R || R <- Repos, R =/= Repo3, R =/= Repo1]),
  75. meck:new(rebar_packages, [passthrough, no_link]),
  76. %% fail when the first repo is updated since it doesn't have a matching package
  77. %% should continue anyway
  78. [_, _, Repo3 | _] = Repos,
  79. meck:expect(rebar_packages, update_package,
  80. fun(_, _, _State) -> ok end),
  81. meck:expect(rebar_packages, verify_table,
  82. fun(_State) -> true end),
  83. [{state, State} | Config];
  84. init_per_testcase(auth_merging, Config) ->
  85. meck:new(file, [passthrough, no_link, unstick]),
  86. meck:new(rebar_packages, [passthrough, no_link]),
  87. Config;
  88. init_per_testcase(organization_merging, Config) ->
  89. meck:new(file, [passthrough, no_link, unstick]),
  90. meck:new(rebar_packages, [passthrough, no_link]),
  91. Config;
  92. init_per_testcase(_, Config) ->
  93. Config.
  94. end_per_testcase(Case, _Config) when Case =:= auth_merging ;
  95. Case =:= organization_merging ->
  96. meck:unload(file),
  97. meck:unload(rebar_packages);
  98. end_per_testcase(Case, _Config) when Case =:= use_first_repo_match ;
  99. Case =:= use_exact_with_hash ;
  100. Case =:= fail_repo_update ;
  101. Case =:= ignore_match_in_excluded_repo ->
  102. meck:unload(rebar_packages);
  103. end_per_testcase(_, _) ->
  104. ok.
  105. default_repo(_Config) ->
  106. Repo1 = #{name => <<"hexpm">>,
  107. api_key => <<"asdf">>},
  108. MergedRepos = rebar_hex_repos:repos([{repos, [Repo1]}]),
  109. ?assertMatch([#{name := <<"hexpm">>,
  110. api_key := <<"asdf">>,
  111. api_url := <<"https://hex.pm/api">>}], MergedRepos).
  112. repo_merging(_Config) ->
  113. Repo1 = #{name => <<"repo-1">>,
  114. api_url => <<"repo-1/api">>},
  115. Repo2 = #{name => <<"repo-2">>,
  116. repo_url => <<"repo-2/repo">>,
  117. repo_verify => false},
  118. Result = rebar_hex_repos:merge_repos([Repo1, Repo2,
  119. #{name => <<"repo-2">>,
  120. api_url => <<"repo-2/api">>,
  121. repo_url => <<"bad url">>,
  122. repo_verify => true},
  123. #{name => <<"repo-1">>,
  124. api_url => <<"bad url">>,
  125. repo_verify => true},
  126. #{name => <<"repo-2">>,
  127. api_url => <<"repo-2/api-2">>,
  128. repo_url => <<"other/repo">>}]),
  129. ?assertMatch([#{name := <<"repo-1">>,
  130. api_url := <<"repo-1/api">>,
  131. repo_verify := true},
  132. #{name := <<"repo-2">>,
  133. api_url := <<"repo-2/api">>,
  134. repo_url := <<"repo-2/repo">>,
  135. repo_verify := false}], Result).
  136. repo_replacing(_Config) ->
  137. Repo1 = #{name => <<"repo-1">>,
  138. api_url => <<"repo-1/api">>},
  139. Repo2 = #{name => <<"repo-2">>,
  140. repo_url => <<"repo-2/repo">>,
  141. repo_verify => false},
  142. ?assertMatch([Repo1, Repo2, #{name := <<"hexpm">>}],
  143. rebar_hex_repos:repos([{repos, [Repo1]},
  144. {repos, [Repo2]}])),
  145. %% use of replace is ignored if found in later entries than the first
  146. ?assertMatch([Repo1, Repo2, #{name := <<"hexpm">>}],
  147. rebar_hex_repos:repos([{repos, [Repo1]},
  148. {repos, replace, [Repo2]}])),
  149. ?assertMatch([Repo1],
  150. rebar_hex_repos:repos([{repos, replace, [Repo1]},
  151. {repos, [Repo2]}])).
  152. auth_merging(_Config) ->
  153. Repo1 = #{name => <<"repo-1">>,
  154. api_url => <<"repo-1/api">>},
  155. Repo2 = #{name => <<"repo-2">>,
  156. repo_url => <<"repo-2/repo">>,
  157. repo_verify => false},
  158. State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]),
  159. meck:expect(file, consult,
  160. fun(_) ->
  161. {ok, [#{<<"repo-1">> => #{read_key => <<"read key">>,
  162. write_key => <<"write key">>},
  163. <<"repo-2">> => #{read_key => <<"read key 2">>,
  164. repos_key => <<"repos key 2">>,
  165. write_key => <<"write key 2">>},
  166. <<"hexpm">> => #{write_key => <<"write key hexpm">>}}]}
  167. end),
  168. ?assertMatch({ok,
  169. #resource{state=#{repos := [#{name := <<"repo-1">>,
  170. read_key := <<"read key">>,
  171. write_key := <<"write key">>},
  172. #{name := <<"repo-2">>,
  173. read_key := <<"read key 2">>,
  174. repos_key := <<"repos key 2">>,
  175. write_key := <<"write key 2">>},
  176. #{name := <<"hexpm">>,
  177. write_key := <<"write key hexpm">>}]}}},
  178. rebar_pkg_resource:init(pkg, State)),
  179. ok.
  180. organization_merging(_Config) ->
  181. Repo1 = #{name => <<"hexpm:repo-1">>,
  182. api_url => <<"repo-1/api">>},
  183. Repo2 = #{name => <<"hexpm:repo-2">>,
  184. repo_url => <<"repo-2/repo">>,
  185. repo_verify => false},
  186. State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]),
  187. meck:expect(file, consult,
  188. fun(_) ->
  189. {ok, [#{<<"hexpm:repo-1">> => #{read_key => <<"read key">>},
  190. <<"hexpm:repo-2">> => #{read_key => <<"read key 2">>,
  191. repos_key => <<"repos key 2">>,
  192. write_key => <<"write key 2">>},
  193. <<"hexpm">> => #{write_key => <<"write key hexpm">>}}]}
  194. end),
  195. ?assertMatch({ok,
  196. #resource{state=#{repos := [#{name := <<"hexpm:repo-1">>,
  197. parent := <<"hexpm">>,
  198. read_key := <<"read key">>,
  199. write_key := <<"write key hexpm">>},
  200. #{name := <<"hexpm:repo-2">>,
  201. parent := <<"hexpm">>,
  202. read_key := <<"read key 2">>,
  203. repos_key := <<"repos key 2">>,
  204. write_key := <<"write key 2">>},
  205. #{name := <<"hexpm">>,
  206. write_key := <<"write key hexpm">>}]}}},
  207. rebar_pkg_resource:init(pkg, State)),
  208. ok.
  209. use_first_repo_match(Config) ->
  210. State = ?config(state, Config),
  211. ?assertMatch({ok,{package,{<<"B">>, <<"2.0.0">>, Repo2},
  212. <<"some checksum">>, false, []},
  213. #{name := Repo2,
  214. http_adapter_config := #{profile := rebar}}},
  215. rebar_packages:resolve_version(<<"B">>, <<"> 1.4.0">>, undefined,
  216. ?PACKAGE_TABLE, State)),
  217. ?assertMatch({ok,{package,{<<"B">>, <<"1.4.0">>, Repo3},
  218. <<"some checksum">>, false, []},
  219. #{name := Repo3,
  220. http_adapter_config := #{profile := rebar}}},
  221. rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined,
  222. ?PACKAGE_TABLE, State)).
  223. %% tests that even though an easier repo has C-1.3.1 it doesn't use it since its hash is different
  224. use_exact_with_hash(Config) ->
  225. State = ?config(state, Config),
  226. ?assertMatch({ok,{package,{<<"C">>, <<"1.3.1">>, Repo2},
  227. <<"good checksum">>, false, []},
  228. #{name := Repo2,
  229. http_adapter_config := #{profile := rebar}}},
  230. rebar_packages:resolve_version(<<"C">>, <<"1.3.1">>, <<"good checksum">>,
  231. ?PACKAGE_TABLE, State)).
  232. fail_repo_update(Config) ->
  233. State = ?config(state, Config),
  234. ?assertMatch({ok,{package,{<<"B">>, <<"1.4.0">>, Repo3},
  235. <<"some checksum">>, false, []},
  236. #{name := Repo3,
  237. http_adapter_config := #{profile := rebar}}},
  238. rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined,
  239. ?PACKAGE_TABLE, State)).
  240. ignore_match_in_excluded_repo(Config) ->
  241. State = ?config(state, Config),
  242. Repos = ?config(repos, Config),
  243. ?assertMatch({ok,{package,{<<"B">>, <<"1.4.3">>, Hexpm},
  244. <<"some checksum">>, false, []},
  245. #{name := Hexpm,
  246. http_adapter_config := #{profile := rebar}}},
  247. rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined,
  248. ?PACKAGE_TABLE, State)),
  249. [_, Repo2 | _] = Repos,
  250. ?assertMatch({ok,{package,{<<"A">>, <<"0.1.1">>, Repo2},
  251. <<"good checksum">>, false, []},
  252. #{name := Repo2,
  253. http_adapter_config := #{profile := rebar}}},
  254. rebar_packages:resolve_version(<<"A">>, <<"0.1.1">>, <<"good checksum">>,
  255. ?PACKAGE_TABLE, State)).
  256. %%
  257. setup_deps_and_repos(Deps, Repos) ->
  258. true = rebar_packages:new_package_table(),
  259. insert_deps(Deps),
  260. State = rebar_state:new([{hex, [{repos, [#{name => R} || R <- Repos]}]}]),
  261. rebar_state:create_resources([{pkg, rebar_pkg_resource}], State).
  262. insert_deps(Deps) ->
  263. lists:foreach(fun({Name, Version, Repo}) ->
  264. ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(Name),
  265. rebar_utils:to_binary(Version),
  266. rebar_utils:to_binary(Repo)},
  267. dependencies=[],
  268. retired=false,
  269. checksum = <<"some checksum">>});
  270. ({Name, Version, Checksum, Repo}) ->
  271. ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(Name),
  272. rebar_utils:to_binary(Version),
  273. rebar_utils:to_binary(Repo)},
  274. dependencies=[],
  275. retired=false,
  276. checksum = Checksum})
  277. end, Deps).