25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

534 lines
21 KiB

  1. -module(rebar_profiles_SUITE).
  2. -export([init_per_suite/1,
  3. end_per_suite/1,
  4. init_per_testcase/2,
  5. end_per_testcase/2,
  6. all/0,
  7. profile_new_key/1,
  8. profile_merge_keys/1,
  9. explicit_profile_deduplicate_deps/1,
  10. implicit_profile_deduplicate_deps/1,
  11. all_deps_code_paths/1,
  12. profile_merges/1,
  13. same_profile_deduplication/1,
  14. stack_deduplication/1,
  15. add_to_profile/1,
  16. add_to_existing_profile/1,
  17. profiles_remain_applied_with_config_present/1,
  18. deduplicated_paths/1,
  19. test_profile_applied_at_completion/1,
  20. test_profile_applied_before_compile/1,
  21. test_profile_applied_before_eunit/1,
  22. test_profile_applied_to_apps/1,
  23. test_profile_erl_opts_order_1/1,
  24. test_profile_erl_opts_order_2/1,
  25. test_profile_erl_opts_order_3/1,
  26. test_profile_erl_opts_order_4/1,
  27. test_profile_erl_opts_order_5/1]).
  28. -include_lib("common_test/include/ct.hrl").
  29. -include_lib("eunit/include/eunit.hrl").
  30. -include_lib("kernel/include/file.hrl").
  31. all() ->
  32. [profile_new_key, profile_merge_keys, all_deps_code_paths, profile_merges,
  33. explicit_profile_deduplicate_deps, implicit_profile_deduplicate_deps,
  34. same_profile_deduplication, stack_deduplication,
  35. add_to_profile, add_to_existing_profile,
  36. profiles_remain_applied_with_config_present,
  37. deduplicated_paths,
  38. test_profile_applied_at_completion,
  39. test_profile_applied_before_compile,
  40. test_profile_applied_before_eunit,
  41. test_profile_applied_to_apps,
  42. test_profile_erl_opts_order_1,
  43. test_profile_erl_opts_order_2,
  44. test_profile_erl_opts_order_3,
  45. test_profile_erl_opts_order_4,
  46. test_profile_erl_opts_order_5].
  47. init_per_suite(Config) ->
  48. application:start(meck),
  49. Config.
  50. end_per_suite(_Config) ->
  51. application:stop(meck).
  52. init_per_testcase(_, Config) ->
  53. rebar_test_utils:init_rebar_state(Config, "profiles_").
  54. end_per_testcase(_, Config) ->
  55. meck:unload(),
  56. Config.
  57. profile_new_key(Config) ->
  58. AppDir = ?config(apps, Config),
  59. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  60. ,{"b", "1.0.0", []}]),
  61. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  62. mock_git_resource:mock([{deps, SrcDeps}]),
  63. Name = rebar_test_utils:create_random_name("profile_new_key_"),
  64. Vsn = rebar_test_utils:create_random_vsn(),
  65. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  66. Deps = rebar_test_utils:top_level_deps(
  67. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  68. ,{"b", "1.0.0", []}])),
  69. ct:pal("Deps ~p", [Deps]),
  70. RebarConfig = [{profiles,
  71. [{ct,
  72. [{deps, Deps}]}]}],
  73. rebar_test_utils:run_and_check(Config, RebarConfig,
  74. ["as", "ct", "compile"], {ok, [{app, Name}
  75. ,{dep, "a", "1.0.0"}
  76. ,{dep, "b", "1.0.0"}]}).
  77. profile_merge_keys(Config) ->
  78. AppDir = ?config(apps, Config),
  79. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  80. ,{"b", "1.0.0", []}
  81. ,{"b", "2.0.0", []}]),
  82. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  83. mock_git_resource:mock([{deps, SrcDeps}]),
  84. Name = rebar_test_utils:create_random_name("profile_new_key_"),
  85. Vsn = rebar_test_utils:create_random_vsn(),
  86. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  87. Deps = rebar_test_utils:top_level_deps(
  88. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  89. ,{"b", "1.0.0", []}])),
  90. ProfileDeps = rebar_test_utils:top_level_deps(
  91. rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])),
  92. RebarConfig = [{deps, Deps},
  93. {profiles,
  94. [{ct,
  95. [{deps, ProfileDeps}]}]}],
  96. rebar_test_utils:run_and_check(Config, RebarConfig,
  97. ["as", "ct", "compile"], {ok, [{app, Name}
  98. ,{dep, "a", "1.0.0"}
  99. ,{dep, "b", "2.0.0"}]}).
  100. explicit_profile_deduplicate_deps(Config) ->
  101. AppDir = ?config(apps, Config),
  102. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  103. ,{"a", "2.0.0", []}
  104. ,{"b", "1.0.0", []}
  105. ,{"b", "2.0.0", []}]),
  106. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  107. mock_git_resource:mock([{deps, SrcDeps}]),
  108. Name = rebar_test_utils:create_random_name("explicit_profile_deduplicate_deps_"),
  109. Vsn = rebar_test_utils:create_random_vsn(),
  110. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  111. FooDeps = rebar_test_utils:top_level_deps(
  112. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []},
  113. {"b", "2.0.0", []}])),
  114. BarDeps = rebar_test_utils:top_level_deps(
  115. rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])),
  116. RebarConfig = [{profiles,
  117. [{foo,
  118. [{deps, FooDeps}]},
  119. {bar,
  120. [{deps, BarDeps}]}]}],
  121. rebar_test_utils:run_and_check(Config, RebarConfig,
  122. ["as", "bar,foo,bar", "compile"], {ok, [{app, Name}
  123. ,{dep, "a", "1.0.0"}
  124. ,{dep, "b", "1.0.0"}]}).
  125. implicit_profile_deduplicate_deps(Config) ->
  126. AppDir = ?config(apps, Config),
  127. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  128. ,{"a", "2.0.0", []}
  129. ,{"b", "1.0.0", []}
  130. ,{"b", "2.0.0", []}]),
  131. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  132. mock_git_resource:mock([{deps, SrcDeps}]),
  133. Name = rebar_test_utils:create_random_name("implicit_profile_deduplicate_deps_"),
  134. Vsn = rebar_test_utils:create_random_vsn(),
  135. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  136. TestDeps = rebar_test_utils:top_level_deps(
  137. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []},
  138. {"b", "2.0.0", []}])),
  139. ProfileDeps = rebar_test_utils:top_level_deps(
  140. rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])),
  141. RebarConfig = [{profiles,
  142. [{test,
  143. [{deps, TestDeps}]},
  144. {bar,
  145. [{deps, ProfileDeps}]}]}],
  146. rebar_test_utils:run_and_check(Config, RebarConfig,
  147. ["as", "test,bar", "eunit"], {ok, [{app, Name}
  148. ,{dep, "a", "1.0.0"}
  149. ,{dep, "b", "2.0.0"}]}).
  150. all_deps_code_paths(Config) ->
  151. AppDir = ?config(apps, Config),
  152. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  153. ,{"b", "2.0.0", []}]),
  154. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  155. mock_git_resource:mock([{deps, SrcDeps}]),
  156. Name = rebar_test_utils:create_random_name("all_deps_code_paths"),
  157. Vsn = rebar_test_utils:create_random_vsn(),
  158. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  159. Deps = rebar_test_utils:top_level_deps(
  160. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}])),
  161. ProfileDeps = rebar_test_utils:top_level_deps(
  162. rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])),
  163. RebarConfig = [{deps, Deps},
  164. {profiles,
  165. [{all_deps_test,
  166. [{deps, ProfileDeps}]}]}],
  167. os:putenv("REBAR_PROFILE", "all_deps_test"),
  168. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig,
  169. ["compile"], {ok, [{app, Name}
  170. ,{dep, "a", "1.0.0"}
  171. ,{dep, "b", "2.0.0"}]}),
  172. os:putenv("REBAR_PROFILE", ""),
  173. Paths = rebar_state:code_paths(State, all_deps),
  174. Path = lists:reverse(["_build", "all_deps_test", "lib", "b", "ebin"]),
  175. ?assert(lists:any(fun(X) ->
  176. Path =:= lists:sublist(lists:reverse(filename:split(X)), 5)
  177. end, Paths)).
  178. profile_merges(_Config) ->
  179. RebarConfig = [{test1, [{key1, 1, 2}, key2]},
  180. {test2, "hello"},
  181. {test3, [key3]},
  182. {test4, "oldvalue"},
  183. {test5, [{key5, true}]},
  184. {test6, [{key6, false}]},
  185. {profiles,
  186. [{profile1,
  187. [{test1, [{key3, 5}, key1]}]},
  188. {profile2, [{test2, "goodbye"},
  189. {test3, []},
  190. {test4, []},
  191. {test5, [{key5, false}]},
  192. {test6, [{key6, true}]}
  193. ]}]}],
  194. State = rebar_state:new(RebarConfig),
  195. State1 = rebar_state:apply_profiles(State, [profile1, profile2]),
  196. %% Combine lists
  197. ?assertEqual(lists:sort([key1, key2, {key1, 1, 2}, {key3, 5}]),
  198. lists:sort(rebar_state:get(State1, test1))),
  199. %% Use new value for strings
  200. "goodbye" = rebar_state:get(State1, test2),
  201. %% Check that a newvalue of []/"" doesn't override non-string oldvalues
  202. [key3] = rebar_state:get(State1, test3),
  203. [] = rebar_state:get(State1, test4),
  204. [{key5, false}, {key5, true}] = rebar_state:get(State1, test5),
  205. [{key6, true}, {key6, false}] = rebar_state:get(State1, test6).
  206. same_profile_deduplication(_Config) ->
  207. RebarConfig = [{test1, [{key1, 1, 2}, key2]},
  208. {test2, [foo]},
  209. {test3, [key3]},
  210. {profiles,
  211. [{profile1,
  212. [{test1, [{key3, 5}, {key2, "hello"}]},
  213. {test2, [bar]},
  214. {test3, []}
  215. ]}]
  216. }],
  217. State = rebar_state:new(RebarConfig),
  218. State1 = rebar_state:apply_profiles(State, [profile1, profile1, profile1]),
  219. ?assertEqual([default, profile1], rebar_state:current_profiles(State1)),
  220. Test1 = rebar_state:get(State1, test1),
  221. %% Combine lists
  222. ?assertEqual(lists:sort([key2, {key1, 1, 2}, {key3, 5}, {key2, "hello"}]),
  223. lists:sort(Test1)),
  224. %% Key2 from profile1 overrides key2 from default profile
  225. ?assertEqual("hello", proplists:get_value(key2, Test1)),
  226. %% Check that a newvalue of []/"" doesn't override non-string oldvalues
  227. ?assertEqual([key3], rebar_state:get(State1, test3)),
  228. ?assertEqual([bar, foo], rebar_state:get(State1, test2)).
  229. stack_deduplication(_Config) ->
  230. RebarConfig = [
  231. {test_key, default},
  232. {test_list, [ {foo, default} ]},
  233. {profiles, [
  234. {a, [
  235. {test_key, a},
  236. {test_list, [ {foo, a} ]}
  237. ]},
  238. {b, [
  239. {test_key, b},
  240. {test_list, [ {foo, b} ]}
  241. ]},
  242. {c, [
  243. {test_key, c},
  244. {test_list, [ {foo, c} ]}
  245. ]},
  246. {d, [
  247. {test_key, d},
  248. {test_list, [ {foo, d} ]}
  249. ]},
  250. {e, [
  251. {test_key, e},
  252. {test_list, [ {foo, e} ]}
  253. ]}
  254. ]}
  255. ],
  256. State = rebar_state:new(RebarConfig),
  257. State1 = rebar_state:apply_profiles(State, [a, b, c, d, e, a, e, b]),
  258. ?assertEqual(b, rebar_state:get(State1, test_key)),
  259. TestList = rebar_state:get(State1, test_list),
  260. ?assertEqual(
  261. [{foo, b}, {foo, e}, {foo, a}, {foo, d}, {foo, c}, {foo, default} ],
  262. TestList
  263. ),
  264. ?assertEqual(b, proplists:get_value(foo, TestList)).
  265. add_to_profile(_Config) ->
  266. RebarConfig = [{foo, true}, {bar, false}],
  267. State = rebar_state:new(RebarConfig),
  268. State1 = rebar_state:add_to_profile(State, test, [{foo, false}]),
  269. State2 = rebar_state:apply_profiles(State1, test),
  270. Opts = rebar_state:opts(State2),
  271. lists:map(fun(K) -> false = dict:fetch(K, Opts) end, [foo, bar]).
  272. add_to_existing_profile(_Config) ->
  273. RebarConfig = [{foo, true}, {bar, false}, {profiles, [
  274. {test, [{foo, false}]}
  275. ]}],
  276. State = rebar_state:new(RebarConfig),
  277. State1 = rebar_state:add_to_profile(State, test, [{baz, false}]),
  278. State2 = rebar_state:apply_profiles(State1, test),
  279. Opts = rebar_state:opts(State2),
  280. lists:map(fun(K) -> false = dict:fetch(K, Opts) end, [foo, bar, baz]).
  281. profiles_remain_applied_with_config_present(Config) ->
  282. AppDir = ?config(apps, Config),
  283. Name = rebar_test_utils:create_random_name("profiles_remain_applied_"),
  284. Vsn = rebar_test_utils:create_random_vsn(),
  285. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  286. RebarConfig = [{erl_opts, []}, {profiles, [
  287. {not_ok, [{erl_opts, [{d, not_ok}]}]}
  288. ]}],
  289. rebar_test_utils:create_config(AppDir, RebarConfig),
  290. rebar_test_utils:run_and_check(Config, RebarConfig,
  291. ["as", "not_ok", "compile"], {ok, [{app, Name}]}),
  292. Path = filename:join([AppDir, "_build", "not_ok", "lib", Name, "ebin"]),
  293. code:add_patha(Path),
  294. Mod = list_to_atom("not_a_real_src_" ++ Name),
  295. true = lists:member({d, not_ok}, proplists:get_value(options, Mod:module_info(compile), [])).
  296. deduplicated_paths(Config) ->
  297. AppDir = ?config(apps, Config),
  298. Name = rebar_test_utils:create_random_name("deduplicated_paths_"),
  299. Vsn = rebar_test_utils:create_random_vsn(),
  300. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  301. RebarConfig = [],
  302. rebar_test_utils:create_config(AppDir, RebarConfig),
  303. rebar_test_utils:run_and_check(Config, RebarConfig,
  304. ["as", "a,b,c,d,e,a,e,b", "compile"],
  305. {ok, [{app, Name}]}),
  306. Path = filename:join([AppDir, "_build", "c+d+a+e+b", "lib", Name, "ebin"]),
  307. ?assert(filelib:is_dir(Path)).
  308. test_profile_applied_at_completion(Config) ->
  309. AppDir = ?config(apps, Config),
  310. Name = rebar_test_utils:create_random_name("test_profile_at_completion_"),
  311. Vsn = rebar_test_utils:create_random_vsn(),
  312. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  313. RebarConfig = [{erl_opts, [{d, some_define}]}],
  314. rebar_test_utils:create_config(AppDir, RebarConfig),
  315. {ok, State} = rebar_test_utils:run_and_check(Config,
  316. RebarConfig,
  317. ["eunit"],
  318. return),
  319. [App] = rebar_state:project_apps(State),
  320. ErlOpts = rebar_app_info:get(App, erl_opts),
  321. true = lists:member({d, 'TEST'}, ErlOpts).
  322. test_profile_applied_before_compile(Config) ->
  323. AppDir = ?config(apps, Config),
  324. Name = rebar_test_utils:create_random_name("test_profile_before_compile_"),
  325. Vsn = rebar_test_utils:create_random_vsn(),
  326. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  327. RebarConfig = [{erl_opts, [{d, some_define}]}],
  328. rebar_test_utils:create_config(AppDir, RebarConfig),
  329. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
  330. code:add_paths(rebar_state:code_paths(State, all_deps)),
  331. S = list_to_atom("not_a_real_src_" ++ Name),
  332. true = lists:member({d, 'TEST'}, proplists:get_value(options, S:module_info(compile), [])).
  333. test_profile_applied_before_eunit(Config) ->
  334. AppDir = ?config(apps, Config),
  335. Name = rebar_test_utils:create_random_name("test_profile_before_eunit_"),
  336. Vsn = rebar_test_utils:create_random_vsn(),
  337. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  338. RebarConfig = [{erl_opts, [{d, some_define}]}],
  339. rebar_test_utils:create_config(AppDir, RebarConfig),
  340. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
  341. code:add_paths(rebar_state:code_paths(State, all_deps)),
  342. T = list_to_atom("not_a_real_src_" ++ Name ++ "_tests"),
  343. true = lists:member({d, 'TEST'}, proplists:get_value(options, T:module_info(compile), [])).
  344. test_profile_applied_to_apps(Config) ->
  345. AppDir = ?config(apps, Config),
  346. Name = rebar_test_utils:create_random_name("test_profile_applied_to_apps_"),
  347. Vsn = rebar_test_utils:create_random_vsn(),
  348. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  349. RebarConfig = [{erl_opts, [{d, some_define}]}],
  350. rebar_test_utils:create_config(AppDir, RebarConfig),
  351. {ok, State} = rebar_test_utils:run_and_check(Config,
  352. RebarConfig,
  353. ["eunit"],
  354. return),
  355. Apps = rebar_state:project_apps(State),
  356. lists:foreach(fun(App) ->
  357. Opts = rebar_app_info:opts(App),
  358. ErlOpts = dict:fetch(erl_opts, Opts),
  359. true = lists:member({d, 'TEST'}, ErlOpts)
  360. end, Apps).
  361. test_profile_erl_opts_order_1(Config) ->
  362. Opts = get_compiled_profile_erl_opts([default], Config),
  363. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  364. undefined = Opt.
  365. test_profile_erl_opts_order_2(Config) ->
  366. Opts = get_compiled_profile_erl_opts([strict], Config),
  367. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  368. warn_export_all = Opt.
  369. test_profile_erl_opts_order_3(Config) ->
  370. Opts = get_compiled_profile_erl_opts([loose], Config),
  371. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  372. nowarn_export_all = Opt.
  373. test_profile_erl_opts_order_4(Config) ->
  374. Opts = get_compiled_profile_erl_opts([strict, loose], Config),
  375. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  376. nowarn_export_all = Opt.
  377. test_profile_erl_opts_order_5(Config) ->
  378. Opts = get_compiled_profile_erl_opts([loose, strict], Config),
  379. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  380. warn_export_all = Opt.
  381. get_compiled_profile_erl_opts(Profiles, Config) ->
  382. AppDir = ?config(apps, Config),
  383. PStrs = [atom_to_list(P) || P <- Profiles],
  384. Name = rebar_test_utils:create_random_name(
  385. lists:flatten(["erl_opts_order_" | [[S, $_] || S <- PStrs]])),
  386. Vsn = rebar_test_utils:create_random_vsn(),
  387. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  388. RebarConfig = [
  389. {erl_opts, [warnings_as_errors, {d, profile_default}]},
  390. {profiles, [
  391. {strict, [{erl_opts, [warn_export_all, {d, profile_strict}]}]},
  392. {loose, [{erl_opts, [nowarn_export_all, {d, profile_loose}]}]} ]}],
  393. rebar_test_utils:create_config(AppDir, RebarConfig),
  394. Command = case Profiles of
  395. [] ->
  396. ["compile"];
  397. [default] ->
  398. ["compile"];
  399. _ ->
  400. ["as", string:join(PStrs, ","), "compile"]
  401. end,
  402. {ok, State} = rebar_test_utils:run_and_check(
  403. Config, RebarConfig, Command, {ok, [{app, Name}]}),
  404. code:add_paths(rebar_state:code_paths(State, all_deps)),
  405. Mod = list_to_atom(Name),
  406. proplists:get_value(options, Mod:module_info(compile), []).
  407. % macro definitions get special handling
  408. last_erl_opt([{d, Macro} = Opt | Opts], Targets, Last) ->
  409. case lists:any(erl_opt_macro_match_fun(Macro), Targets) of
  410. true ->
  411. last_erl_opt(Opts, Targets, Opt);
  412. _ ->
  413. last_erl_opt(Opts, Targets, Last)
  414. end;
  415. last_erl_opt([{d, Macro, _} = Opt | Opts], Targets, Last) ->
  416. case lists:any(erl_opt_macro_match_fun(Macro), Targets) of
  417. true ->
  418. last_erl_opt(Opts, Targets, Opt);
  419. _ ->
  420. last_erl_opt(Opts, Targets, Last)
  421. end;
  422. last_erl_opt([Opt | Opts], Targets, Last) ->
  423. case lists:member(Opt, Targets) of
  424. true ->
  425. last_erl_opt(Opts, Targets, Opt);
  426. _ ->
  427. last_erl_opt(Opts, Targets, Last)
  428. end;
  429. last_erl_opt([], _, Last) ->
  430. Last.
  431. erl_opt_macro_match_fun(Macro) ->
  432. fun({d, M}) ->
  433. M == Macro;
  434. ({d, M, _}) ->
  435. M == Macro;
  436. (_) ->
  437. false
  438. end.