Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

423 строки
15 KiB

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