選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

258 行
8.5 KiB

  1. -module(rebar_dialyzer_SUITE).
  2. -export([suite/0,
  3. init_per_suite/1,
  4. end_per_suite/1,
  5. init_per_testcase/2,
  6. all/0,
  7. update_base_plt/1,
  8. update_app_plt/1,
  9. build_release_plt/1,
  10. plt_apps_option/1]).
  11. -include_lib("common_test/include/ct.hrl").
  12. -include_lib("eunit/include/eunit.hrl").
  13. -include_lib("kernel/include/file.hrl").
  14. suite() ->
  15. [].
  16. init_per_suite(Config) ->
  17. Config.
  18. end_per_suite(_Config) ->
  19. ok.
  20. init_per_testcase(Testcase, Config) ->
  21. PrivDir = ?config(priv_dir, Config),
  22. Prefix = ec_cnv:to_list(Testcase),
  23. BasePrefix = Prefix ++ "_base",
  24. Opts = [{plt_prefix, Prefix},
  25. {plt_location, PrivDir},
  26. {base_plt_prefix, BasePrefix},
  27. {base_plt_location, PrivDir},
  28. {base_plt_apps, [erts]}],
  29. Suffix = "_" ++ rebar_utils:otp_release() ++ "_plt",
  30. [{plt, filename:join(PrivDir, Prefix ++ Suffix)},
  31. {base_plt, filename:join(PrivDir, BasePrefix ++ Suffix)},
  32. {rebar_config, [{dialyzer, Opts}]} |
  33. rebar_test_utils:init_rebar_state(Config)].
  34. all() ->
  35. [update_base_plt, update_app_plt, build_release_plt, plt_apps_option].
  36. update_base_plt(Config) ->
  37. AppDir = ?config(apps, Config),
  38. RebarConfig = ?config(rebar_config, Config),
  39. BasePlt = ?config(base_plt, Config),
  40. Plt = ?config(plt, Config),
  41. Name = rebar_test_utils:create_random_name("app1_"),
  42. Vsn = rebar_test_utils:create_random_vsn(),
  43. rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]),
  44. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  45. {ok, [{app, Name}]}),
  46. ErtsFiles = erts_files(),
  47. {ok, BasePltFiles} = plt_files(BasePlt),
  48. ?assertEqual(ErtsFiles, BasePltFiles),
  49. alter_plt(BasePlt),
  50. ok = file:delete(Plt),
  51. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  52. {ok, [{app, Name}]}),
  53. {ok, BasePltFiles2} = plt_files(BasePlt),
  54. ?assertEqual(ErtsFiles, BasePltFiles2),
  55. {ok, PltFiles} = plt_files(Plt),
  56. ?assertEqual(ErtsFiles, PltFiles),
  57. add_missing_file(BasePlt),
  58. ok = file:delete(Plt),
  59. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  60. {ok, [{app, Name}]}),
  61. {ok, BasePltFiles3} = plt_files(BasePlt),
  62. ?assertEqual(ErtsFiles, BasePltFiles3).
  63. update_app_plt(Config) ->
  64. AppDir = ?config(apps, Config),
  65. RebarConfig = ?config(rebar_config, Config),
  66. Plt = ?config(plt, Config),
  67. Name = rebar_test_utils:create_random_name("app1_"),
  68. Vsn = rebar_test_utils:create_random_vsn(),
  69. rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]),
  70. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  71. {ok, [{app, Name}]}),
  72. ErtsFiles = erts_files(),
  73. {ok, PltFiles} = plt_files(Plt),
  74. ?assertEqual(ErtsFiles, PltFiles),
  75. alter_plt(Plt),
  76. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  77. {ok, [{app, Name}]}),
  78. {ok, PltFiles2} = plt_files(Plt),
  79. ?assertEqual(ErtsFiles, PltFiles2),
  80. ok = file:delete(Plt),
  81. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  82. {ok, [{app, Name}]}),
  83. {ok, PltFiles3} = plt_files(Plt),
  84. ?assertEqual(ErtsFiles, PltFiles3),
  85. add_missing_file(Plt),
  86. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  87. {ok, [{app, Name}]}),
  88. {ok, PltFiles4} = plt_files(Plt),
  89. ?assertEqual(ErtsFiles, PltFiles4).
  90. build_release_plt(Config) ->
  91. AppDir = ?config(apps, Config),
  92. RebarConfig = ?config(rebar_config, Config),
  93. BasePlt = ?config(base_plt, Config),
  94. Plt = ?config(plt, Config),
  95. Name1 = rebar_test_utils:create_random_name("relapp1_"),
  96. Vsn1 = rebar_test_utils:create_random_vsn(),
  97. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1,
  98. [erts]),
  99. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  100. Vsn2 = rebar_test_utils:create_random_vsn(),
  101. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2,
  102. [erts, ec_cnv:to_atom(Name1)]),
  103. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  104. {ok, [{app, Name1}, {app, Name2}]}),
  105. ErtsFiles = erts_files(),
  106. {ok, BasePltFiles} = plt_files(BasePlt),
  107. ?assertEqual(ErtsFiles, BasePltFiles),
  108. {ok, PltFiles} = plt_files(Plt),
  109. ?assertEqual(ErtsFiles, PltFiles).
  110. plt_apps_option(Config) ->
  111. AppDir = ?config(apps, Config),
  112. RebarConfig = ?config(rebar_config, Config),
  113. Plt = ?config(plt, Config),
  114. State = ?config(state, Config),
  115. %% Create applications
  116. Name1 = rebar_test_utils:create_random_name("app1_"),
  117. Vsn1 = rebar_test_utils:create_random_vsn(),
  118. rebar_test_utils:create_app(filename:join([AppDir,"deps",Name1]), Name1, Vsn1,
  119. []),
  120. App1 = ec_cnv:to_atom(Name1),
  121. Name2 = rebar_test_utils:create_random_name("app2_"),
  122. Vsn2 = rebar_test_utils:create_random_vsn(),
  123. rebar_test_utils:create_app(filename:join([AppDir,"deps",Name2]), Name2, Vsn2,
  124. [App1]), % App2 depends on App1
  125. App2 = ec_cnv:to_atom(Name2),
  126. Name3 = rebar_test_utils:create_random_name("app3_"), % the project application
  127. Vsn3 = rebar_test_utils:create_random_vsn(),
  128. rebar_test_utils:create_app(AppDir, Name3, Vsn3,
  129. [App2]), % App3 depends on App2
  130. %% Dependencies settings
  131. State1 = rebar_state:add_resource(State, {localfs, rebar_localfs_resource}),
  132. Config1 = [{state, State1} | Config],
  133. RebarConfig1 = merge_config(
  134. [{deps,
  135. [
  136. {App1, {localfs, filename:join([AppDir,"deps",Name1])}},
  137. {App2, {localfs, filename:join([AppDir,"deps",Name2])}}
  138. ]}],
  139. RebarConfig),
  140. %% Dialyzer: plt_apps = top_level_deps (default)
  141. rebar_test_utils:run_and_check(Config1, RebarConfig1, ["dialyzer"],
  142. {ok, [{app, Name3}]}),
  143. %% NOTE: `erts` is included in `base_plt_apps`
  144. {ok, PltFiles1} = plt_files(Plt),
  145. ?assertEqual([App2, erts], get_apps_from_beam_files(PltFiles1)),
  146. %% Dialyzer: plt_apps = all_deps
  147. RebarConfig2 = merge_config([{dialyzer, [{plt_apps, all_deps}]}],
  148. RebarConfig1),
  149. rebar_test_utils:run_and_check(Config1, RebarConfig2, ["dialyzer"],
  150. {ok, [{app, Name3}]}),
  151. {ok, PltFiles2} = plt_files(Plt),
  152. ?assertEqual([App1, App2, erts], get_apps_from_beam_files(PltFiles2)).
  153. %% Helpers
  154. erts_files() ->
  155. ErtsDir = code:lib_dir(erts, ebin),
  156. ErtsBeams = filelib:wildcard("*.beam", ErtsDir),
  157. ErtsFiles = lists:map(fun(Beam) -> filename:join(ErtsDir, Beam) end,
  158. ErtsBeams),
  159. lists:sort(ErtsFiles).
  160. plt_files(Plt) ->
  161. case dialyzer:plt_info(Plt) of
  162. {ok, Info} ->
  163. Files = proplists:get_value(files, Info),
  164. {ok, lists:sort(Files)};
  165. Other ->
  166. Other
  167. end.
  168. alter_plt(Plt) ->
  169. {ok, Files} = plt_files(Plt),
  170. _ = dialyzer:run([{analysis_type, plt_remove},
  171. {init_plt, Plt},
  172. {files, [hd(Files)]}]),
  173. _ = dialyzer:run([{analysis_type, plt_add},
  174. {init_plt, Plt},
  175. {files, [code:which(dialyzer)]}]),
  176. ok.
  177. add_missing_file(Plt) ->
  178. Source = code:which(dialyzer),
  179. Dest = filename:join(filename:dirname(Plt), "dialyzer.beam"),
  180. {ok, _} = file:copy(Source, Dest),
  181. _ = try
  182. dialyzer:run([{analysis_type, plt_add},
  183. {init_plt, Plt},
  184. {files, [Dest]}])
  185. after
  186. ok = file:delete(Dest)
  187. end,
  188. ok.
  189. -spec merge_config(Config, Config) -> Config when
  190. Config :: [{term(), term()}].
  191. merge_config(NewConfig, OldConfig) ->
  192. dict:to_list(
  193. rebar_opts:merge_opts(dict:from_list(NewConfig),
  194. dict:from_list(OldConfig))).
  195. -spec get_apps_from_beam_files(string()) -> [atom()].
  196. get_apps_from_beam_files(BeamFiles) ->
  197. lists:usort(
  198. [begin
  199. AppNameVsn = filename:basename(filename:dirname(filename:dirname(File))),
  200. [AppName | _] = string:tokens(AppNameVsn ++ "-", "-"),
  201. ec_cnv:to_atom(AppName)
  202. end || File <- BeamFiles]).