Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

208 рядки
6.6 KiB

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
  1. -module(rebar_install_deps_SUITE).
  2. -compile(export_all).
  3. -include_lib("common_test/include/ct.hrl").
  4. -include_lib("eunit/include/eunit.hrl").
  5. all() -> [{group, git}, {group, pkg}].
  6. groups() ->
  7. [{all, [], [flat, pick_highest_left, pick_highest_right,
  8. pick_smallest1, pick_smallest2,
  9. circular1, circular2, circular_skip,
  10. fail_conflict]},
  11. {git, [], [{group, all}]},
  12. {pkg, [], [{group, all}]}].
  13. init_per_suite(Config) ->
  14. application:start(meck),
  15. Config.
  16. end_per_suite(_Config) ->
  17. application:stop(meck).
  18. init_per_group(git, Config) ->
  19. [{deps_type, git} | Config];
  20. init_per_group(pkg, Config) ->
  21. [{deps_type, pkg} | Config];
  22. init_per_group(_, Config) ->
  23. Config.
  24. end_per_group(_, Config) ->
  25. Config.
  26. init_per_testcase(Case, Config) ->
  27. {Deps, Warnings, Expect} = deps(Case),
  28. Expected = case Expect of
  29. {ok, List} -> {ok, format_expected_deps(List)};
  30. Other -> Other
  31. end,
  32. DepsType = ?config(deps_type, Config),
  33. mock_warnings(),
  34. [{expect, Expected},
  35. {warnings, Warnings}
  36. | setup_project(Case, Config, rebar_test_utils:expand_deps(DepsType, Deps))].
  37. end_per_testcase(_, Config) ->
  38. meck:unload(),
  39. Config.
  40. format_expected_deps(Deps) ->
  41. [case Dep of
  42. {N,V} -> {dep, N, V};
  43. N -> {dep, N}
  44. end || Dep <- Deps].
  45. %% format:
  46. %% {Spec,
  47. %% [Warning],
  48. %% {ok, Result} | {error, Reason}}
  49. %%
  50. %% Spec is a list of levelled dependencies of two possible forms:
  51. %% - {"Name", Spec}
  52. %% - {"Name", "Vsn", Spec}
  53. %%
  54. %% Warnings are going to match on mocked ?WARN(...)
  55. %% calls to be evaluated. An empty list means we do not care about
  56. %% warnings, not that no warnings will be printed. This means
  57. %% the list of warning isn't interpreted to be exhaustive, and more
  58. %% warnings may be generated than are listed.
  59. deps(flat) ->
  60. {[{"B", []},
  61. {"C", []}],
  62. [],
  63. {ok, ["B", "C"]}};
  64. deps(pick_highest_left) ->
  65. {[{"B", [{"C", "2", []}]},
  66. {"C", "1", []}],
  67. [{"C","2"}],
  68. {ok, ["B", {"C", "1"}]}};
  69. deps(pick_highest_right) ->
  70. {[{"B", "1", []},
  71. {"C", [{"B", "2", []}]}],
  72. [{"B","2"}],
  73. {ok, [{"B","1"}, "C"]}};
  74. deps(pick_smallest1) ->
  75. {[{"B", [{"D", "1", []}]},
  76. {"C", [{"D", "2", []}]}],
  77. [{"D","2"}],
  78. %% we pick D1 because B < C
  79. {ok, ["B","C",{"D","1"}]}};
  80. deps(pick_smallest2) ->
  81. {[{"C", [{"D", "2", []}]},
  82. {"B", [{"D", "1", []}]}],
  83. [{"D","2"}],
  84. %% we pick D1 because B < C
  85. {ok, ["B","C",{"D","1"}]}};
  86. deps(circular1) ->
  87. {[{"B", [{"A", []}]}, % A is the top-level app
  88. {"C", []}],
  89. [],
  90. {error, {rebar_prv_install_deps, {cycles, [[<<"A">>,<<"B">>]]}}}};
  91. deps(circular2) ->
  92. {[{"B", [{"C", [{"B", []}]}]},
  93. {"C", []}],
  94. [],
  95. {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}};
  96. deps(circular_skip) ->
  97. %% Never spot the circular dep due to being to low in the deps tree
  98. %% in source deps
  99. {[{"B", [{"C", "2", [{"B", []}]}]},
  100. {"C", "1", [{"D",[]}]}],
  101. [{"C","2"}],
  102. {ok, ["B", {"C","1"}, "D"]}};
  103. deps(fail_conflict) ->
  104. {[{"B", [{"C", "2", []}]},
  105. {"C", "1", []}],
  106. [{"C","2"}],
  107. rebar_abort}.
  108. setup_project(fail_conflict, Config0, Deps) ->
  109. DepsType = ?config(deps_type, Config0),
  110. Config = rebar_test_utils:init_rebar_state(
  111. Config0,
  112. "fail_conflict_"++atom_to_list(DepsType)++"_"
  113. ),
  114. AppDir = ?config(apps, Config),
  115. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  116. TopDeps = rebar_test_utils:top_level_deps(Deps),
  117. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps},
  118. {deps_error_on_conflict, true}]),
  119. case DepsType of
  120. git ->
  121. mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]);
  122. pkg ->
  123. mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}])
  124. end,
  125. [{rebarconfig, RebarConf} | Config];
  126. setup_project(Case, Config0, Deps) ->
  127. DepsType = ?config(deps_type, Config0),
  128. Config = rebar_test_utils:init_rebar_state(
  129. Config0,
  130. atom_to_list(Case)++"_installdeps_"++atom_to_list(DepsType)++"_"
  131. ),
  132. AppDir = ?config(apps, Config),
  133. rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
  134. TopDeps = rebar_test_utils:top_level_deps(Deps),
  135. RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
  136. case DepsType of
  137. git ->
  138. mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]);
  139. pkg ->
  140. mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}])
  141. end,
  142. [{rebarconfig, RebarConf} | Config].
  143. mock_warnings() ->
  144. %% just let it do its thing, we check warnings through
  145. %% the call log.
  146. meck:new(rebar_log, [no_link, passthrough]).
  147. %%% TESTS %%%
  148. flat(Config) -> run(Config).
  149. pick_highest_left(Config) -> run(Config).
  150. pick_highest_right(Config) -> run(Config).
  151. pick_smallest1(Config) -> run(Config).
  152. pick_smallest2(Config) -> run(Config).
  153. circular1(Config) -> run(Config).
  154. circular2(Config) -> run(Config).
  155. circular_skip(Config) -> run(Config).
  156. fail_conflict(Config) ->
  157. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  158. rebar_test_utils:run_and_check(
  159. Config, RebarConfig, ["install_deps"], ?config(expect, Config)
  160. ),
  161. check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)).
  162. run(Config) ->
  163. {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
  164. rebar_test_utils:run_and_check(
  165. Config, RebarConfig, ["install_deps"], ?config(expect, Config)
  166. ),
  167. check_warnings(warning_calls(), ?config(warnings, Config), ?config(deps_type, Config)).
  168. warning_calls() ->
  169. History = meck:history(rebar_log),
  170. [{Str, Args} || {_, {rebar_log, log, [warn, Str, Args]}, _} <- History].
  171. error_calls() ->
  172. History = meck:history(rebar_log),
  173. [{Str, Args} || {_, {rebar_log, log, [error, Str, Args]}, _} <- History].
  174. check_warnings(_, [], _) ->
  175. ok;
  176. check_warnings(Warns, [{Name, Vsn} | Rest], Type) ->
  177. ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]),
  178. ?assert(in_warnings(Type, Warns, Name, Vsn)),
  179. check_warnings(Warns, Rest, Type).
  180. in_warnings(git, Warns, NameRaw, VsnRaw) ->
  181. Name = iolist_to_binary(NameRaw),
  182. 1 =< length([1 || {_, [AppName, {git, _, {_, Vsn}}]} <- Warns,
  183. AppName =:= Name, Vsn =:= VsnRaw]);
  184. in_warnings(pkg, Warns, NameRaw, VsnRaw) ->
  185. Name = iolist_to_binary(NameRaw),
  186. Vsn = iolist_to_binary(VsnRaw),
  187. 1 =< length([1 || {_, [AppName, AppVsn]} <- Warns,
  188. AppName =:= Name, AppVsn =:= Vsn]).