Вы не можете выбрать более 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]).