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.

319 line
10 KiB

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