Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

405 lignes
14 KiB

il y a 8 ans
il y a 8 ans
il y a 8 ans
il y a 8 ans
il y a 8 ans
il y a 8 ans
il y a 9 ans
il y a 9 ans
il y a 9 ans
il y a 9 ans
  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. empty_app_succ_typings/1,
  13. update_base_plt/1,
  14. update_app_plt/1,
  15. build_release_plt/1,
  16. plt_apps_option/1,
  17. exclude_and_extra/1,
  18. cli_args/1]).
  19. -include_lib("common_test/include/ct.hrl").
  20. -include_lib("eunit/include/eunit.hrl").
  21. -include_lib("kernel/include/file.hrl").
  22. suite() ->
  23. [].
  24. init_per_suite(Config) ->
  25. Config.
  26. end_per_suite(_Config) ->
  27. ok.
  28. init_per_group(empty, Config) ->
  29. [{base_plt_apps, []} | Config];
  30. init_per_group(_Group, Config) ->
  31. [{base_plt_apps, [erts]} | Config].
  32. end_per_group(_Group, _Config) ->
  33. ok.
  34. init_per_testcase(Testcase, Config) ->
  35. PrivDir = ?config(priv_dir, Config),
  36. Prefix = ec_cnv:to_list(Testcase),
  37. BasePrefix = Prefix ++ "_base",
  38. Opts = [{plt_prefix, Prefix},
  39. {plt_location, PrivDir},
  40. {base_plt_prefix, BasePrefix},
  41. {base_plt_location, PrivDir},
  42. {base_plt_apps, ?config(base_plt_apps, Config)}],
  43. Suffix = "_" ++ rebar_utils:otp_release() ++ "_plt",
  44. [{plt, filename:join(PrivDir, Prefix ++ Suffix)},
  45. {base_plt, filename:join(PrivDir, BasePrefix ++ Suffix)},
  46. {rebar_config, [{dialyzer, Opts}]} |
  47. rebar_test_utils:init_rebar_state(Config)].
  48. all() ->
  49. [{group, empty}, {group, build_and_check}, {group, update}].
  50. groups() ->
  51. [{empty, [empty_base_plt, empty_app_plt, empty_app_succ_typings]},
  52. {build_and_check, [cli_args, build_release_plt, plt_apps_option, exclude_and_extra]},
  53. {update, [update_base_plt, update_app_plt]}].
  54. empty_base_plt(Config) ->
  55. AppDir = ?config(apps, Config),
  56. RebarConfig = ?config(rebar_config, Config),
  57. BasePlt = ?config(base_plt, Config),
  58. Plt = ?config(plt, Config),
  59. Name = rebar_test_utils:create_random_name("app1_"),
  60. Vsn = rebar_test_utils:create_random_vsn(),
  61. rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]),
  62. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  63. {ok, [{app, Name}]}),
  64. {ok, BasePltFiles} = plt_files(BasePlt),
  65. ?assertEqual([], BasePltFiles),
  66. ErtsFiles = erts_files(),
  67. {ok, PltFiles} = plt_files(Plt),
  68. ?assertEqual(ErtsFiles, PltFiles),
  69. ok.
  70. empty_app_plt(Config) ->
  71. AppDir = ?config(apps, Config),
  72. RebarConfig = ?config(rebar_config, Config),
  73. BasePlt = ?config(base_plt, Config),
  74. Plt = ?config(plt, Config),
  75. Name = rebar_test_utils:create_random_name("app1_"),
  76. Vsn = rebar_test_utils:create_random_vsn(),
  77. rebar_test_utils:create_app(AppDir, Name, Vsn, []),
  78. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  79. {ok, [{app, Name}]}),
  80. {ok, BasePltFiles} = plt_files(BasePlt),
  81. ?assertEqual([], BasePltFiles),
  82. {ok, PltFiles} = plt_files(Plt),
  83. ?assertEqual([], PltFiles),
  84. ok.
  85. empty_app_succ_typings(Config) ->
  86. AppDir = ?config(apps, Config),
  87. RebarConfig = ?config(rebar_config, Config),
  88. Name = rebar_test_utils:create_random_name("app1_"),
  89. Vsn = rebar_test_utils:create_random_vsn(),
  90. rebar_test_utils:create_empty_app(AppDir, Name, Vsn, []),
  91. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  92. {ok, [{app, Name}]}),
  93. ok.
  94. update_base_plt(Config) ->
  95. AppDir = ?config(apps, Config),
  96. RebarConfig = ?config(rebar_config, Config),
  97. BasePlt = ?config(base_plt, Config),
  98. Plt = ?config(plt, Config),
  99. Name = rebar_test_utils:create_random_name("app1_"),
  100. Vsn = rebar_test_utils:create_random_vsn(),
  101. rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]),
  102. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  103. {ok, [{app, Name}]}),
  104. ErtsFiles = erts_files(),
  105. {ok, BasePltFiles} = plt_files(BasePlt),
  106. ?assertEqual(ErtsFiles, BasePltFiles),
  107. alter_plt(BasePlt),
  108. ok = file:delete(Plt),
  109. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  110. {ok, [{app, Name}]}),
  111. {ok, BasePltFiles2} = plt_files(BasePlt),
  112. ?assertEqual(ErtsFiles, BasePltFiles2),
  113. {ok, PltFiles} = plt_files(Plt),
  114. ?assertEqual(ErtsFiles, PltFiles),
  115. add_missing_file(BasePlt),
  116. ok = file:delete(Plt),
  117. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  118. {ok, [{app, Name}]}),
  119. {ok, BasePltFiles3} = plt_files(BasePlt),
  120. ?assertEqual(ErtsFiles, BasePltFiles3).
  121. update_app_plt(Config) ->
  122. AppDir = ?config(apps, Config),
  123. RebarConfig = ?config(rebar_config, Config),
  124. Plt = ?config(plt, Config),
  125. Name = rebar_test_utils:create_random_name("app1_"),
  126. Vsn = rebar_test_utils:create_random_vsn(),
  127. rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]),
  128. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  129. {ok, [{app, Name}]}),
  130. ErtsFiles = erts_files(),
  131. {ok, PltFiles} = plt_files(Plt),
  132. ?assertEqual(ErtsFiles, PltFiles),
  133. alter_plt(Plt),
  134. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  135. {ok, [{app, Name}]}),
  136. {ok, PltFiles2} = plt_files(Plt),
  137. ?assertEqual(ErtsFiles, PltFiles2),
  138. ok = file:delete(Plt),
  139. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  140. {ok, [{app, Name}]}),
  141. {ok, PltFiles3} = plt_files(Plt),
  142. ?assertEqual(ErtsFiles, PltFiles3),
  143. add_missing_file(Plt),
  144. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  145. {ok, [{app, Name}]}),
  146. {ok, PltFiles4} = plt_files(Plt),
  147. ?assertEqual(ErtsFiles, PltFiles4).
  148. build_release_plt(Config) ->
  149. AppDir = ?config(apps, Config),
  150. RebarConfig = ?config(rebar_config, Config),
  151. BasePlt = ?config(base_plt, Config),
  152. Plt = ?config(plt, Config),
  153. Name1 = rebar_test_utils:create_random_name("relapp1_"),
  154. Vsn1 = rebar_test_utils:create_random_vsn(),
  155. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1,
  156. [erts]),
  157. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  158. Vsn2 = rebar_test_utils:create_random_vsn(),
  159. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2,
  160. [erts, ec_cnv:to_atom(Name1)]),
  161. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"],
  162. {ok, [{app, Name1}, {app, Name2}]}),
  163. ErtsFiles = erts_files(),
  164. {ok, BasePltFiles} = plt_files(BasePlt),
  165. ?assertEqual(ErtsFiles, BasePltFiles),
  166. {ok, PltFiles} = plt_files(Plt),
  167. ?assertEqual(ErtsFiles, PltFiles).
  168. plt_apps_option(Config) ->
  169. AppDir = ?config(apps, Config),
  170. RebarConfig = ?config(rebar_config, Config),
  171. Plt = ?config(plt, Config),
  172. State = ?config(state, Config),
  173. %% Create applications
  174. Name1 = rebar_test_utils:create_random_name("app1_"),
  175. Vsn1 = rebar_test_utils:create_random_vsn(),
  176. rebar_test_utils:create_app(filename:join([AppDir,"deps",Name1]), Name1, Vsn1,
  177. []),
  178. App1 = ec_cnv:to_atom(Name1),
  179. Name2 = rebar_test_utils:create_random_name("app2_"),
  180. Vsn2 = rebar_test_utils:create_random_vsn(),
  181. rebar_test_utils:create_app(filename:join([AppDir,"deps",Name2]), Name2, Vsn2,
  182. [App1]), % App2 depends on App1
  183. App2 = ec_cnv:to_atom(Name2),
  184. Name3 = rebar_test_utils:create_random_name("app3_"), % the project application
  185. Vsn3 = rebar_test_utils:create_random_vsn(),
  186. rebar_test_utils:create_app(AppDir, Name3, Vsn3,
  187. [App2]), % App3 depends on App2
  188. %% Dependencies settings
  189. State1 = rebar_state:add_resource(State, {localfs, rebar_localfs_resource}),
  190. Config1 = [{state, State1} | Config],
  191. RebarConfig1 = merge_config(
  192. [{deps,
  193. [
  194. {App1, {localfs, filename:join([AppDir,"deps",Name1])}},
  195. {App2, {localfs, filename:join([AppDir,"deps",Name2])}}
  196. ]}],
  197. RebarConfig),
  198. %% Dialyzer: plt_apps = top_level_deps (default)
  199. rebar_test_utils:run_and_check(Config1, RebarConfig1, ["dialyzer"],
  200. {ok, [{app, Name3}]}),
  201. %% NOTE: `erts` is included in `base_plt_apps`
  202. {ok, PltFiles1} = plt_files(Plt),
  203. ?assertEqual([App2, erts], get_apps_from_beam_files(PltFiles1)),
  204. %% Dialyzer: plt_apps = all_deps
  205. RebarConfig2 = merge_config([{dialyzer, [{plt_apps, all_deps}]}],
  206. RebarConfig1),
  207. rebar_test_utils:run_and_check(Config1, RebarConfig2, ["dialyzer"],
  208. {ok, [{app, Name3}]}),
  209. {ok, PltFiles2} = plt_files(Plt),
  210. ?assertEqual([App1, App2, erts], get_apps_from_beam_files(PltFiles2)).
  211. exclude_and_extra(Config) ->
  212. AppDir = ?config(apps, Config),
  213. RebarConfig = ?config(rebar_config, Config),
  214. BasePlt = ?config(base_plt, Config),
  215. Plt = ?config(plt, Config),
  216. {value, {dialyzer, Opts}, Rest} = lists:keytake(dialyzer, 1, RebarConfig),
  217. % Remove erts => []
  218. % Add erlang+zlib => [erlang, zlib],
  219. % Add erl_prim_loader+init => [erl_prim_loader, init, erlang, zlib]
  220. % Remove zlib+init => [erl_prim_loader, erlang]
  221. Opts2 = [{exclude_apps, [erts]},
  222. {base_plt_mods, [erlang, zlib]},
  223. {plt_extra_mods, [erl_prim_loader, init]},
  224. {exclude_mods, [zlib, init]} |
  225. Opts],
  226. RebarConfig2 = [{dialyzer, Opts2} | Rest],
  227. Name = rebar_test_utils:create_random_name("app1_"),
  228. Vsn = rebar_test_utils:create_random_vsn(),
  229. rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]),
  230. rebar_test_utils:run_and_check(Config, RebarConfig2, ["dialyzer"],
  231. {ok, [{app, Name}]}),
  232. Erlang = code:where_is_file("erlang.beam"),
  233. {ok, BasePltFiles} = plt_files(BasePlt),
  234. ?assertEqual([Erlang], BasePltFiles),
  235. Pair = lists:sort([Erlang, code:where_is_file("erl_prim_loader.beam")]),
  236. {ok, PltFiles} = plt_files(Plt),
  237. ?assertEqual(Pair, PltFiles).
  238. cli_args(Config) ->
  239. AppDir = ?config(apps, Config),
  240. [{dialyzer, Opts}] = ?config(rebar_config, Config),
  241. BasePlt = ?config(base_plt, Config),
  242. Plt = ?config(plt, Config),
  243. {value, {_, Prefix}, Opts1} = lists:keytake(plt_prefix, 1, Opts),
  244. {value, {_, BasePrefix}, Opts2} = lists:keytake(base_plt_prefix, 1, Opts1),
  245. {value, {_, Location}, Opts3} = lists:keytake(plt_location, 1, Opts2),
  246. {value, {_, BasePltLocation}, Opts4} = lists:keytake(base_plt_location, 1, Opts3),
  247. RebarConfig = [{dialyzer, Opts4}],
  248. Name1 = rebar_test_utils:create_random_name("relapp1_"),
  249. Vsn1 = rebar_test_utils:create_random_vsn(),
  250. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1,
  251. [erts]),
  252. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  253. Vsn2 = rebar_test_utils:create_random_vsn(),
  254. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2,
  255. [erts, ec_cnv:to_atom(Name1)]),
  256. rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer",
  257. "--plt-location=" ++ Location,
  258. "--base-plt-location=" ++ BasePltLocation,
  259. "--plt-prefix=" ++ Prefix,
  260. "--base-plt-prefix=" ++ BasePrefix,
  261. "--statistics"],
  262. {ok, [{app, Name1}, {app, Name2}]}),
  263. ErtsFiles = erts_files(),
  264. {ok, BasePltFiles} = plt_files(BasePlt),
  265. ?assertEqual(ErtsFiles, BasePltFiles),
  266. {ok, PltFiles} = plt_files(Plt),
  267. ?assertEqual(ErtsFiles, PltFiles).
  268. %% Helpers
  269. erts_files() ->
  270. ErtsDir = code:lib_dir(erts, ebin),
  271. ErtsBeams = filelib:wildcard("*.beam", ErtsDir),
  272. ErtsFiles = lists:map(fun(Beam) -> filename:join(ErtsDir, Beam) end,
  273. ErtsBeams),
  274. lists:sort(ErtsFiles).
  275. plt_files(Plt) ->
  276. case dialyzer:plt_info(Plt) of
  277. {ok, Info} ->
  278. Files = proplists:get_value(files, Info),
  279. {ok, lists:sort(Files)};
  280. Other ->
  281. Other
  282. end.
  283. alter_plt(Plt) ->
  284. {ok, Files} = plt_files(Plt),
  285. _ = dialyzer:run([{analysis_type, plt_remove},
  286. {init_plt, Plt},
  287. {files, [hd(Files)]}]),
  288. _ = dialyzer:run([{analysis_type, plt_add},
  289. {init_plt, Plt},
  290. {files, [code:which(dialyzer)]}]),
  291. ok.
  292. add_missing_file(Plt) ->
  293. Source = code:which(dialyzer),
  294. Dest = filename:join(filename:dirname(Plt), "dialyzer.beam"),
  295. {ok, _} = file:copy(Source, Dest),
  296. _ = try
  297. dialyzer:run([{analysis_type, plt_add},
  298. {init_plt, Plt},
  299. {files, [Dest]}])
  300. after
  301. ok = file:delete(Dest)
  302. end,
  303. ok.
  304. -spec merge_config(Config, Config) -> Config when
  305. Config :: [{term(), term()}].
  306. merge_config(NewConfig, OldConfig) ->
  307. dict:to_list(
  308. rebar_opts:merge_opts(dict:from_list(NewConfig),
  309. dict:from_list(OldConfig))).
  310. -spec get_apps_from_beam_files(string()) -> [atom()].
  311. get_apps_from_beam_files(BeamFiles) ->
  312. lists:usort(
  313. [begin
  314. AppNameVsn = filename:basename(filename:dirname(filename:dirname(File))),
  315. [AppName | _] = rebar_string:lexemes(AppNameVsn ++ "-", "-"),
  316. ec_cnv:to_atom(AppName)
  317. end || File <- BeamFiles]).