Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

2981 righe
117 KiB

10 anni fa
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 anni fa
10 anni fa
Fix handling of updated files in extra_src_dirs This change fixes cases where changes in .hrl files would not be picked up in .erl files that are in extra source directories (such as those defined with `extra_src_dirs` or modules in the test/ directory during a CT or Eunit run). The problem was due to the way the Directed Acyclic Graph (DAG) of dependencies between files was being loaded and stored by the compiler modules. Prior to this fix, a single DAG would be used for all runs. On a regular run, the prior DAG is loaded from disk, re-checked, and if changed, it would get re-written to disk with the changes deciding what to re-compile. However, whenever extra source directories were specified, a second run would be done which swaps target directories around in the compiler modules. Bug 1: this second run was done without properly tracking the private .hrl files (in src/), so the changes were invisible. This has been fixed by re-adding the paths. The problem is that the DAG handling is self-contained; just invoking it was sufficient to get it loaded and rewritten to disk. But since runs with extra src dirs were done on different sets, the compilation of extra src dirs would be done with bad historical data (all the modules in src/ are dropped, all those in test/ are re-added); this DAG was then written to disk once again, polluting the next non-extra run. This is bug 2, and it is fixed by adding an optional label to each run so that a regular or extra compile round can be distinguished, each tracking their own files in their own DAG. A single test (and a lot of diffing) were sufficient for this.
6 anni fa
Fix directory recursion in compiler This patch contains two behaviour changes and reasserts other behaviours that now line things up with user and documentation expectations: 1. The src directories remain recursive. We turned it on by accident at some point in the past and now people rely on it, so we're stuck with it. However a new test ensures that the feature can be turned off on-demand as documented on the website. 2. The test directories are no longer recursive by default. The fix is done by properly fixing how rebar3.erl does its feature injection by mandating the default value there. I'm somewhat nervous that this change could negatively impact some users and older compiler module versions, but if users stick to the rebar_dir interface, everything should keep working transparently. 3. The test directories' configuration is no longer silently dropped. Due to how rebar3.erl injected test state without looking for what the user may have specified, multiple extra_src_dirs entries existed at once and were run; one with the recursion set to true and one with whatever the user specified. If the user disabled recursion of the "test" extra_src_dir, then the injected value still ran it once... 4. The handling of extra files in the compiler module is fixed to actually use the rebar_dir interface properly, and reinjects non-default directory recursion settings into the swapped options for the shimmed extra apps. Not doing this annotation step resulted in the write for swapped opts to actually drop the configured recursion value and make everything recursive all the time. A single new test actually validates all of that behaviour and seems to work fine.
4 anni fa
10 anni fa
10 anni fa
10 anni fa
10 anni fa
10 anni fa
10 anni fa
10 anni fa
10 anni fa
Fix handling of updated files in extra_src_dirs This change fixes cases where changes in .hrl files would not be picked up in .erl files that are in extra source directories (such as those defined with `extra_src_dirs` or modules in the test/ directory during a CT or Eunit run). The problem was due to the way the Directed Acyclic Graph (DAG) of dependencies between files was being loaded and stored by the compiler modules. Prior to this fix, a single DAG would be used for all runs. On a regular run, the prior DAG is loaded from disk, re-checked, and if changed, it would get re-written to disk with the changes deciding what to re-compile. However, whenever extra source directories were specified, a second run would be done which swaps target directories around in the compiler modules. Bug 1: this second run was done without properly tracking the private .hrl files (in src/), so the changes were invisible. This has been fixed by re-adding the paths. The problem is that the DAG handling is self-contained; just invoking it was sufficient to get it loaded and rewritten to disk. But since runs with extra src dirs were done on different sets, the compilation of extra src dirs would be done with bad historical data (all the modules in src/ are dropped, all those in test/ are re-added); this DAG was then written to disk once again, polluting the next non-extra run. This is bug 2, and it is fixed by adding an optional label to each run so that a regular or extra compile round can be distinguished, each tracking their own files in their own DAG. A single test (and a lot of diffing) were sufficient for this.
6 anni fa
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 anni fa
Fix directory recursion in compiler This patch contains two behaviour changes and reasserts other behaviours that now line things up with user and documentation expectations: 1. The src directories remain recursive. We turned it on by accident at some point in the past and now people rely on it, so we're stuck with it. However a new test ensures that the feature can be turned off on-demand as documented on the website. 2. The test directories are no longer recursive by default. The fix is done by properly fixing how rebar3.erl does its feature injection by mandating the default value there. I'm somewhat nervous that this change could negatively impact some users and older compiler module versions, but if users stick to the rebar_dir interface, everything should keep working transparently. 3. The test directories' configuration is no longer silently dropped. Due to how rebar3.erl injected test state without looking for what the user may have specified, multiple extra_src_dirs entries existed at once and were run; one with the recursion set to true and one with whatever the user specified. If the user disabled recursion of the "test" extra_src_dir, then the injected value still ran it once... 4. The handling of extra files in the compiler module is fixed to actually use the rebar_dir interface properly, and reinjects non-default directory recursion settings into the swapped options for the shimmed extra apps. Not doing this annotation step resulted in the write for swapped opts to actually drop the configured recursion value and make everything recursive all the time. A single new test actually validates all of that behaviour and seems to work fine.
4 anni fa
  1. -module(rebar_compile_SUITE).
  2. -compile(export_all).
  3. -include_lib("common_test/include/ct.hrl").
  4. -include_lib("eunit/include/eunit.hrl").
  5. -include_lib("kernel/include/file.hrl").
  6. suite() ->
  7. [].
  8. all() ->
  9. [{group, basic_app}, {group, release_apps},
  10. {group, checkout_apps}, {group, checkout_deps},
  11. {group, basic_srcdirs}, {group, release_srcdirs}, {group, unbalanced_srcdirs},
  12. {group, basic_extras}, {group, release_extras}, {group, unbalanced_extras},
  13. {group, root_extras},
  14. recompile_when_hrl_changes, recompile_when_included_hrl_changes,
  15. recompile_extra_when_hrl_in_src_changes,
  16. recompile_when_opts_included_hrl_changes,
  17. recompile_when_foreign_included_hrl_changes,
  18. recompile_when_foreign_behaviour_changes,
  19. recompile_when_recursive_behaviour_changes,
  20. recompile_when_opts_change, recompile_when_dag_opts_change,
  21. dont_recompile_when_opts_dont_change, dont_recompile_yrl_or_xrl,
  22. delete_beam_if_source_deleted,
  23. deps_in_path, checkout_priority, highest_version_of_pkg_dep,
  24. parse_transform_test, erl_first_files_test, mib_test,
  25. umbrella_mib_first_test, deps_mib_test,
  26. only_default_transitive_deps, clean_all,
  27. clean_specific, profile_deps, deps_build_in_prod, only_deps,
  28. override_deps, git_subdir_deps, override_add_deps, override_del_deps,
  29. override_del_pkg_deps, override_opts, override_add_opts, override_del_opts,
  30. apply_overrides_exactly_once, override_only_deps,
  31. profile_override_deps, profile_override_add_deps, profile_override_del_deps,
  32. profile_override_opts, profile_override_add_opts, profile_override_del_opts,
  33. include_file_relative_to_working_directory, include_file_in_src,
  34. include_file_relative_to_working_directory_test, include_file_in_src_test,
  35. include_file_in_src_test_multiapp,
  36. recompile_when_parse_transform_as_opt_changes,
  37. recompile_when_parse_transform_inline_changes,
  38. regex_filter_skip, regex_filter_regression,
  39. recursive, no_recursive, extra_recursion,
  40. always_recompile_when_erl_compiler_options_set,
  41. dont_recompile_when_erl_compiler_options_env_does_not_change,
  42. recompile_when_erl_compiler_options_env_changes,
  43. rebar_config_os_var, split_project_apps_hooks,
  44. app_file_linting].
  45. groups() ->
  46. [{basic_app, [], [build_basic_app, paths_basic_app, clean_basic_app]},
  47. {release_apps, [], [build_release_apps, paths_release_apps, clean_release_apps]},
  48. {checkout_apps, [], [paths_checkout_apps]},
  49. {checkout_deps, [], [build_checkout_deps, paths_checkout_deps]},
  50. {basic_srcdirs, [], [build_basic_srcdirs, paths_basic_srcdirs]},
  51. {release_srcdirs, [], [build_release_srcdirs,
  52. paths_release_srcdirs]},
  53. {unbalanced_srcdirs, [], [build_unbalanced_srcdirs,
  54. paths_unbalanced_srcdirs]},
  55. {basic_extras, [], [build_basic_extra_dirs,
  56. paths_basic_extra_dirs,
  57. clean_basic_extra_dirs]},
  58. {release_extras, [], [build_release_extra_dirs,
  59. paths_release_extra_dirs,
  60. clean_release_extra_dirs]},
  61. {unbalanced_extras, [], [build_unbalanced_extra_dirs,
  62. paths_unbalanced_extra_dirs]},
  63. {root_extras, [], [build_extra_dirs_in_project_root,
  64. paths_extra_dirs_in_project_root,
  65. clean_extra_dirs_in_project_root]}].
  66. init_per_group(basic_app, Config) ->
  67. NewConfig = rebar_test_utils:init_rebar_state(Config, "basic_app_"),
  68. AppDir = ?config(apps, NewConfig),
  69. Name = rebar_test_utils:create_random_name("app1"),
  70. Vsn = rebar_test_utils:create_random_vsn(),
  71. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  72. [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig];
  73. init_per_group(release_apps, Config) ->
  74. NewConfig = rebar_test_utils:init_rebar_state(Config, "release_apps_"),
  75. AppDir = ?config(apps, NewConfig),
  76. Name1 = rebar_test_utils:create_random_name("relapp1_"),
  77. Vsn1 = rebar_test_utils:create_random_vsn(),
  78. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [kernel, stdlib]),
  79. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  80. Vsn2 = rebar_test_utils:create_random_vsn(),
  81. rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [kernel, stdlib]),
  82. [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
  83. init_per_group(checkout_apps, Config) ->
  84. NewConfig = rebar_test_utils:init_rebar_state(Config, "checkout_apps_"),
  85. AppDir = ?config(apps, NewConfig),
  86. CheckoutsDir = ?config(checkouts, NewConfig),
  87. Name1 = rebar_test_utils:create_random_name("checkapp1_"),
  88. Vsn1 = rebar_test_utils:create_random_vsn(),
  89. rebar_test_utils:create_app(AppDir, Name1, Vsn1, [kernel, stdlib]),
  90. Name2 = rebar_test_utils:create_random_name("checkapp2_"),
  91. Vsn2 = rebar_test_utils:create_random_vsn(),
  92. rebar_test_utils:create_app(filename:join([CheckoutsDir,Name2]), Name2, Vsn2, [kernel, stdlib]),
  93. [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
  94. init_per_group(checkout_deps, Config) ->
  95. NewConfig = rebar_test_utils:init_rebar_state(Config, "checkout_deps_"),
  96. AppDir = ?config(apps, NewConfig),
  97. CheckoutsDir = ?config(checkouts, NewConfig),
  98. DepsDir = filename:join([AppDir, "_build", "default", "lib"]),
  99. Name1 = rebar_test_utils:create_random_name("checkapp1_"),
  100. Vsn1 = rebar_test_utils:create_random_vsn(),
  101. rebar_test_utils:create_app(AppDir, Name1, Vsn1, [kernel, stdlib]),
  102. Name2 = rebar_test_utils:create_random_name("checkapp2_"),
  103. Vsn2 = rebar_test_utils:create_random_vsn(),
  104. rebar_test_utils:create_app(filename:join([CheckoutsDir,Name2]), Name2, Vsn2, [kernel, stdlib]),
  105. rebar_test_utils:create_app(filename:join([DepsDir,Name2]), Name2, Vsn1, [kernel, stdlib]),
  106. [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
  107. init_per_group(Group, Config) when Group == basic_srcdirs; Group == basic_extras ->
  108. NewConfig = rebar_test_utils:init_rebar_state(Config, "basic_srcdirs_"),
  109. AppDir = ?config(apps, NewConfig),
  110. Name = rebar_test_utils:create_random_name("app1_"),
  111. Vsn = rebar_test_utils:create_random_vsn(),
  112. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  113. ExtraSrc = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name]),
  114. ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
  115. ok = file:write_file(filename:join([AppDir, "extra", io_lib:format("~ts_extra.erl", [Name])]),
  116. ExtraSrc),
  117. [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig];
  118. init_per_group(Group, Config) when Group == release_srcdirs; Group == release_extras ->
  119. NewConfig = rebar_test_utils:init_rebar_state(Config, "release_srcdirs_"),
  120. AppDir = ?config(apps, NewConfig),
  121. Name1 = rebar_test_utils:create_random_name("relapp1_"),
  122. Vsn1 = rebar_test_utils:create_random_vsn(),
  123. rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
  124. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  125. Vsn2 = rebar_test_utils:create_random_vsn(),
  126. rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
  127. ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]),
  128. ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])),
  129. ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra",
  130. io_lib:format("~ts_extra.erl", [Name1])]),
  131. ExtraOne),
  132. ExtraTwo = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name2]),
  133. ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "extra", "dummy"])),
  134. ok = file:write_file(filename:join([AppDir, "apps", Name2, "extra",
  135. io_lib:format("~ts_extra.erl", [Name2])]),
  136. ExtraTwo),
  137. [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
  138. init_per_group(Group, Config) when Group == unbalanced_srcdirs; Group == unbalanced_extras ->
  139. NewConfig = rebar_test_utils:init_rebar_state(Config, "unbalanced_srcdirs_"),
  140. AppDir = ?config(apps, NewConfig),
  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, [kernel, stdlib]),
  144. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  145. Vsn2 = rebar_test_utils:create_random_vsn(),
  146. rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
  147. ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]),
  148. ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])),
  149. ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra",
  150. io_lib:format("~ts_extra.erl", [Name1])]),
  151. ExtraOne),
  152. [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig];
  153. init_per_group(root_extras, Config) ->
  154. NewConfig = rebar_test_utils:init_rebar_state(Config, "root_extras_"),
  155. AppDir = ?config(apps, NewConfig),
  156. Name1 = rebar_test_utils:create_random_name("relapp1_"),
  157. Vsn1 = rebar_test_utils:create_random_vsn(),
  158. rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]),
  159. Name2 = rebar_test_utils:create_random_name("relapp2_"),
  160. Vsn2 = rebar_test_utils:create_random_vsn(),
  161. rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]),
  162. Extra = <<"-module(extra).\n-export([ok/0]).\nok() -> ok.\n">>,
  163. ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])),
  164. ok = file:write_file(filename:join([AppDir, "extra", "extra.erl"]), Extra),
  165. [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig].
  166. end_per_group(_Group, _Config) ->
  167. ok.
  168. init_per_suite(Config) ->
  169. Config.
  170. end_per_suite(_Config) ->
  171. ok.
  172. init_per_testcase(Test, Config) when
  173. Test == dont_recompile_when_erl_compiler_options_env_does_not_change
  174. orelse
  175. Test == recompile_when_erl_compiler_options_env_changes ->
  176. _ = code:ensure_loaded(os),
  177. UnSetEnv = erlang:function_exported(os, unsetenv, 1),
  178. _ = code:ensure_loaded(compile),
  179. EnvOpts = erlang:function_exported(compile, env_compiler_options, 0),
  180. case {UnSetEnv, EnvOpts} of
  181. {true, true} -> maybe_init_config(Config);
  182. _ -> {skip, "compile:env_compiler_options/0 unavailable"}
  183. end;
  184. init_per_testcase(always_recompile_when_erl_compiler_options_set, Config) ->
  185. _ = code:ensure_loaded(os),
  186. UnSetEnv = erlang:function_exported(os, unsetenv, 1),
  187. _ = code:ensure_loaded(compile),
  188. EnvOpts = erlang:function_exported(compile, env_compiler_options, 0),
  189. case {UnSetEnv, EnvOpts} of
  190. {true, true} -> {skip, "compile:env_compiler_options/0 available"};
  191. {true, false} -> maybe_init_config(Config);
  192. _ -> {skip, "os:unsetenv/1 unavailable"}
  193. end;
  194. init_per_testcase(_, Config) -> maybe_init_config(Config).
  195. maybe_init_config(Config) ->
  196. case ?config(apps, Config) of
  197. undefined -> rebar_test_utils:init_rebar_state(Config);
  198. _ -> Config
  199. end.
  200. end_per_testcase(_, _Config) ->
  201. catch meck:unload().
  202. %% test cases
  203. build_basic_app(Config) ->
  204. [Name] = ?config(app_names, Config),
  205. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}).
  206. build_release_apps(Config) ->
  207. [Name1, Name2] = ?config(app_names, Config),
  208. rebar_test_utils:run_and_check(
  209. Config, [], ["compile"],
  210. {ok, [{app, Name1}, {app, Name2}]}
  211. ).
  212. build_checkout_deps(Config) ->
  213. AppDir = ?config(apps, Config),
  214. [Name1, Name2] = ?config(app_names, Config),
  215. [_, Vsn2] = ?config(vsns, Config),
  216. Deps = [{list_to_atom(Name2), Vsn2, {git, "", ""}}],
  217. {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, Deps}])),
  218. rebar_test_utils:run_and_check(
  219. Config, RebarConfig, ["compile"],
  220. {ok, [{app, Name1}, {checkout, Name2}]}
  221. ).
  222. build_basic_srcdirs(Config) ->
  223. AppDir = ?config(apps, Config),
  224. [Name] = ?config(app_names, Config),
  225. RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
  226. %% check a beam corresponding to the src in the extra src_dir exists
  227. ExtraBeam = filename:join([AppDir, "_build", "default", "lib", Name, "ebin",
  228. io_lib:format("~ts_extra.beam", [Name])]),
  229. %% check the extra src_dir was copied/linked into the _build dir
  230. ExtraDir = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]),
  231. rebar_test_utils:run_and_check(
  232. Config, RebarConfig, ["compile"],
  233. {ok, [{app, Name}, {file, ExtraBeam}, {dir, ExtraDir}]}
  234. ).
  235. build_release_srcdirs(Config) ->
  236. AppDir = ?config(apps, Config),
  237. [Name1, Name2] = ?config(app_names, Config),
  238. RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
  239. %% check a beam corresponding to the src in the extra src_dir exists
  240. Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
  241. io_lib:format("~ts_extra.beam", [Name1])]),
  242. Extra2Beam = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin",
  243. io_lib:format("~ts_extra.beam", [Name2])]),
  244. %% check the extra src_dir was copied/linked into the _build dir
  245. Extra1Dir = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]),
  246. Extra2Dir = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]),
  247. rebar_test_utils:run_and_check(
  248. Config, RebarConfig, ["compile"],
  249. {ok, [{app, Name1}, {app, Name2},
  250. {file, Extra1Beam}, {file, Extra2Beam},
  251. {dir, Extra1Dir}, {dir, Extra2Dir}]}
  252. ).
  253. build_unbalanced_srcdirs(Config) ->
  254. AppDir = ?config(apps, Config),
  255. [Name1, Name2] = ?config(app_names, Config),
  256. RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
  257. %% check a beam corresponding to the src in the extra src_dir exists
  258. Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
  259. io_lib:format("~ts_extra.beam", [Name1])]),
  260. %% check the extra src_dir was copied/linked into the _build dir
  261. Extra1Dir = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]),
  262. rebar_test_utils:run_and_check(
  263. Config, RebarConfig, ["compile"],
  264. {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {dir, Extra1Dir}]}
  265. ),
  266. %% check no extra src_dir were copied/linked into the _build dir
  267. Extra2Dir = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]),
  268. false = filelib:is_dir(Extra2Dir),
  269. %% check only expected beams are in the ebin dir
  270. {ok, Files} = rebar_utils:list_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"])),
  271. lists:all(fun(Beam) -> lists:member(Beam, [Name2 ++ ".app", "not_a_real_src_" ++ Name2 ++ ".beam"]) end,
  272. Files).
  273. build_basic_extra_dirs(Config) ->
  274. AppDir = ?config(apps, Config),
  275. [Name] = ?config(app_names, Config),
  276. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  277. %% check a beam corresponding to the src in the extra src_dir exists
  278. ExtraBeam = filename:join([AppDir, "_build", "default", "lib", Name, "extra",
  279. io_lib:format("~ts_extra.beam", [Name])]),
  280. rebar_test_utils:run_and_check(
  281. Config, RebarConfig, ["compile"],
  282. {ok, [{app, Name}, {file, ExtraBeam}]}
  283. ).
  284. build_release_extra_dirs(Config) ->
  285. AppDir = ?config(apps, Config),
  286. [Name1, Name2] = ?config(app_names, Config),
  287. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  288. %% check a beam corresponding to the src in the extra src_dir exists
  289. Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
  290. io_lib:format("~ts_extra.beam", [Name1])]),
  291. Extra2Beam = filename:join([AppDir, "_build", "default", "lib", Name2, "extra",
  292. io_lib:format("~ts_extra.beam", [Name2])]),
  293. rebar_test_utils:run_and_check(
  294. Config, RebarConfig, ["compile"],
  295. {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {file, Extra2Beam}]}
  296. ).
  297. build_unbalanced_extra_dirs(Config) ->
  298. AppDir = ?config(apps, Config),
  299. [Name1, Name2] = ?config(app_names, Config),
  300. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  301. %% check a beam corresponding to the src in the extra src_dir exists
  302. Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
  303. io_lib:format("~ts_extra.beam", [Name1])]),
  304. rebar_test_utils:run_and_check(
  305. Config, RebarConfig, ["compile"],
  306. {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}]}
  307. ),
  308. %% check no extra src_dir were copied/linked into the _build dir
  309. false = filelib:is_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "extra"])),
  310. %% check only expected beams are in the ebin dir
  311. {ok, Files} = rebar_utils:list_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"])),
  312. lists:all(fun(Beam) -> lists:member(Beam, [Name2 ++ ".app", "not_a_real_src_" ++ Name2 ++ ".beam"]) end,
  313. Files).
  314. build_extra_dirs_in_project_root(Config) ->
  315. AppDir = ?config(apps, Config),
  316. [Name1, Name2] = ?config(app_names, Config),
  317. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  318. %% check a beam corresponding to the src in the extra src_dir exists
  319. ExtraBeam = filename:join([AppDir, "_build", "default", "extras", "extra", "extra.beam"]),
  320. rebar_test_utils:run_and_check(
  321. Config, RebarConfig, ["compile"],
  322. {ok, [{app, Name1}, {app, Name2}, {file, ExtraBeam}]}
  323. ).
  324. paths_basic_app(Config) ->
  325. [Name] = ?config(app_names, Config),
  326. [Vsn] = ?config(vsns, Config),
  327. {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
  328. code:add_paths(rebar_state:code_paths(State, all_deps)),
  329. ok = application:load(list_to_atom(Name)),
  330. Loaded = application:loaded_applications(),
  331. {_, _, Vsn} = lists:keyfind(list_to_atom(Name), 1, Loaded).
  332. paths_release_apps(Config) ->
  333. [Name1, Name2] = ?config(app_names, Config),
  334. [Vsn1, Vsn2] = ?config(vsns, Config),
  335. {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
  336. code:add_paths(rebar_state:code_paths(State, all_deps)),
  337. ok = application:load(list_to_atom(Name1)),
  338. ok = application:load(list_to_atom(Name2)),
  339. Loaded = application:loaded_applications(),
  340. {_, _, Vsn1} = lists:keyfind(list_to_atom(Name1), 1, Loaded),
  341. {_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded).
  342. paths_checkout_apps(Config) ->
  343. [Name1, _Name2] = ?config(app_names, Config),
  344. [Vsn1, _Vsn2] = ?config(vsns, Config),
  345. {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
  346. code:add_paths(rebar_state:code_paths(State, all_deps)),
  347. ok = application:load(list_to_atom(Name1)),
  348. Loaded = application:loaded_applications(),
  349. {_, _, Vsn1} = lists:keyfind(list_to_atom(Name1), 1, Loaded).
  350. paths_checkout_deps(Config) ->
  351. AppDir = ?config(apps, Config),
  352. [_Name1, Name2] = ?config(app_names, Config),
  353. [_Vsn1, Vsn2] = ?config(vsns, Config),
  354. %% rebar_test_utils:init_rebar_state/1,2 uses rebar_state:new/3 which
  355. %% maybe incorrectly sets deps to [] (based on `rebar.lock`) instead of
  356. %% to the checkapps
  357. %% until that is sorted out the lock file has to be removed before
  358. %% this test will pass
  359. file:delete(filename:join([AppDir, "rebar.lock"])),
  360. {ok, RebarConfig} = file:consult(filename:join([AppDir, "rebar.config"])),
  361. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  362. [AppName2] = rebar_state:all_checkout_deps(State),
  363. Name2Bin = binary:list_to_bin(Name2),
  364. Name2Bin = rebar_app_info:name(AppName2),
  365. code:add_paths(rebar_state:code_paths(State, all_deps)),
  366. ok = application:load(list_to_atom(Name2)),
  367. Loaded = application:loaded_applications(),
  368. {_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded).
  369. paths_basic_srcdirs(Config) ->
  370. AppDir = ?config(apps, Config),
  371. [Name] = ?config(app_names, Config),
  372. RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
  373. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  374. code:add_paths(rebar_state:code_paths(State, all_deps)),
  375. Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))),
  376. {module, Mod} = code:ensure_loaded(Mod),
  377. Expect = filename:join([AppDir, "_build", "default", "lib", Name, "ebin",
  378. io_lib:format("~ts_extra.beam", [Name])]),
  379. Expect = code:which(Mod).
  380. paths_release_srcdirs(Config) ->
  381. AppDir = ?config(apps, Config),
  382. [Name1, Name2] = ?config(app_names, Config),
  383. RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
  384. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  385. code:add_paths(rebar_state:code_paths(State, all_deps)),
  386. Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
  387. {module, Mod1} = code:ensure_loaded(Mod1),
  388. Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
  389. {module, Mod2} = code:ensure_loaded(Mod2),
  390. ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
  391. io_lib:format("~ts_extra.beam", [Name1])]),
  392. ExpectOne = code:which(Mod1),
  393. ExpectTwo = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin",
  394. io_lib:format("~ts_extra.beam", [Name2])]),
  395. ExpectTwo = code:which(Mod2).
  396. paths_unbalanced_srcdirs(Config) ->
  397. AppDir = ?config(apps, Config),
  398. [Name1, Name2] = ?config(app_names, Config),
  399. RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}],
  400. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  401. code:add_paths(rebar_state:code_paths(State, all_deps)),
  402. Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
  403. {module, Mod1} = code:ensure_loaded(Mod1),
  404. Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
  405. {error, nofile} = code:ensure_loaded(Mod2),
  406. ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin",
  407. io_lib:format("~ts_extra.beam", [Name1])]),
  408. ExpectOne = code:which(Mod1).
  409. paths_basic_extra_dirs(Config) ->
  410. AppDir = ?config(apps, Config),
  411. [Name] = ?config(app_names, Config),
  412. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  413. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  414. code:add_paths(rebar_state:code_paths(State, all_deps)),
  415. Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))),
  416. {module, Mod} = code:ensure_loaded(Mod),
  417. Expect = filename:join([AppDir, "_build", "default", "lib", Name, "extra",
  418. io_lib:format("~ts_extra.beam", [Name])]),
  419. Expect = code:which(Mod).
  420. paths_release_extra_dirs(Config) ->
  421. AppDir = ?config(apps, Config),
  422. [Name1, Name2] = ?config(app_names, Config),
  423. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  424. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  425. code:add_paths(rebar_state:code_paths(State, all_deps)),
  426. Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
  427. {module, Mod1} = code:ensure_loaded(Mod1),
  428. Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
  429. {module, Mod2} = code:ensure_loaded(Mod2),
  430. ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
  431. io_lib:format("~ts_extra.beam", [Name1])]),
  432. ExpectOne = code:which(Mod1),
  433. ExpectTwo = filename:join([AppDir, "_build", "default", "lib", Name2, "extra",
  434. io_lib:format("~ts_extra.beam", [Name2])]),
  435. ExpectTwo = code:which(Mod2).
  436. paths_unbalanced_extra_dirs(Config) ->
  437. AppDir = ?config(apps, Config),
  438. [Name1, Name2] = ?config(app_names, Config),
  439. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  440. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  441. code:add_paths(rebar_state:code_paths(State, all_deps)),
  442. Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
  443. {module, Mod1} = code:ensure_loaded(Mod1),
  444. Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
  445. {error, nofile} = code:ensure_loaded(Mod2),
  446. ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "extra",
  447. io_lib:format("~ts_extra.beam", [Name1])]),
  448. ExpectOne = code:which(Mod1).
  449. paths_extra_dirs_in_project_root(Config) ->
  450. AppDir = ?config(apps, Config),
  451. RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}],
  452. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
  453. code:add_paths(rebar_state:code_paths(State, all_deps)),
  454. {module, extra} = code:ensure_loaded(extra),
  455. Expect = filename:join([AppDir, "_build", "default", "extras", "extra", "extra.beam"]),
  456. Expect = code:which(extra).
  457. clean_basic_app(Config) ->
  458. [Name] = ?config(app_names, Config),
  459. rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}).
  460. clean_release_apps(Config) ->
  461. [Name1, Name2] = ?config(app_names, Config),
  462. rebar_test_utils:run_and_check(Config, [], ["clean"],
  463. {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}).
  464. clean_basic_extra_dirs(Config) ->
  465. AppDir = ?config(apps, Config),
  466. [Name] = ?config(app_names, Config),
  467. rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}),
  468. Beam = lists:flatten(io_lib:format("~ts_extra", [Name])),
  469. false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name, "extras", Beam])).
  470. clean_release_extra_dirs(Config) ->
  471. AppDir = ?config(apps, Config),
  472. [Name1, Name2] = ?config(app_names, Config),
  473. rebar_test_utils:run_and_check(Config, [], ["clean"],
  474. {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}),
  475. Beam1 = lists:flatten(io_lib:format("~ts_extra", [Name1])),
  476. false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name1, "extras", Beam1])),
  477. Beam2 = lists:flatten(io_lib:format("~ts_extra", [Name2])),
  478. false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name2, "extras", Beam2])).
  479. clean_extra_dirs_in_project_root(Config) ->
  480. AppDir = ?config(apps, Config),
  481. [Name1, Name2] = ?config(app_names, Config),
  482. rebar_test_utils:run_and_check(Config, [], ["clean"],
  483. {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}),
  484. false = ec_file:exists(filename:join([AppDir, "_build", "default", "extras"])).
  485. recompile_when_hrl_changes(Config) ->
  486. AppDir = ?config(apps, Config),
  487. Name = rebar_test_utils:create_random_name("app1_"),
  488. Vsn = rebar_test_utils:create_random_vsn(),
  489. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  490. ExtraSrc = <<"-module(test_header_include).\n"
  491. "-export([main/0]).\n"
  492. "-include(\"test_header_include.hrl\").\n"
  493. "main() -> ?SOME_DEFINE.\n">>,
  494. ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>,
  495. HeaderFile = filename:join([AppDir, "src", "test_header_include.hrl"]),
  496. ok = file:write_file(filename:join([AppDir, "src", "test_header_include.erl"]), ExtraSrc),
  497. ok = file:write_file(HeaderFile, ExtraHeader),
  498. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  499. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  500. {ok, Files} = rebar_utils:list_dir(EbinDir),
  501. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  502. || F <- Files, filename:extension(F) == ".beam"],
  503. timer:sleep(1000),
  504. NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>,
  505. ok = file:write_file(HeaderFile, NewExtraHeader),
  506. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  507. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  508. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  509. || F <- NewFiles, filename:extension(F) == ".beam"],
  510. ?assert(ModTime =/= NewModTime).
  511. recompile_when_included_hrl_changes(Config) ->
  512. AppDir = ?config(apps, Config),
  513. Name = rebar_test_utils:create_random_name("app1_"),
  514. Vsn = rebar_test_utils:create_random_vsn(),
  515. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  516. ExtraSrc = <<"-module(test_header_include).\n"
  517. "-export([main/0]).\n"
  518. "-include(\"test_header_include.hrl\").\n"
  519. "main() -> ?SOME_DEFINE.\n">>,
  520. ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>,
  521. ok = filelib:ensure_dir(filename:join([AppDir, "include", "dummy"])),
  522. HeaderFile = filename:join([AppDir, "include", "test_header_include.hrl"]),
  523. ok = file:write_file(filename:join([AppDir, "src", "test_header_include.erl"]), ExtraSrc),
  524. ok = file:write_file(HeaderFile, ExtraHeader),
  525. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  526. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  527. {ok, Files} = rebar_utils:list_dir(EbinDir),
  528. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  529. || F <- Files, filename:extension(F) == ".beam"],
  530. timer:sleep(1000),
  531. NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>,
  532. ok = file:write_file(HeaderFile, NewExtraHeader),
  533. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  534. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  535. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  536. || F <- NewFiles, filename:extension(F) == ".beam"],
  537. ?assert(ModTime =/= NewModTime).
  538. recompile_extra_when_hrl_in_src_changes(Config) ->
  539. AppDir = ?config(apps, Config),
  540. Name = rebar_test_utils:create_random_name("app1_"),
  541. Vsn = rebar_test_utils:create_random_vsn(),
  542. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  543. ExtraSrc = <<"-module(test_header_include).\n"
  544. "-export([main/0]).\n"
  545. "-include(\"test_header_include.hrl\").\n"
  546. "main() -> ?SOME_DEFINE.\n">>,
  547. ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>,
  548. HeaderFile = filename:join([AppDir, "src", "test_header_include.hrl"]),
  549. SrcFile = filename:join([AppDir, "extra", "test_header_include.erl"]),
  550. filelib:ensure_dir(SrcFile),
  551. ok = file:write_file(SrcFile, ExtraSrc),
  552. ok = file:write_file(HeaderFile, ExtraHeader),
  553. RebarCfg = [{extra_src_dirs, ["extra"]}],
  554. rebar_test_utils:run_and_check(Config, RebarCfg, ["compile"],
  555. {ok, [{app, Name}]}),
  556. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]),
  557. {ok, Files} = rebar_utils:list_dir(EbinDir),
  558. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  559. || F <- Files, filename:extension(F) == ".beam"],
  560. timer:sleep(1000),
  561. NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>,
  562. ok = file:write_file(HeaderFile, NewExtraHeader, [sync]),
  563. rebar_test_utils:run_and_check(Config, RebarCfg, ["compile"],
  564. {ok, [{app, Name}]}),
  565. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  566. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  567. || F <- NewFiles, filename:extension(F) == ".beam"],
  568. ?assert(ModTime =/= NewModTime).
  569. recompile_when_opts_included_hrl_changes(Config) ->
  570. AppsDir = ?config(apps, Config),
  571. Name = rebar_test_utils:create_random_name("app1_"),
  572. Vsn = rebar_test_utils:create_random_vsn(),
  573. AppDir = filename:join([AppsDir, "apps", Name]),
  574. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  575. ExtraSrc = <<"-module(test_header_include).\n"
  576. "-export([main/0]).\n"
  577. "-include(\"test_header_include.hrl\").\n"
  578. "main() -> ?SOME_DEFINE.\n">>,
  579. ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>,
  580. ok = filelib:ensure_dir(filename:join([AppsDir, "include", "dummy"])),
  581. HeaderFile = filename:join([AppsDir, "include", "test_header_include.hrl"]),
  582. ok = file:write_file(filename:join([AppDir, "src", "test_header_include.erl"]), ExtraSrc),
  583. ok = file:write_file(HeaderFile, ExtraHeader),
  584. %% Using relative path from the project root
  585. RebarConfig = [{erl_opts, [{i, "include/"}]}],
  586. {ok,Cwd} = file:get_cwd(),
  587. ok = file:set_cwd(AppsDir),
  588. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  589. EbinDir = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]),
  590. {ok, Files} = rebar_utils:list_dir(EbinDir),
  591. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  592. || F <- Files, filename:extension(F) == ".beam"],
  593. timer:sleep(1000),
  594. NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>,
  595. ok = file:write_file(HeaderFile, NewExtraHeader),
  596. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  597. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  598. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  599. || F <- NewFiles, filename:extension(F) == ".beam"],
  600. ok = file:set_cwd(Cwd),
  601. ?assert(ModTime =/= NewModTime).
  602. recompile_when_foreign_included_hrl_changes(Config) ->
  603. AppDir = ?config(apps, Config),
  604. AppsDir = filename:join([AppDir, "apps"]),
  605. Name1 = rebar_test_utils:create_random_name("app1_"),
  606. Name2 = rebar_test_utils:create_random_name("app2_"),
  607. Vsn = rebar_test_utils:create_random_vsn(),
  608. rebar_test_utils:create_app(filename:join(AppsDir, Name1),
  609. Name1, Vsn, [kernel, stdlib]),
  610. rebar_test_utils:create_app(filename:join(AppsDir, Name2),
  611. Name2, Vsn, [kernel, stdlib]),
  612. ExtraSrc = [<<"-module(test_header_include).\n"
  613. "-export([main/0]).\n"
  614. "-include_lib(\"">>, Name2, <<"/include/test_header_include.hrl\").\n"
  615. "main() -> ?SOME_DEFINE.\n">>],
  616. ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>,
  617. ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])),
  618. ok = filelib:ensure_dir(filename:join([AppsDir, Name2, "include", "dummy"])),
  619. HeaderFile = filename:join([AppsDir, Name2, "include", "test_header_include.hrl"]),
  620. ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_header_include.erl"]), ExtraSrc),
  621. ok = file:write_file(HeaderFile, ExtraHeader),
  622. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
  623. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]),
  624. {ok, Files} = rebar_utils:list_dir(EbinDir),
  625. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  626. || F <- Files, filename:extension(F) == ".beam"],
  627. timer:sleep(1000),
  628. NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>,
  629. ok = file:write_file(HeaderFile, NewExtraHeader),
  630. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
  631. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  632. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  633. || F <- NewFiles, filename:extension(F) == ".beam"],
  634. ?assert(ModTime =/= NewModTime).
  635. recompile_when_foreign_behaviour_changes(Config) ->
  636. AppDir = ?config(apps, Config),
  637. AppsDir = filename:join([AppDir, "apps"]),
  638. Name1 = rebar_test_utils:create_random_name("app1_"),
  639. Name2 = rebar_test_utils:create_random_name("app2_"),
  640. Vsn = rebar_test_utils:create_random_vsn(),
  641. rebar_test_utils:create_app(filename:join(AppsDir, Name1),
  642. Name1, Vsn, [kernel, stdlib]),
  643. rebar_test_utils:create_app(filename:join(AppsDir, Name2),
  644. Name2, Vsn, [kernel, stdlib]),
  645. ExtraSrc = <<"-module(test_behaviour_include).\n"
  646. "-export([main/0]).\n"
  647. "-behaviour(app2_behaviour).\n"
  648. "main() -> 1.\n">>,
  649. Behaviour = <<"-module(app2_behaviour).\n"
  650. "-callback main() -> term().\n">>,
  651. ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])),
  652. ok = filelib:ensure_dir(filename:join([AppsDir, Name2, "src", "dummy"])),
  653. BehaviourFile = filename:join([AppsDir, Name2, "src", "app2_behaviour.erl"]),
  654. ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_behaviour_include.erl"]), ExtraSrc),
  655. ok = file:write_file(BehaviourFile, Behaviour),
  656. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
  657. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]),
  658. {ok, Files} = rebar_utils:list_dir(EbinDir),
  659. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  660. || F <- Files, filename:extension(F) == ".beam"],
  661. timer:sleep(1000),
  662. NewBehaviour = <<"-module(app2_behaviour).\n"
  663. "-callback main(_) -> term().\n">>,
  664. ok = file:write_file(BehaviourFile, NewBehaviour),
  665. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
  666. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  667. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  668. || F <- NewFiles, filename:extension(F) == ".beam"],
  669. ?assert(ModTime =/= NewModTime).
  670. recompile_when_recursive_behaviour_changes(Config) ->
  671. AppDir = ?config(apps, Config),
  672. AppsDir = filename:join([AppDir, "apps"]),
  673. Name1 = rebar_test_utils:create_random_name("app1_"),
  674. Vsn = rebar_test_utils:create_random_vsn(),
  675. rebar_test_utils:create_app(filename:join(AppsDir, Name1),
  676. Name1, Vsn, [kernel, stdlib]),
  677. ExtraSrc = <<"-module(test_behaviour_include).\n"
  678. "-export([main/0]).\n"
  679. "-behaviour(app1_behaviour).\n"
  680. "main() -> 1.\n">>,
  681. Behaviour = <<"-module(app1_behaviour).\n"
  682. "-callback main() -> term().\n">>,
  683. ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])),
  684. ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "sub", "dummy"])),
  685. BehaviourFile = filename:join([AppsDir, Name1, "src", "sub", "app1_behaviour.erl"]),
  686. ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_behaviour_include.erl"]), ExtraSrc),
  687. ok = file:write_file(BehaviourFile, Behaviour),
  688. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
  689. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]),
  690. {ok, Files} = rebar_utils:list_dir(EbinDir),
  691. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  692. || F <- Files,
  693. filename:extension(F) == ".beam",
  694. filename:basename(F) =/= "app1_behaviour.beam"],
  695. timer:sleep(1000),
  696. NewBehaviour = <<"-module(app1_behaviour).\n"
  697. "-callback main(_) -> term().\n">>,
  698. ok = file:write_file(BehaviourFile, NewBehaviour),
  699. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}),
  700. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  701. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  702. || F <- NewFiles,
  703. filename:extension(F) == ".beam",
  704. filename:basename(F) =/= "app1_behaviour.beam"],
  705. ?assert(ModTime =/= NewModTime).
  706. recompile_when_opts_change(Config) ->
  707. AppDir = ?config(apps, Config),
  708. Name = rebar_test_utils:create_random_name("app1_"),
  709. Vsn = rebar_test_utils:create_random_vsn(),
  710. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  711. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  712. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  713. {ok, Files} = rebar_utils:list_dir(EbinDir),
  714. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  715. || F <- Files, filename:extension(F) == ".beam"],
  716. timer:sleep(1000),
  717. rebar_test_utils:create_config(AppDir, [{erl_opts, [{d, some_define}]}]),
  718. rebar_test_utils:run_and_check(Config, [{erl_opts, [{d, some_define}]}], ["compile"], {ok, [{app, Name}]}),
  719. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  720. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  721. || F <- NewFiles, filename:extension(F) == ".beam"],
  722. ?assert(ModTime =/= NewModTime).
  723. recompile_when_dag_opts_change(Config) ->
  724. AppDir = ?config(apps, Config),
  725. Name = rebar_test_utils:create_random_name("app1_"),
  726. Vsn = rebar_test_utils:create_random_vsn(),
  727. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  728. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  729. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  730. {ok, Files} = rebar_utils:list_dir(EbinDir),
  731. Beams = [filename:join([EbinDir, F])
  732. || F <- Files, filename:extension(F) == ".beam"],
  733. ModTime = [filelib:last_modified(Beam) || Beam <- Beams],
  734. timer:sleep(1000),
  735. DepsDir = filename:join([AppDir, "_build", "default", "lib"]),
  736. G = rebar_compiler_dag:init(DepsDir, rebar_compiler_erl, "project_apps", []),
  737. %% change the config in the DAG...
  738. [digraph:add_vertex(G, Beam, {artifact, [{d, some_define}]}) || Beam <- Beams],
  739. digraph:add_vertex(G, '$r3_dirty_bit', true), % trigger a save
  740. %% the rebar_compiler_erl module is annotated with a compiler version
  741. %% to help rebuild deps
  742. {ok, CompileVsn} = application:get_key(compiler, vsn),
  743. CritMeta = [{compiler, CompileVsn}],
  744. rebar_compiler_dag:maybe_store(G, DepsDir, rebar_compiler_erl, "project_apps", CritMeta),
  745. rebar_compiler_dag:terminate(G),
  746. %% ... but don't change the actual rebar3 config...
  747. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  748. %% ... and checks that it rebuilds anyway due to DAG changes
  749. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  750. NewBeams = [filename:join([EbinDir, F])
  751. || F <- NewFiles, filename:extension(F) == ".beam"],
  752. NewModTime = [filelib:last_modified(Beam) || Beam <- NewBeams],
  753. ?assert(ModTime =/= NewModTime).
  754. dont_recompile_when_opts_dont_change(Config) ->
  755. AppDir = ?config(apps, Config),
  756. Name = rebar_test_utils:create_random_name("app1_"),
  757. Vsn = rebar_test_utils:create_random_vsn(),
  758. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  759. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  760. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  761. {ok, Files} = rebar_utils:list_dir(EbinDir),
  762. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  763. || F <- Files, filename:extension(F) == ".beam"],
  764. timer:sleep(1000),
  765. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  766. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  767. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  768. || F <- NewFiles, filename:extension(F) == ".beam"],
  769. ?assertEqual(ModTime, NewModTime).
  770. dont_recompile_yrl_or_xrl(Config) ->
  771. AppDir = ?config(apps, Config),
  772. Name = rebar_test_utils:create_random_name("app1_"),
  773. Vsn = rebar_test_utils:create_random_vsn(),
  774. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  775. Xrl = filename:join([AppDir, "src", "not_a_real_xrl_" ++ Name ++ ".xrl"]),
  776. ok = filelib:ensure_dir(Xrl),
  777. XrlBody =
  778. "Definitions."
  779. "\n\n"
  780. "D = [0-9]"
  781. "\n\n"
  782. "Rules."
  783. "\n\n"
  784. "{D}+ :"
  785. " {token,{integer,TokenLine,list_to_integer(TokenChars)}}."
  786. "\n\n"
  787. "{D}+\\.{D}+((E|e)(\\+|\\-)?{D}+)? :"
  788. " {token,{float,TokenLine,list_to_float(TokenChars)}}."
  789. "\n\n"
  790. "Erlang code.",
  791. ok = ec_file:write(Xrl, XrlBody),
  792. Yrl = filename:join([AppDir, "src", "not_a_real_yrl_" ++ Name ++ ".yrl"]),
  793. ok = filelib:ensure_dir(Yrl),
  794. YrlBody = ["Nonterminals E T F.\n"
  795. "Terminals '+' '*' '(' ')' number.\n"
  796. "Rootsymbol E.\n"
  797. "E -> E '+' T: {'$2', '$1', '$3'}.\n"
  798. "E -> T : '$1'.\n"
  799. "T -> T '*' F: {'$2', '$1', '$3'}.\n"
  800. "T -> F : '$1'.\n"
  801. "F -> '(' E ')' : '$2'.\n"
  802. "F -> number : '$1'.\n"],
  803. ok = ec_file:write(Yrl, YrlBody),
  804. XrlErl = filename:join([AppDir, "src", filename:basename(Xrl, ".xrl") ++ ".erl"]),
  805. YrlErl = filename:join([AppDir, "src", filename:basename(Yrl, ".yrl") ++ ".erl"]),
  806. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  807. XrlBeam = filename:join([EbinDir, filename:basename(Xrl, ".xrl") ++ ".beam"]),
  808. YrlBeam = filename:join([EbinDir, filename:basename(Yrl, ".yrl") ++ ".beam"]),
  809. Hrl = filename:join([AppDir, "include", "some_header.hrl"]),
  810. ok = filelib:ensure_dir(Hrl),
  811. HrlBody = yeccpre_hrl(),
  812. ok = ec_file:write(Hrl, HrlBody),
  813. RebarConfig = [{yrl_opts, [{includefile, "include/some_header.hrl"}]}],
  814. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  815. XrlModTime = filelib:last_modified(XrlErl),
  816. YrlModTime = filelib:last_modified(YrlErl),
  817. XrlBeamModTime = filelib:last_modified(XrlBeam),
  818. YrlBeamModTime = filelib:last_modified(YrlBeam),
  819. timer:sleep(1000),
  820. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  821. NewXrlModTime = filelib:last_modified(XrlErl),
  822. NewYrlModTime = filelib:last_modified(YrlErl),
  823. NewXrlBeamModTime = filelib:last_modified(XrlBeam),
  824. NewYrlBeamModTime = filelib:last_modified(YrlBeam),
  825. ?assert(XrlBeamModTime == NewXrlBeamModTime),
  826. ?assert(YrlBeamModTime == NewYrlBeamModTime),
  827. ?assert(XrlModTime == NewXrlModTime),
  828. ?assert(YrlModTime == NewYrlModTime).
  829. delete_beam_if_source_deleted(Config) ->
  830. AppDir = ?config(apps, Config),
  831. Name = rebar_test_utils:create_random_name("app1_"),
  832. Vsn = rebar_test_utils:create_random_vsn(),
  833. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  834. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  835. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  836. _SrcDir = filename:join([AppDir, "_build", "default", "lib", Name, "src"]),
  837. ?assert(filelib:is_regular(filename:join(EbinDir, "not_a_real_src_" ++ Name ++ ".beam"))),
  838. file:delete(filename:join([AppDir, "src", "not_a_real_src_" ++ Name ++ ".erl"])),
  839. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  840. ?assertNot(filelib:is_regular(filename:join(EbinDir, "not_a_real_src_" ++ Name ++ ".beam"))).
  841. deps_in_path(Config) ->
  842. AppDir = ?config(apps, Config),
  843. StartPaths = code:get_path(),
  844. Name = rebar_test_utils:create_random_name("app1_"),
  845. Vsn = rebar_test_utils:create_random_vsn(),
  846. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  847. DepName = rebar_test_utils:create_random_name("dep1_"),
  848. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  849. mock_git_resource:mock([]),
  850. mock_pkg_resource:mock([
  851. {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]}
  852. ]),
  853. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [
  854. {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}},
  855. {list_to_atom(PkgName), Vsn}
  856. ]}]),
  857. {ok, RConf} = file:consult(RConfFile),
  858. %% Make sure apps we look for are not visible
  859. %% Hope not to find src name
  860. ?assertEqual([], [Path || Path <- code:get_path(),
  861. {match, _} <- [re:run(Path, DepName)]]),
  862. %% Hope not to find pkg name in there
  863. ?assertEqual([], [Path || Path <- code:get_path(),
  864. {match, _} <- [re:run(Path, PkgName)]]),
  865. %% Build things
  866. {ok, State} = rebar_test_utils:run_and_check(
  867. Config, RConf, ["compile"],
  868. {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]}
  869. ),
  870. code:add_paths(rebar_state:code_paths(State, all_deps)),
  871. %% Find src name in there
  872. ?assertNotEqual([], [Path || Path <- code:get_path(),
  873. {match, _} <- [re:run(Path, DepName)]]),
  874. %% find pkg name in there
  875. ?assertNotEqual([], [Path || Path <- code:get_path(),
  876. {match, _} <- [re:run(Path, PkgName)]]),
  877. true = code:set_path(lists:filter(fun(P) -> ec_file:exists(P) end, StartPaths)),
  878. %% Make sure apps we look for are not visible again
  879. %% Hope not to find src name
  880. ?assertEqual([], [Path || Path <- code:get_path(),
  881. {match, _} <- [re:run(Path, DepName)]]),
  882. %% Hope not to find pkg name in there
  883. ?assertEqual([], [Path || Path <- code:get_path(),
  884. {match, _} <- [re:run(Path, PkgName)]]),
  885. %% Rebuild
  886. {ok, State1} = rebar_test_utils:run_and_check(
  887. Config, RConf, ["compile"],
  888. {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]}
  889. ),
  890. %% Find src name in there
  891. code:add_paths(rebar_state:code_paths(State1, all_deps)),
  892. ?assertNotEqual([], [Path || Path <- code:get_path(),
  893. {match, _} <- [re:run(Path, DepName)]]),
  894. %% find pkg name in there
  895. ?assertNotEqual([], [Path || Path <- code:get_path(),
  896. {match, _} <- [re:run(Path, PkgName)]]).
  897. checkout_priority(Config) ->
  898. AppDir = ?config(apps, Config),
  899. CheckoutsDir = ?config(checkouts, Config),
  900. StartPaths = code:get_path(),
  901. Name = rebar_test_utils:create_random_name("app1_"),
  902. Vsn = rebar_test_utils:create_random_vsn(),
  903. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  904. DepName = rebar_test_utils:create_random_name("dep1_"),
  905. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  906. mock_git_resource:mock([]),
  907. mock_pkg_resource:mock([
  908. {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]}
  909. ]),
  910. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [
  911. {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}},
  912. {list_to_atom(PkgName), Vsn}
  913. ]}]),
  914. {ok, RConf} = file:consult(RConfFile),
  915. %% Build with deps.
  916. rebar_test_utils:run_and_check(
  917. Config, RConf, ["compile"],
  918. {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]}
  919. ),
  920. %% Build two checkout apps similar to dependencies to be fetched,
  921. %% but on a different version
  922. Vsn2 = rebar_test_utils:create_random_vsn(),
  923. rebar_test_utils:create_app(filename:join([CheckoutsDir,DepName]), DepName, Vsn2, [kernel, stdlib]),
  924. rebar_test_utils:create_app(filename:join([CheckoutsDir,PkgName]), PkgName, Vsn2, [kernel, stdlib]),
  925. %% Rebuild and make sure the checkout apps are in path
  926. code:set_path(StartPaths),
  927. {ok, State} = rebar_test_utils:run_and_check(
  928. Config, RConf, ["compile"],
  929. {ok, [{app, Name}, {checkout, DepName}, {checkout, PkgName}]}
  930. ),
  931. code:add_paths(rebar_state:code_paths(State, all_deps)),
  932. [DepPath] = [Path || Path <- code:get_path(),
  933. {match, _} <- [re:run(Path, DepName)]],
  934. [PkgPath] = [Path || Path <- code:get_path(),
  935. {match, _} <- [re:run(Path, PkgName)]],
  936. {ok, [DepApp]} = file:consult(filename:join([DepPath, DepName ++ ".app"])),
  937. {ok, [PkgApp]} = file:consult(filename:join([PkgPath, PkgName ++ ".app"])),
  938. {application, _, DepProps} = DepApp,
  939. {application, _, PkgProps} = PkgApp,
  940. ?assertEqual(Vsn2, proplists:get_value(vsn, DepProps)),
  941. ?assertEqual(Vsn2, proplists:get_value(vsn, PkgProps)).
  942. highest_version_of_pkg_dep(Config) ->
  943. AppDir = ?config(apps, Config),
  944. Name = rebar_test_utils:create_random_name("app1_"),
  945. Vsn = rebar_test_utils:create_random_vsn(),
  946. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  947. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  948. mock_git_resource:mock([]),
  949. mock_pkg_resource:mock([
  950. {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []},
  951. {{iolist_to_binary(PkgName), <<"0.0.1">>}, []},
  952. {{iolist_to_binary(PkgName), <<"0.1.3">>}, []},
  953. {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}
  954. ]),
  955. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [list_to_atom(PkgName)]}]),
  956. {ok, RConf} = file:consult(RConfFile),
  957. %% Build with deps.
  958. rebar_test_utils:run_and_check(
  959. Config, RConf, ["compile"],
  960. {ok, [{app, Name}, {dep, PkgName, <<"0.1.3">>}]}
  961. ).
  962. parse_transform_test(Config) ->
  963. AppDir = ?config(apps, Config),
  964. RebarConfig = [{erl_opts, [{parse_transform, pascal}]}],
  965. Name = rebar_test_utils:create_random_name("app1_"),
  966. Vsn = rebar_test_utils:create_random_vsn(),
  967. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  968. ExtraSrc = <<"-module(pascal). "
  969. "-export([parse_transform/2]). "
  970. "parse_transform(Forms, _Options) -> "
  971. "Forms.">>,
  972. ok = file:write_file(filename:join([AppDir, "src", "pascal.erl"]), ExtraSrc),
  973. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  974. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  975. true = filelib:is_file(filename:join([EbinDir, "pascal.beam"])).
  976. erl_first_files_test(Config) ->
  977. AppDir = ?config(apps, Config),
  978. RebarConfig = [{erl_opts, [{parse_transform, mark_time}]},
  979. {erl_first_files, ["src/mark_time.erl",
  980. "src/b.erl",
  981. "src/d.erl",
  982. "src/a.erl"]}],
  983. Name = rebar_test_utils:create_random_name("app1_"),
  984. Vsn = rebar_test_utils:create_random_vsn(),
  985. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  986. rebar_test_utils:write_src_file(AppDir, "a.erl"),
  987. rebar_test_utils:write_src_file(AppDir, "b.erl"),
  988. rebar_test_utils:write_src_file(AppDir, "d.erl"),
  989. rebar_test_utils:write_src_file(AppDir, "e.erl"),
  990. ExtraSrc = <<"-module(mark_time). "
  991. "-export([parse_transform/2]). "
  992. "parse_transform([Form={attribute,_,module,Mod}|Forms], Options) -> "
  993. " [Form, {attribute,1,number, os:timestamp()} | Forms];"
  994. "parse_transform([Form|Forms], Options) -> "
  995. " [Form | parse_transform(Forms, Options)].">>,
  996. ok = file:write_file(filename:join([AppDir, "src", "mark_time.erl"]), ExtraSrc),
  997. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  998. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  999. true = filelib:is_file(filename:join([EbinDir, "mark_time.beam"])),
  1000. code:load_abs(filename:join([EbinDir, "a"])),
  1001. code:load_abs(filename:join([EbinDir, "b"])),
  1002. code:load_abs(filename:join([EbinDir, "d"])),
  1003. code:load_abs(filename:join([EbinDir, "e"])),
  1004. A = proplists:get_value(number, a:module_info(attributes)),
  1005. B = proplists:get_value(number, b:module_info(attributes)),
  1006. D = proplists:get_value(number, d:module_info(attributes)),
  1007. E = proplists:get_value(number, e:module_info(attributes)),
  1008. ?assertEqual([B,D,A,E], lists:sort([A,B,D,E])).
  1009. mib_test(Config) ->
  1010. AppDir = ?config(apps, Config),
  1011. RebarConfig = [{mib_first_files, ["mibs/SIMPLE-MIB.mib"]}],
  1012. Name = rebar_test_utils:create_random_name("app1_"),
  1013. Vsn = rebar_test_utils:create_random_vsn(),
  1014. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1015. MibsSrc = <<"-- SIMPLE-MIB.\n"
  1016. "-- This is just a simple MIB used for testing!\n"
  1017. "--\n"
  1018. "SIMPLE-MIB DEFINITIONS ::= BEGIN\n"
  1019. "IMPORTS\n"
  1020. " MODULE-IDENTITY, enterprises\n"
  1021. " FROM SNMPv2-SMI;\n"
  1022. "\n"
  1023. "ericsson MODULE-IDENTITY\n"
  1024. " LAST-UPDATED\n"
  1025. " \"201403060000Z\"\n"
  1026. " ORGANIZATION\n"
  1027. " \"rebar\"\n"
  1028. " CONTACT-INFO\n"
  1029. " \"rebar <rebar@example.com>\n"
  1030. " or\n"
  1031. " whoever is currently responsible for the SIMPLE\n"
  1032. " enterprise MIB tree branch (enterprises.999).\"\n"
  1033. " DESCRIPTION\n"
  1034. " \"This very small module is made available\n"
  1035. " for mib-compilation testing.\"\n"
  1036. " ::= { enterprises 999 }\n"
  1037. "END\n">>,
  1038. ok = filelib:ensure_dir(filename:join([AppDir, "mibs", "dummy"])),
  1039. ok = file:write_file(filename:join([AppDir, "mibs", "SIMPLE-MIB.mib"]), MibsSrc),
  1040. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  1041. %% check a bin corresponding to the mib in the mibs dir exists in priv/mibs
  1042. PrivMibsDir = filename:join([AppDir, "_build", "default", "lib", Name, "priv", "mibs"]),
  1043. true = filelib:is_file(filename:join([PrivMibsDir, "SIMPLE-MIB.bin"])),
  1044. %% check a hrl corresponding to the mib in the mibs dir exists in include
  1045. true = filelib:is_file(filename:join([AppDir, "include", "SIMPLE-MIB.hrl"])),
  1046. %% check the mibs dir was linked into the _build dir
  1047. true = filelib:is_dir(filename:join([AppDir, "_build", "default", "lib", Name, "mibs"])).
  1048. umbrella_mib_first_test(Config) ->
  1049. AppsDir = ?config(apps, Config),
  1050. Name = rebar_test_utils:create_random_name("app1_"),
  1051. Vsn = rebar_test_utils:create_random_vsn(),
  1052. AppDir = filename:join([AppsDir, "apps", Name]),
  1053. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1054. BExporterSrc = <<"-- BEXPORTER-MIB.\n"
  1055. "-- This is just a simple MIB used for testing!\n"
  1056. "--\n"
  1057. "BEXPORTER-MIB DEFINITIONS ::= BEGIN\n"
  1058. "IMPORTS\n"
  1059. " TEXTUAL-CONVENTION\n"
  1060. " FROM SNMPv2-TC\n"
  1061. " MODULE-IDENTITY, enterprises\n"
  1062. " FROM SNMPv2-SMI;\n"
  1063. "\n"
  1064. "ericsson MODULE-IDENTITY\n"
  1065. " LAST-UPDATED\n"
  1066. " \"201812050000Z\"\n"
  1067. " ORGANIZATION\n"
  1068. " \"rebar\"\n"
  1069. " CONTACT-INFO\n"
  1070. " \"rebar <rebar@example.com>\n"
  1071. " or\n"
  1072. " whoever is currently responsible for the SIMPLE\n"
  1073. " enterprise MIB tree branch (enterprises.999).\"\n"
  1074. " DESCRIPTION\n"
  1075. " \"This very small module is made available\n"
  1076. " for mib-compilation testing.\"\n"
  1077. " ::= { enterprises 999 }\n"
  1078. "\n"
  1079. "Something ::= TEXTUAL-CONVENTION\n"
  1080. " STATUS current\n"
  1081. " DESCRIPTION \"\"\n"
  1082. " SYNTAX OCTET STRING (SIZE (4))\n"
  1083. "END\n">>,
  1084. AImporterSrc = <<"-- AIMPORTER-MIB.\n"
  1085. "-- This is just a simple MIB used for testing!\n"
  1086. "--\n"
  1087. "AIMPORTER-MIB DEFINITIONS ::= BEGIN\n"
  1088. "IMPORTS\n"
  1089. " Something\n"
  1090. " FROM BEXPORTER-MIB\n"
  1091. " MODULE-IDENTITY, enterprises\n"
  1092. " FROM SNMPv2-SMI;\n"
  1093. "\n"
  1094. "ericsson MODULE-IDENTITY\n"
  1095. " LAST-UPDATED\n"
  1096. " \"201812050000Z\"\n"
  1097. " ORGANIZATION\n"
  1098. " \"rebar\"\n"
  1099. " CONTACT-INFO\n"
  1100. " \"rebar <rebar@example.com>\n"
  1101. " or\n"
  1102. " whoever is currently responsible for the SIMPLE\n"
  1103. " enterprise MIB tree branch (enterprises.999).\"\n"
  1104. " DESCRIPTION\n"
  1105. " \"This very small module is made available\n"
  1106. " for mib-compilation testing.\"\n"
  1107. " ::= { enterprises 1000 }\n"
  1108. "END\n">>,
  1109. ok = filelib:ensure_dir(filename:join([AppDir, "mibs", "dummy"])),
  1110. ok = file:write_file(filename:join([AppDir, "mibs", "AIMPORTER-MIB.mib"]), AImporterSrc),
  1111. ok = file:write_file(filename:join([AppDir, "mibs", "BEXPORTER-MIB.mib"]), BExporterSrc),
  1112. FailureRebarConfig = [{mib_first_files, ["mibs/AIMPORTER-MIB.mib"]}],
  1113. SuccessRebarConfig = [{mib_first_files, ["mibs/BEXPORTER-MIB.mib"]}],
  1114. PrivMibsDir = filename:join([AppsDir, "_build", "default", "lib", Name, "priv", "mibs"]),
  1115. FailureRebarConfig = [{mib_first_files, ["mibs/AIMPORTER-MIB.mib"]}],
  1116. catch (
  1117. rebar_test_utils:run_and_check(Config, FailureRebarConfig, ["compile"], {ok, [{app, Name}]}) ),
  1118. %% check that the bin file was NOT cretated
  1119. false = filelib:is_file(filename:join([PrivMibsDir, "AIMPORTER-MIB.bin"])),
  1120. SuccessRebarConfig = [{mib_first_files, ["mibs/BEXPORTER-MIB.mib"]}],
  1121. rebar_test_utils:run_and_check(Config, SuccessRebarConfig, ["compile"], {ok, [{app, Name}]}),
  1122. %% check a bin corresponding to the mib in the mibs dir exists in priv/mibs
  1123. true = filelib:is_file(filename:join([PrivMibsDir, "AIMPORTER-MIB.bin"])),
  1124. %% check a hrl corresponding to the mib in the mibs dir exists in include
  1125. true = filelib:is_file(filename:join([AppDir, "include", "AIMPORTER-MIB.hrl"])),
  1126. %% check the mibs dir was linked into the _build dir
  1127. true = filelib:is_dir(filename:join([AppsDir, "_build", "default", "lib", Name, "mibs"])).
  1128. deps_mib_test() ->
  1129. [{doc, "reproduces the dependency handling required for the issue "
  1130. "reported in https://github.com/erlang/rebar3/issues/2372"}].
  1131. deps_mib_test(Config) ->
  1132. Priv = ?config(priv_dir, Config),
  1133. CliLvl2Mib =
  1134. "---\n"
  1135. "---\n"
  1136. "---\n"
  1137. "LVL2-MIB DEFINITIONS ::= BEGIN\n"
  1138. "IMPORTS\n"
  1139. " MODULE-IDENTITY, OBJECT-TYPE\n"
  1140. " FROM SNMPv2-SMI\n"
  1141. " lvlModules, lvlApplications\n"
  1142. " FROM LVL0-REG\n"
  1143. " LvlFoo\n"
  1144. " FROM LVL0-TC\n"
  1145. " ;\n"
  1146. "\n"
  1147. "lvl2Module MODULE-IDENTITY\n"
  1148. " LAST-UPDATED \"202009261630Z\"\n"
  1149. " ORGANIZATION \"'some org'\"\n"
  1150. " CONTACT-INFO \"'Contact: some contact'\"\n"
  1151. " DESCRIPTION\n"
  1152. " \" \"\n"
  1153. " ::= { lvlModules 3 }\n"
  1154. "\n\n\n"
  1155. "END",
  1156. CpiLvl0Mib1 =
  1157. " \n"
  1158. "---\n"
  1159. "---\n\n"
  1160. "LVL0-TC DEFINITIONS ::= BEGIN\n"
  1161. "IMPORTS\n"
  1162. " lvlModules\n"
  1163. " FROM LVL0-REG\n"
  1164. " MODULE-IDENTITY\n"
  1165. " FROM SNMPv2-SMI\n"
  1166. " TEXTUAL-CONVENTION\n"
  1167. " FROM SNMPv2-TC\n"
  1168. " ;\n\n"
  1169. "lvlTcModule MODULE-IDENTITY\n"
  1170. " LAST-UPDATED \"202009261630Z\"\n"
  1171. " ORGANIZATION \"'some org'\"\n"
  1172. " CONTACT-INFO \"'Contact: some contact'\"\n"
  1173. " DESCRIPTION\n"
  1174. " \" This MIB is part of the LVL MIB. It defines common\n"
  1175. " Textual Conventions used in other LVL mib modules.\"\n"
  1176. " ::= { lvlModules 2 }\n\n\n"
  1177. "LvlFoo ::= TEXTUAL-CONVENTION\n"
  1178. " DISPLAY-HINT \"512a\"\n"
  1179. " STATUS current\n"
  1180. " DESCRIPTION \"\"\n"
  1181. " SYNTAX OCTET STRING (SIZE (1..512))\n\n"
  1182. "LvlEnum ::= TEXTUAL-CONVENTION\n"
  1183. " STATUS current\n"
  1184. " DESCRIPTION \"\"\n"
  1185. " SYNTAX INTEGER { foo(1), bar(2), baz(3) }\n\n"
  1186. "END\n",
  1187. CpiLvl0Mib2 =
  1188. "---\n---\n---\n\n"
  1189. "LVL0-REG DEFINITIONS ::= BEGIN\n"
  1190. "\n"
  1191. "IMPORTS\n"
  1192. " MODULE-IDENTITY, enterprises\n"
  1193. " FROM SNMPv2-SMI\n"
  1194. " ;\n\n"
  1195. "lvlRegModule MODULE-IDENTITY\n"
  1196. " LAST-UPDATED \"202009261630Z\"\n"
  1197. " ORGANIZATION \"'some org'\"\n"
  1198. " CONTACT-INFO \"'Contact: some contact'\"\n"
  1199. " DESCRIPTION\n"
  1200. " \"The root MIB module for LVL\"\n"
  1201. " ::= { lvlModules 1 }\n\n"
  1202. "-- Example Enterprise Number for Documentation use\n"
  1203. "example OBJECT IDENTIFIER ::= { enterprises 32473 }\n"
  1204. "\n"
  1205. "lvl OBJECT IDENTIFIER ::= { example 1 }\n\n"
  1206. "-- sub-tree for registrations (Modules information)\n"
  1207. "lvlReg OBJECT IDENTIFIER ::= { lvl 1 }\n"
  1208. "lvlModules OBJECT IDENTIFIER ::= { lvlReg 1 }\n"
  1209. "\n"
  1210. "-- the application subtree\n"
  1211. "lvlApplications OBJECT IDENTIFIER ::= { lvl 2 }\n"
  1212. "END\n",
  1213. CliLvl2Path = filename:join([Priv, "deps_mib", "cli_lvl2", "mibs", "LVL2-MIB.mib"]),
  1214. CpiLvl0Path1 = filename:join([Priv, "deps_mib", "cpi_lvl0", "mibs", "LVL0-TC.mib"]),
  1215. CpiLvl0Path2 = filename:join([Priv, "deps_mib", "cpi_lvl0", "mibs", "LVL0-REG.mib"]),
  1216. NprLvl1Path = filename:join([Priv, "deps_mib", "npr_lvl1", "mibs"]), % no mibs dir
  1217. FakeLvl1Path = filename:join([Priv, "deps_mib", "fake_lvl1", "mibs", "no_file"]), % no mibs file
  1218. ok = filelib:ensure_dir(CliLvl2Path),
  1219. ok = filelib:ensure_dir(CpiLvl0Path1), % CpiLvl0Path2 is the same dir
  1220. ok = filelib:ensure_dir(NprLvl1Path),
  1221. ok = filelib:ensure_dir(FakeLvl1Path),
  1222. ok = file:write_file(CliLvl2Path, CliLvl2Mib),
  1223. ok = file:write_file(CpiLvl0Path1, CpiLvl0Mib1),
  1224. ok = file:write_file(CpiLvl0Path2, CpiLvl0Mib2),
  1225. Res = rebar_compiler_mib:dependencies(
  1226. CliLvl2Path,
  1227. filename:dirname(CliLvl2Path),
  1228. [filename:dirname(CliLvl2Path),
  1229. filename:dirname(CpiLvl0Path1),
  1230. NprLvl1Path,
  1231. filename:dirname(FakeLvl1Path)]
  1232. ),
  1233. ?assertEqual(lists:sort([CpiLvl0Path1, CpiLvl0Path2]),
  1234. lists:sort(Res)),
  1235. ok.
  1236. only_default_transitive_deps(Config) ->
  1237. AppDir = ?config(apps, Config),
  1238. Name = rebar_test_utils:create_random_name("app1_"),
  1239. Vsn = rebar_test_utils:create_random_vsn(),
  1240. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1241. GitDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}]),
  1242. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  1243. {SrcDeps, _} = rebar_test_utils:flat_deps(GitDeps),
  1244. mock_git_resource:mock([{deps, SrcDeps},
  1245. {config, [{profiles, [{test, [{deps, [list_to_atom(PkgName)]}]}]}]}]),
  1246. mock_pkg_resource:mock([{pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}]}]),
  1247. Deps = rebar_test_utils:top_level_deps(GitDeps),
  1248. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, Deps}]),
  1249. {ok, RConf} = file:consult(RConfFile),
  1250. %% Build with deps.
  1251. rebar_test_utils:run_and_check(
  1252. Config, RConf, ["as", "test", "compile"],
  1253. {ok, [{app, Name}, {dep, "a", <<"1.0.0">>}, {dep_not_exist, PkgName}]}
  1254. ).
  1255. clean_all(Config) ->
  1256. AppDir = ?config(apps, Config),
  1257. Name = rebar_test_utils:create_random_name("app1_"),
  1258. Vsn = rebar_test_utils:create_random_vsn(),
  1259. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1260. DepName = rebar_test_utils:create_random_name("dep1_"),
  1261. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  1262. mock_git_resource:mock([]),
  1263. mock_pkg_resource:mock([
  1264. {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]}
  1265. ]),
  1266. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [
  1267. {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}},
  1268. {list_to_atom(PkgName), Vsn}
  1269. ]}]),
  1270. {ok, RConf} = file:consult(RConfFile),
  1271. %% Build things
  1272. rebar_test_utils:run_and_check(
  1273. Config, RConf, ["compile"],
  1274. {ok, [{app, Name}, {app, DepName}, {app, PkgName}]}
  1275. ),
  1276. %% Clean all
  1277. rebar_test_utils:run_and_check(Config, [], ["clean", "--all"],
  1278. {ok, [{app, Name, invalid},
  1279. {app, DepName, invalid},
  1280. {app, PkgName, invalid}]}).
  1281. clean_specific(Config) ->
  1282. AppDir = ?config(apps, Config),
  1283. Name = rebar_test_utils:create_random_name("app1_"),
  1284. Vsn = rebar_test_utils:create_random_vsn(),
  1285. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1286. DepName = rebar_test_utils:create_random_name("dep1_"),
  1287. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  1288. mock_git_resource:mock([]),
  1289. mock_pkg_resource:mock([
  1290. {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]}
  1291. ]),
  1292. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [
  1293. {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}},
  1294. {list_to_atom(PkgName), Vsn}
  1295. ]}]),
  1296. {ok, RConf} = file:consult(RConfFile),
  1297. %% Build things
  1298. rebar_test_utils:run_and_check(
  1299. Config, RConf, ["compile"],
  1300. {ok, [{app, Name}, {app, DepName}, {app, PkgName}]}
  1301. ),
  1302. %% Clean all
  1303. rebar_test_utils:run_and_check(Config, [], ["clean", "--apps="++DepName++","++Name],
  1304. {ok, [{app, Name, invalid},
  1305. {app, DepName, invalid},
  1306. {app, PkgName, valid}]}).
  1307. override_deps(Config) ->
  1308. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1309. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1310. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1311. mock_git_resource:mock([{deps, SrcDeps}]),
  1312. RebarConfig = [
  1313. {deps, TopDeps},
  1314. {overrides, [
  1315. {override, some_dep, [
  1316. {deps, []}
  1317. ]}
  1318. ]}
  1319. ],
  1320. rebar_test_utils:run_and_check(
  1321. Config, RebarConfig, ["compile"],
  1322. {ok, [{dep, "some_dep"},
  1323. {dep_not_exist, "other_dep"}]}
  1324. ).
  1325. git_subdir_deps(Config) ->
  1326. Deps = rebar_test_utils:expand_deps(git_subdir, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1327. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1328. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1329. mock_git_subdir_resource:mock([{deps, SrcDeps}]),
  1330. RebarConfig = [
  1331. {deps, TopDeps}
  1332. ],
  1333. rebar_test_utils:run_and_check(
  1334. Config, RebarConfig, ["compile"],
  1335. {ok, [{subdir_dep, "some_dep"},
  1336. {subdir_dep, "other_dep"}]}
  1337. ).
  1338. override_add_deps(Config) ->
  1339. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1340. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1341. DepA = {dep_a, "0.0.1", {git, "http://site.com/dep_a.git", {tag, "0.0.1"}}},
  1342. DepB = {dep_b, "0.0.1", {git, "http://site.com/dep_b.git", {tag, "0.0.1"}}},
  1343. DepC = {dep_c, "0.0.1", {git, "http://site.com/dep_c.git", {tag, "0.0.1"}}},
  1344. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1345. mock_git_resource:mock([{deps, [DepA, DepB, DepC | SrcDeps]}]),
  1346. RebarConfig = [
  1347. {deps, TopDeps},
  1348. {overrides, [
  1349. {add, some_dep, [
  1350. {deps, [DepA, DepB]}
  1351. ]},
  1352. {add, [
  1353. {deps, [DepC]}
  1354. ]}
  1355. ]}
  1356. ],
  1357. rebar_test_utils:run_and_check(
  1358. Config, RebarConfig, ["compile"],
  1359. {ok, [{dep, "some_dep"},
  1360. {dep, "other_dep"},
  1361. {dep, "dep_a"},
  1362. {dep, "dep_b"},
  1363. {dep, "dep_c"}]}
  1364. ).
  1365. override_del_deps(Config) ->
  1366. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"dep_a", "0.0.1", []},
  1367. {"dep_b", "0.0.1", []},
  1368. {"dep_c", "0.0.1", []}]},
  1369. {"other_dep", "0.0.1", [{"dep_c", "0.0.1", []},
  1370. {"dep_d", "0.0.1", []}]}]),
  1371. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1372. DepA = {dep_a, "0.0.1", {git, "https://example.org/user/dep_a.git", {tag, "0.0.1"}}},
  1373. DepB = {dep_b, "0.0.1", {git, "https://example.org/user/dep_b.git", {tag, "0.0.1"}}},
  1374. DepC = {dep_c, "0.0.1", {git, "https://example.org/user/dep_c.git", {tag, "0.0.1"}}},
  1375. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1376. mock_git_resource:mock([{deps, SrcDeps}]),
  1377. RebarConfig = [
  1378. {deps, TopDeps},
  1379. {overrides, [
  1380. {del, some_dep, [
  1381. {deps, [DepA, DepB]}
  1382. ]},
  1383. {del, [
  1384. {deps, [DepC]}
  1385. ]}
  1386. ]}
  1387. ],
  1388. rebar_test_utils:run_and_check(
  1389. Config, RebarConfig, ["compile"],
  1390. {ok, [{dep, "some_dep"},
  1391. {dep, "other_dep"},
  1392. {dep_not_exist, "dep_a"},
  1393. {dep_not_exist, "dep_b"},
  1394. {dep_not_exist, "dep_c"},
  1395. {dep, "dep_d"}]}
  1396. ).
  1397. override_del_pkg_deps(Config) ->
  1398. Deps = rebar_test_utils:expand_deps(pkg, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1399. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1400. {_, PkgDeps} = rebar_test_utils:flat_deps(Deps),
  1401. mock_pkg_resource:mock([{pkgdeps, PkgDeps}]),
  1402. RebarConfig = [
  1403. {deps, TopDeps},
  1404. {overrides, [
  1405. {del, some_dep, [
  1406. {deps, [other_dep]},
  1407. %% regression: a non-existing option deletion
  1408. %% could trigger an infinite loop
  1409. {provider_hooks, [{post, [{compile, xref}]}]}
  1410. ]}
  1411. ]}
  1412. ],
  1413. rebar_test_utils:run_and_check(
  1414. Config, RebarConfig, ["compile"],
  1415. {ok, [{dep, "some_dep"},
  1416. {dep_not_exist, "other_dep"}]}
  1417. ).
  1418. override_opts(Config) ->
  1419. AppsDir = ?config(apps, Config),
  1420. Name = rebar_test_utils:create_random_name("app1_"),
  1421. Vsn = rebar_test_utils:create_random_vsn(),
  1422. AppDir = filename:join([AppsDir, "apps", Name]),
  1423. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1424. RebarConfig = [
  1425. {erl_opts, [
  1426. compressed,
  1427. warn_missing_spec
  1428. ]},
  1429. {overrides, [
  1430. {override, [
  1431. {erl_opts, [compressed]}
  1432. ]}
  1433. ]}
  1434. ],
  1435. rebar_test_utils:create_config(AppsDir, RebarConfig),
  1436. rebar_test_utils:run_and_check(
  1437. Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  1438. Path = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]),
  1439. code:add_patha(Path),
  1440. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1441. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1442. false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])).
  1443. %% test for fix of https://github.com/erlang/rebar3/issues/1801
  1444. %% only apply overrides once
  1445. %% verify by having an override add the macro TEST to the dep some_dep
  1446. %% building under `ct` will fail if the `add` is applied more than once
  1447. apply_overrides_exactly_once(Config) ->
  1448. AppDir = ?config(apps, Config),
  1449. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1450. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1451. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1452. mock_git_resource:mock([{deps, SrcDeps}]),
  1453. Name = rebar_test_utils:create_random_name("app1_"),
  1454. Vsn = rebar_test_utils:create_random_vsn(),
  1455. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1456. RebarConfig = [{deps, TopDeps},
  1457. {overrides, [
  1458. {add, some_dep, [
  1459. {erl_opts, [{d, 'TEST'}]}
  1460. ]}
  1461. ]}],
  1462. rebar_test_utils:create_config(AppDir, RebarConfig),
  1463. rebar_test_utils:run_and_check(
  1464. Config, RebarConfig, ["ct", "--compile_only"], {ok, [{app, Name}, {dep, "some_dep"}], "test"}).
  1465. override_only_deps(Config) ->
  1466. AppDir = ?config(apps, Config),
  1467. Name = rebar_test_utils:create_random_name("app1_"),
  1468. Vsn = rebar_test_utils:create_random_vsn(),
  1469. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1470. RebarConfig = [
  1471. {deps, []}, %% with deps enabled, this test fails
  1472. {overrides, [
  1473. {add, [
  1474. {erl_opts, [{d, bad, a}, {d, bad, b}]}
  1475. ]}
  1476. ]}
  1477. ],
  1478. rebar_test_utils:create_config(AppDir, RebarConfig),
  1479. rebar_test_utils:run_and_check(
  1480. Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  1481. ok.
  1482. override_add_opts(Config) ->
  1483. AppsDir = ?config(apps, Config),
  1484. Name = rebar_test_utils:create_random_name("app1_"),
  1485. Vsn = rebar_test_utils:create_random_vsn(),
  1486. AppDir = filename:join([AppsDir, "apps", Name]),
  1487. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1488. RebarConfig = [
  1489. {erl_opts, [
  1490. warn_missing_spec
  1491. ]},
  1492. {overrides, [
  1493. {add, [
  1494. {erl_opts, [compressed]}
  1495. ]}
  1496. ]}
  1497. ],
  1498. rebar_test_utils:create_config(AppsDir, RebarConfig),
  1499. rebar_test_utils:run_and_check(
  1500. Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  1501. Path = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]),
  1502. code:add_patha(Path),
  1503. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1504. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1505. true = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])).
  1506. override_del_opts(Config) ->
  1507. AppsDir = ?config(apps, Config),
  1508. Name = rebar_test_utils:create_random_name("app1_"),
  1509. Vsn = rebar_test_utils:create_random_vsn(),
  1510. AppDir = filename:join([AppsDir, "apps", Name]),
  1511. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1512. RebarConfig = [
  1513. {erl_opts, [
  1514. compressed,
  1515. warn_missing_spec
  1516. ]},
  1517. {overrides, [
  1518. {del, [
  1519. {erl_opts, [warn_missing_spec]}
  1520. ]}
  1521. ]}
  1522. ],
  1523. rebar_test_utils:create_config(AppsDir, RebarConfig),
  1524. rebar_test_utils:run_and_check(
  1525. Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  1526. Path = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]),
  1527. code:add_patha(Path),
  1528. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1529. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1530. false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])),
  1531. ok.
  1532. profile_override_deps(Config) ->
  1533. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1534. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1535. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1536. mock_git_resource:mock([{deps, SrcDeps}]),
  1537. RebarConfig = [
  1538. {deps, TopDeps},
  1539. {profiles, [
  1540. {a, [
  1541. {overrides, [
  1542. {override, some_dep, [
  1543. {deps, []}
  1544. ]}
  1545. ]}
  1546. ]}
  1547. ]}],
  1548. rebar_test_utils:run_and_check(
  1549. Config, RebarConfig, ["as", "a", "compile"],
  1550. {ok, [{dep, "some_dep"},
  1551. {dep_not_exist, "other_dep"}]}
  1552. ).
  1553. profile_override_add_deps(Config) ->
  1554. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1555. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1556. DepA = {dep_a, "0.0.1", {git, "http://site.com/dep_a.git", {tag, "0.0.1"}}},
  1557. DepB = {dep_b, "0.0.1", {git, "http://site.com/dep_b.git", {tag, "0.0.1"}}},
  1558. DepC = {dep_c, "0.0.1", {git, "http://site.com/dep_c.git", {tag, "0.0.1"}}},
  1559. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1560. mock_git_resource:mock([{deps, [DepA, DepB, DepC | SrcDeps]}]),
  1561. RebarConfig = [
  1562. {deps, TopDeps},
  1563. {profiles, [
  1564. {a, [
  1565. {overrides, [
  1566. {add, some_dep, [
  1567. {deps, [DepA, DepB]}
  1568. ]},
  1569. {add, [
  1570. {deps, [DepC]}
  1571. ]}
  1572. ]}
  1573. ]}
  1574. ]}
  1575. ],
  1576. rebar_test_utils:run_and_check(
  1577. Config, RebarConfig, ["as", "a", "compile"],
  1578. {ok, [{dep, "some_dep"},
  1579. {dep, "other_dep"},
  1580. {dep, "dep_a"},
  1581. {dep, "dep_b"},
  1582. {dep, "dep_c"}]}
  1583. ).
  1584. profile_override_del_deps(Config) ->
  1585. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"dep_a", "0.0.1", []},
  1586. {"dep_b", "0.0.1", []},
  1587. {"dep_c", "0.0.1", []}]},
  1588. {"other_dep", "0.0.1", [{"dep_c", "0.0.1", []},
  1589. {"dep_d", "0.0.1", []}]}]),
  1590. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1591. DepA = {dep_a, "0.0.1", {git, "https://example.org/user/dep_a.git", {tag, "0.0.1"}}},
  1592. DepB = {dep_b, "0.0.1", {git, "https://example.org/user/dep_b.git", {tag, "0.0.1"}}},
  1593. DepC = {dep_c, "0.0.1", {git, "https://example.org/user/dep_c.git", {tag, "0.0.1"}}},
  1594. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1595. mock_git_resource:mock([{deps, SrcDeps}]),
  1596. RebarConfig = [
  1597. {deps, TopDeps},
  1598. {profiles, [
  1599. {a, [
  1600. {overrides, [
  1601. {del, some_dep, [
  1602. {deps, [DepA, DepB]}
  1603. ]},
  1604. {del, [
  1605. {deps, [DepC]}
  1606. ]}
  1607. ]}
  1608. ]}
  1609. ]}
  1610. ],
  1611. rebar_test_utils:run_and_check(
  1612. Config, RebarConfig, ["as", "a", "compile"],
  1613. {ok, [{dep, "some_dep"},
  1614. {dep, "other_dep"},
  1615. {dep_not_exist, "dep_a"},
  1616. {dep_not_exist, "dep_b"},
  1617. {dep_not_exist, "dep_c"},
  1618. {dep, "dep_d"}]}
  1619. ).
  1620. profile_override_opts(Config) ->
  1621. AppsDir = ?config(apps, Config),
  1622. Name = rebar_test_utils:create_random_name("app1_"),
  1623. Vsn = rebar_test_utils:create_random_vsn(),
  1624. AppDir = filename:join([AppsDir, "apps", Name]),
  1625. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1626. RebarConfig = [
  1627. {erl_opts, [
  1628. compressed,
  1629. warn_missing_spec
  1630. ]},
  1631. {profiles, [
  1632. {a, [
  1633. {overrides, [
  1634. {override, [
  1635. {erl_opts, [compressed]}
  1636. ]}
  1637. ]}
  1638. ]}
  1639. ]}
  1640. ],
  1641. rebar_test_utils:create_config(AppsDir, RebarConfig),
  1642. rebar_test_utils:run_and_check(
  1643. Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}),
  1644. Path = filename:join([AppsDir, "_build", "a", "lib", Name, "ebin"]),
  1645. code:add_patha(Path),
  1646. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1647. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1648. false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])).
  1649. profile_override_add_opts(Config) ->
  1650. AppsDir = ?config(apps, Config),
  1651. Name = rebar_test_utils:create_random_name("app1_"),
  1652. Vsn = rebar_test_utils:create_random_vsn(),
  1653. AppDir = filename:join([AppsDir, "apps", Name]),
  1654. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1655. RebarConfig = [
  1656. {erl_opts, [
  1657. warn_missing_spec
  1658. ]},
  1659. {profiles, [
  1660. {a, [
  1661. {overrides, [
  1662. {add, [
  1663. {erl_opts, [compressed]}
  1664. ]}
  1665. ]}
  1666. ]}
  1667. ]}
  1668. ],
  1669. rebar_test_utils:create_config(AppsDir, RebarConfig),
  1670. rebar_test_utils:run_and_check(
  1671. Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}),
  1672. Path = filename:join([AppsDir, "_build", "a", "lib", Name, "ebin"]),
  1673. code:add_patha(Path),
  1674. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1675. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1676. true = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])).
  1677. profile_override_del_opts(Config) ->
  1678. AppsDir = ?config(apps, Config),
  1679. Name = rebar_test_utils:create_random_name("app1_"),
  1680. Vsn = rebar_test_utils:create_random_vsn(),
  1681. AppDir = filename:join([AppsDir, "apps", Name]),
  1682. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1683. RebarConfig = [
  1684. {erl_opts, [
  1685. compressed,
  1686. warn_missing_spec
  1687. ]},
  1688. {profiles, [
  1689. {a, [
  1690. {overrides, [
  1691. {del, [
  1692. {erl_opts, [warn_missing_spec]}
  1693. ]}
  1694. ]}
  1695. ]}
  1696. ]}
  1697. ],
  1698. rebar_test_utils:create_config(AppsDir, RebarConfig),
  1699. rebar_test_utils:run_and_check(
  1700. Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}),
  1701. Path = filename:join([AppsDir, "_build", "a", "lib", Name, "ebin"]),
  1702. code:add_patha(Path),
  1703. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1704. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1705. false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])),
  1706. ok.
  1707. profile_deps(Config) ->
  1708. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1709. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1710. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1711. mock_git_resource:mock([{deps, SrcDeps}]),
  1712. RebarConfig = [
  1713. {deps, TopDeps},
  1714. {profiles, [{a, []}]}],
  1715. rebar_test_utils:run_and_check(
  1716. Config, RebarConfig, ["as", "a", "compile"],
  1717. {ok, [{dep, "some_dep"},{dep, "other_dep"}]}
  1718. ).
  1719. only_deps(Config) ->
  1720. AppDir = ?config(apps, Config),
  1721. Name = rebar_test_utils:create_random_name("app1_"),
  1722. Vsn = rebar_test_utils:create_random_vsn(),
  1723. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1724. Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]),
  1725. TopDeps = rebar_test_utils:top_level_deps(Deps),
  1726. {SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
  1727. mock_git_resource:mock([{deps, SrcDeps}]),
  1728. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
  1729. {ok, RConf} = file:consult(RConfFile),
  1730. rebar_test_utils:run_and_check(
  1731. Config, RConf, ["compile", "--deps_only"],
  1732. {ok, [{app_not_exist, Name}, {dep, "some_dep"},{dep, "other_dep"}]}
  1733. ).
  1734. %% verify a deps prod profile is used
  1735. %% tested by checking prod hooks run and outputs to default profile dir for dep
  1736. %% and prod deps are installed for dep
  1737. deps_build_in_prod(Config) ->
  1738. AppDir = ?config(apps, Config),
  1739. Name = rebar_test_utils:create_random_name("app1_"),
  1740. Vsn = rebar_test_utils:create_random_vsn(),
  1741. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1742. GitDeps = rebar_test_utils:expand_deps(git, [{"asdf", "1.0.0", []}]),
  1743. PkgName = rebar_test_utils:create_random_name("pkg1_"),
  1744. {SrcDeps, _} = rebar_test_utils:flat_deps(GitDeps),
  1745. mock_git_resource:mock([{deps, SrcDeps},
  1746. {config, [{profiles, [{prod, [{pre_hooks, [{compile, "echo whatsup > randomfile"}]},
  1747. {deps, [list_to_atom(PkgName)]}]}]}]}]),
  1748. mock_pkg_resource:mock([{pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}]}]),
  1749. Deps = rebar_test_utils:top_level_deps(GitDeps),
  1750. RConfFile = rebar_test_utils:create_config(AppDir, [{deps, Deps}]),
  1751. {ok, RConf} = file:consult(RConfFile),
  1752. %% Build with deps.
  1753. rebar_test_utils:run_and_check(
  1754. Config, RConf, ["compile"],
  1755. {ok, [{app, Name}, {dep, "asdf", <<"1.0.0">>}, {dep, PkgName},
  1756. {file, filename:join([AppDir, "_build", "default", "lib", "asdf", "randomfile"])}]}
  1757. ).
  1758. %% verify that the proper include path is defined
  1759. %% according the erlang doc which states:
  1760. %% If the filename File is absolute (possibly after variable substitution),
  1761. %% the include file with that name is included. Otherwise, the specified file
  1762. %% is searched for in the following directories, and in this order:
  1763. %% * The current working directory
  1764. %% * The directory where the module is being compiled
  1765. %% * The directories given by the include option
  1766. include_file_relative_to_working_directory(Config) ->
  1767. AppDir = ?config(apps, Config),
  1768. Name = rebar_test_utils:create_random_name("app1_"),
  1769. Vsn = rebar_test_utils:create_random_vsn(),
  1770. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1771. Src = <<"-module(test).\n"
  1772. "\n"
  1773. "-include(\"include/test.hrl\").\n"
  1774. "\n"
  1775. "test() -> ?TEST_MACRO.\n"
  1776. "\n">>,
  1777. Include = <<"-define(TEST_MACRO, test).\n">>,
  1778. ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
  1779. ok = file:write_file(filename:join([AppDir, "src", "test.erl"]), Src),
  1780. ok = filelib:ensure_dir(filename:join([AppDir, "include", "dummy"])),
  1781. ok = file:write_file(filename:join([AppDir, "include", "test.hrl"]), Include),
  1782. RebarConfig = [],
  1783. rebar_test_utils:run_and_check(Config, RebarConfig,
  1784. ["compile"],
  1785. {ok, [{app, Name}]}).
  1786. include_file_in_src(Config) ->
  1787. AppDir = ?config(apps, Config),
  1788. Name = rebar_test_utils:create_random_name("app1_"),
  1789. Vsn = rebar_test_utils:create_random_vsn(),
  1790. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1791. Src = <<"-module(test).\n"
  1792. "\n"
  1793. "-include(\"test.hrl\").\n"
  1794. "\n"
  1795. "test() -> ?TEST_MACRO.\n"
  1796. "\n">>,
  1797. Include = <<"-define(TEST_MACRO, test).\n">>,
  1798. ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
  1799. ok = file:write_file(filename:join([AppDir, "src", "test.erl"]), Src),
  1800. ok = file:write_file(filename:join([AppDir, "src", "test.hrl"]), Include),
  1801. RebarConfig = [],
  1802. rebar_test_utils:run_and_check(Config, RebarConfig,
  1803. ["compile"],
  1804. {ok, [{app, Name}]}).
  1805. %% verify that the proper include path is defined
  1806. %% according the erlang doc which states:
  1807. %% If the filename File is absolute (possibly after variable substitution),
  1808. %% the include file with that name is included. Otherwise, the specified file
  1809. %% is searched for in the following directories, and in this order:
  1810. %% * The current working directory
  1811. %% * The directory where the module is being compiled
  1812. %% * The directories given by the include option
  1813. %%
  1814. %% This test ensures that things keep working when additional directories
  1815. %% are used for apps, such as the test/ directory within the test profile.
  1816. include_file_relative_to_working_directory_test(Config) ->
  1817. AppDir = ?config(apps, Config),
  1818. Name = rebar_test_utils:create_random_name("app1_"),
  1819. Vsn = rebar_test_utils:create_random_vsn(),
  1820. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1821. Src = <<"-module(test).\n"
  1822. "\n"
  1823. "-include(\"include/test.hrl\").\n"
  1824. "\n"
  1825. "test() -> ?TEST_MACRO.\n"
  1826. "\n">>,
  1827. Include = <<"-define(TEST_MACRO, test).\n">>,
  1828. ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
  1829. ok = filelib:ensure_dir(filename:join([AppDir, "test", "dummy"])),
  1830. ok = file:write_file(filename:join([AppDir, "test", "test.erl"]), Src),
  1831. ok = filelib:ensure_dir(filename:join([AppDir, "include", "dummy"])),
  1832. ok = file:write_file(filename:join([AppDir, "include", "test.hrl"]), Include),
  1833. RebarConfig = [],
  1834. rebar_test_utils:run_and_check(Config, RebarConfig,
  1835. ["as", "test", "compile"],
  1836. {ok, [{app, Name}]}).
  1837. %% Same as `include_file_in_src/1' but using the `test/' directory
  1838. %% within the test profile.
  1839. include_file_in_src_test(Config) ->
  1840. AppDir = ?config(apps, Config),
  1841. Name = rebar_test_utils:create_random_name("app1_"),
  1842. Vsn = rebar_test_utils:create_random_vsn(),
  1843. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1844. Src = <<"-module(test).\n"
  1845. "\n"
  1846. "-include(\"test.hrl\").\n"
  1847. "\n"
  1848. "test() -> ?TEST_MACRO.\n"
  1849. "\n">>,
  1850. Include = <<"-define(TEST_MACRO, test).\n">>,
  1851. ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
  1852. ok = filelib:ensure_dir(filename:join([AppDir, "test", "dummy"])),
  1853. ok = file:write_file(filename:join([AppDir, "test", "test.erl"]), Src),
  1854. ok = file:write_file(filename:join([AppDir, "src", "test.hrl"]), Include),
  1855. RebarConfig = [],
  1856. rebar_test_utils:run_and_check(Config, RebarConfig,
  1857. ["as", "test", "compile"],
  1858. {ok, [{app, Name}]}).
  1859. %% Same as `include_file_in_src_test/1' but using multiple top-level
  1860. %% apps as dependencies.
  1861. include_file_in_src_test_multiapp(Config) ->
  1862. Name1 = rebar_test_utils:create_random_name("app2_"),
  1863. Name2 = rebar_test_utils:create_random_name("app1_"),
  1864. AppDir1 = filename:join([?config(apps, Config), "lib", Name1]),
  1865. AppDir2 = filename:join([?config(apps, Config), "lib", Name2]),
  1866. Vsn = rebar_test_utils:create_random_vsn(),
  1867. rebar_test_utils:create_app(AppDir1, Name1, Vsn, [kernel, stdlib, list_to_atom(Name2)]),
  1868. rebar_test_utils:create_app(AppDir2, Name2, Vsn, [kernel, stdlib]),
  1869. Src = "-module(test).\n"
  1870. "\n"
  1871. "-include_lib(\"" ++ Name2 ++ "/include/test.hrl\").\n"
  1872. "\n"
  1873. "test() -> ?TEST_MACRO.\n"
  1874. "\n",
  1875. Include = <<"-define(TEST_MACRO, test).\n">>,
  1876. ok = filelib:ensure_dir(filename:join([AppDir1, "src", "dummy"])),
  1877. ok = filelib:ensure_dir(filename:join([AppDir1, "test", "dummy"])),
  1878. ok = filelib:ensure_dir(filename:join([AppDir2, "src", "dummy"])),
  1879. ok = filelib:ensure_dir(filename:join([AppDir2, "include", "dummy"])),
  1880. ok = file:write_file(filename:join([AppDir1, "test", "test.erl"]), Src),
  1881. ok = file:write_file(filename:join([AppDir2, "include", "test.hrl"]), Include),
  1882. RebarConfig = [],
  1883. rebar_test_utils:run_and_check(Config, RebarConfig,
  1884. ["as", "test", "compile"],
  1885. {ok, [{app, Name1}]}),
  1886. ok.
  1887. %% this test sets the env var, compiles, records the file last modified timestamp,
  1888. %% recompiles and compares the file last modified timestamp to ensure it hasn't
  1889. %% changed. this test should run on 19.x+
  1890. dont_recompile_when_erl_compiler_options_env_does_not_change(Config) ->
  1891. %% save existing env to restore after test
  1892. ExistingEnv = os:getenv("ERL_COMPILER_OPTIONS"),
  1893. AppDir = ?config(apps, Config),
  1894. Name = rebar_test_utils:create_random_name("erl_compiler_options_"),
  1895. Vsn = rebar_test_utils:create_random_vsn(),
  1896. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1897. true = os:unsetenv("ERL_COMPILER_OPTIONS"),
  1898. true = os:putenv("ERL_COMPILER_OPTIONS", "[{d, some_macro}]"),
  1899. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  1900. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  1901. {ok, Files} = rebar_utils:list_dir(EbinDir),
  1902. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  1903. || F <- Files, filename:extension(F) == ".beam"],
  1904. timer:sleep(1000),
  1905. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  1906. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  1907. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  1908. || F <- NewFiles, filename:extension(F) == ".beam"],
  1909. ?assert(ModTime == NewModTime),
  1910. %% restore existing env
  1911. case ExistingEnv of
  1912. false -> ok;
  1913. _ -> os:putenv("ERL_COMPILER_OPTIONS", ExistingEnv)
  1914. end.
  1915. %% this test compiles, records the file last modified timestamp, sets the env
  1916. %% var, recompiles and compares the file last modified timestamp to ensure it
  1917. %% has changed. this test should run on 19.x+
  1918. recompile_when_erl_compiler_options_env_changes(Config) ->
  1919. %% save existing env to restore after test
  1920. ExistingEnv = os:getenv("ERL_COMPILER_OPTIONS"),
  1921. AppDir = ?config(apps, Config),
  1922. Name = rebar_test_utils:create_random_name("erl_compiler_options_"),
  1923. Vsn = rebar_test_utils:create_random_vsn(),
  1924. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1925. true = os:unsetenv("ERL_COMPILER_OPTIONS"),
  1926. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  1927. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  1928. {ok, Files} = rebar_utils:list_dir(EbinDir),
  1929. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  1930. || F <- Files, filename:extension(F) == ".beam"],
  1931. timer:sleep(1000),
  1932. true = os:putenv("ERL_COMPILER_OPTIONS", "[{d, some_macro}]"),
  1933. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  1934. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  1935. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  1936. || F <- NewFiles, filename:extension(F) == ".beam"],
  1937. ?assert(ModTime =/= NewModTime),
  1938. %% restore existing env
  1939. case ExistingEnv of
  1940. false -> ok;
  1941. _ -> os:putenv("ERL_COMPILER_OPTIONS", ExistingEnv)
  1942. end.
  1943. rebar_config_os_var(Config) ->
  1944. AppDir = ?config(apps, Config),
  1945. Name = rebar_test_utils:create_random_name("rebar_config_os_var_"),
  1946. Vsn = rebar_test_utils:create_random_vsn(),
  1947. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1948. rebar_test_utils:create_config(AppDir, [{erl_opts, []}]),
  1949. AltConfig = filename:join(AppDir, "test.rebar.config"),
  1950. file:write_file(AltConfig, "{erl_opts, [compressed]}."),
  1951. true = os:putenv("REBAR_CONFIG", AltConfig),
  1952. rebar_test_utils:run_and_check(Config, ["compile"], {ok, [{app, Name}]}),
  1953. Path = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  1954. code:add_patha(Path),
  1955. Mod = list_to_atom("not_a_real_src_" ++ Name),
  1956. true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])),
  1957. ok.
  1958. %% this test sets the env var, compiles, records the file last modified
  1959. %% timestamp, recompiles and compares the file last modified timestamp to
  1960. %% ensure it has changed. this test should run on 18.x
  1961. always_recompile_when_erl_compiler_options_set(Config) ->
  1962. %% save existing env to restore after test
  1963. ExistingEnv = os:getenv("ERL_COMPILER_OPTIONS"),
  1964. AppDir = ?config(apps, Config),
  1965. Name = rebar_test_utils:create_random_name("erl_compiler_options_"),
  1966. Vsn = rebar_test_utils:create_random_vsn(),
  1967. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1968. true = os:unsetenv("ERL_COMPILER_OPTIONS"),
  1969. true = os:putenv("ERL_COMPILER_OPTIONS", "[{d, some_macro}]"),
  1970. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  1971. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  1972. {ok, Files} = rebar_utils:list_dir(EbinDir),
  1973. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  1974. || F <- Files, filename:extension(F) == ".beam"],
  1975. timer:sleep(1000),
  1976. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  1977. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  1978. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  1979. || F <- NewFiles, filename:extension(F) == ".beam"],
  1980. ?assert(ModTime =/= NewModTime),
  1981. %% restore existing env
  1982. case ExistingEnv of
  1983. false -> ok;
  1984. _ -> os:putenv("ERL_COMPILER_OPTIONS", ExistingEnv)
  1985. end.
  1986. recompile_when_parse_transform_inline_changes(Config) ->
  1987. AppDir = ?config(apps, Config),
  1988. Name = rebar_test_utils:create_random_name("parse_transform_inline_"),
  1989. Vsn = rebar_test_utils:create_random_vsn(),
  1990. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  1991. ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
  1992. ModSrc = <<"-module(example).\n"
  1993. "-export([foo/2]).\n"
  1994. "-compile([{parse_transform, example_parse_transform}]).\n"
  1995. "foo(_, _) -> ok.">>,
  1996. ok = file:write_file(filename:join([AppDir, "src", "example.erl"]),
  1997. ModSrc),
  1998. ParseTransform = <<"-module(example_parse_transform).\n"
  1999. "-export([parse_transform/2]).\n"
  2000. "parse_transform(AST, _) -> AST.\n">>,
  2001. ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]),
  2002. ParseTransform),
  2003. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  2004. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  2005. {ok, Files} = rebar_utils:list_dir(EbinDir),
  2006. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  2007. || F <- Files, filename:basename(F, ".beam") == "example"],
  2008. timer:sleep(1000),
  2009. NewParseTransform = <<"-module(example_parse_transform).\n"
  2010. "-export([parse_transform/2]).\n"
  2011. "parse_transform(AST, _) -> identity(AST).\n"
  2012. "identity(AST) -> AST.\n">>,
  2013. ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]),
  2014. NewParseTransform),
  2015. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  2016. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  2017. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  2018. || F <- NewFiles, filename:basename(F, ".beam") == "example"],
  2019. ?assert(ModTime =/= NewModTime).
  2020. recompile_when_parse_transform_as_opt_changes(Config) ->
  2021. AppDir = ?config(apps, Config),
  2022. Name = rebar_test_utils:create_random_name("parse_transform_opt_"),
  2023. Vsn = rebar_test_utils:create_random_vsn(),
  2024. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  2025. ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
  2026. ModSrc = <<"-module(example).\n"
  2027. "-export([foo/2]).\n"
  2028. "foo(_, _) -> ok.">>,
  2029. ok = file:write_file(filename:join([AppDir, "src", "example.erl"]),
  2030. ModSrc),
  2031. ParseTransform = <<"-module(example_parse_transform).\n"
  2032. "-export([parse_transform/2]).\n"
  2033. "parse_transform(AST, _) -> AST.">>,
  2034. ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]),
  2035. ParseTransform),
  2036. RebarConfig = [{erl_opts, [{parse_transform, example_parse_transform}]}],
  2037. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  2038. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  2039. {ok, Files} = rebar_utils:list_dir(EbinDir),
  2040. ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  2041. || F <- Files, filename:basename(F, ".beam") == "example"],
  2042. timer:sleep(1000),
  2043. NewParseTransform = <<"-module(example_parse_transform).\n"
  2044. "-export([parse_transform/2]).\n"
  2045. "parse_transform(AST, _) -> identity(AST).\n"
  2046. "identity(AST) -> AST.">>,
  2047. ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]),
  2048. NewParseTransform),
  2049. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
  2050. {ok, NewFiles} = rebar_utils:list_dir(EbinDir),
  2051. NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
  2052. || F <- NewFiles, filename:basename(F, ".beam") == "example"],
  2053. ?assert(ModTime =/= NewModTime).
  2054. recursive(Config) ->
  2055. AppDir = ?config(apps, Config),
  2056. Name = rebar_test_utils:create_random_name("app1_"),
  2057. Vsn = rebar_test_utils:create_random_vsn(),
  2058. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  2059. rebar_test_utils:write_src_file(filename:join(AppDir,src),"rec.erl"),
  2060. rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
  2061. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  2062. {ok, Files} = rebar_utils:list_dir(EbinDir),
  2063. ?assert(lists:member("rec.beam",Files)),
  2064. %% check that rec is in modules list of .app file
  2065. AppFile = filename:join(EbinDir, Name++".app"),
  2066. {ok, [{application, _, List}]} = file:consult(AppFile),
  2067. {modules, Modules} = lists:keyfind(modules, 1, List),
  2068. ?assert(lists:member(rec, Modules)).
  2069. no_recursive(Config) ->
  2070. AppDir = ?config(apps, Config),
  2071. Name = rebar_test_utils:create_random_name("app1_"),
  2072. Vsn = rebar_test_utils:create_random_vsn(),
  2073. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  2074. rebar_test_utils:write_src_file(filename:join(AppDir,src),"rec.erl"),
  2075. RebarConfig1 = [{erlc_compiler,[{recursive,false}]}],
  2076. rebar_test_utils:run_and_check(Config, RebarConfig1, ["compile"],
  2077. {ok, [{app, Name}]}),
  2078. EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
  2079. {ok, Files1} = rebar_utils:list_dir(EbinDir),
  2080. ?assert(false==lists:member("rec.beam",Files1)),
  2081. RebarConfig2 = [{src_dirs,[{"src",[{recursive,false}]}]}],
  2082. rebar_test_utils:run_and_check(Config, RebarConfig2, ["compile"],
  2083. {ok, [{app, Name}]}),
  2084. {ok, Files2} = rebar_utils:list_dir(EbinDir),
  2085. ?assert(false==lists:member("rec.beam",Files2)),
  2086. ok.
  2087. extra_recursion(Config) ->
  2088. AppDir = ?config(apps, Config),
  2089. Name = rebar_test_utils:create_random_name("app1_"),
  2090. Vsn = rebar_test_utils:create_random_vsn(),
  2091. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  2092. rebar_test_utils:write_src_file(filename:join([AppDir, "src", "src2"]), "rec.erl"),
  2093. rebar_test_utils:write_src_file(filename:join([AppDir, "test", "test2"]), "rectest.erl"),
  2094. %% Default for src directories: recursive
  2095. %% default for extra_src directories: non-recursive
  2096. RebarConfig1 = [],
  2097. rebar_test_utils:run_and_check(Config, RebarConfig1, ["as", "test", "compile"],
  2098. {ok, [{app, Name}]}),
  2099. EbinDir = filename:join([AppDir, "_build", "test", "lib", Name, "ebin"]),
  2100. {ok, Files1} = rebar_utils:list_dir(EbinDir),
  2101. ?assert(lists:member("rec.beam", Files1)),
  2102. file:delete(filename:join(EbinDir, "rec.beam")),
  2103. TestEbinDir = filename:join([AppDir, "_build", "test", "lib", Name, "test"]),
  2104. {ok, TestFiles1} = rebar_utils:list_dir(TestEbinDir),
  2105. ?assertNot(lists:member("rectest.beam", TestFiles1)),
  2106. RebarConfig2 = [{src_dirs,[{"src",[{recursive,false}]}]},
  2107. {extra_src_dirs, [{"test", [{recursive, true}]}]}],
  2108. rebar_test_utils:run_and_check(Config, RebarConfig2, ["as", "test", "compile"],
  2109. {ok, [{app, Name}]}),
  2110. {ok, Files2} = rebar_utils:list_dir(EbinDir),
  2111. ?assertNot(lists:member("rec.beam",Files2)),
  2112. {ok, TestFiles2} = rebar_utils:list_dir(TestEbinDir),
  2113. ?assert(lists:member("rectest.beam", TestFiles2)),
  2114. ok.
  2115. regex_filter_skip(Config) ->
  2116. AppDir = ?config(apps, Config),
  2117. Name = rebar_test_utils:create_random_name("regex_skip"),
  2118. Vsn = rebar_test_utils:create_random_vsn(),
  2119. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  2120. rebar_test_utils:write_src_file(filename:join(AppDir,src),"._rec.erl"),
  2121. Expected = filename:join([AppDir, "_build", "default", "lib", Name, "ebin","._rec.beam"]),
  2122. RebarConfig = [],
  2123. try
  2124. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"],
  2125. {ok, [{file, Expected}]}),
  2126. throw(should_not_be_found)
  2127. catch
  2128. %% the file was not found, as desired!
  2129. error:{assertion_failed,_} -> %% OTP =< 17
  2130. ok;
  2131. error:{assert,_} -> %% OTP >= 18
  2132. ok
  2133. end.
  2134. regex_filter_regression(Config) ->
  2135. AppDir = ?config(apps, Config),
  2136. Name = rebar_test_utils:create_random_name("regex_regression"),
  2137. Vsn = rebar_test_utils:create_random_vsn(),
  2138. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  2139. rebar_test_utils:write_src_file(filename:join(AppDir,src),"r_f.erl"),
  2140. Expected = filename:join([AppDir, "_build", "default", "lib", Name, "ebin","r_f.beam"]),
  2141. RebarConfig = [],
  2142. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"],
  2143. {ok, [{file, Expected}]}),
  2144. ok.
  2145. %% This test could also have existed in rebar_hooks_SUITE but it's more
  2146. %% about compiler implementation details than the hook logic itself,
  2147. %% so it was located here.
  2148. split_project_apps_hooks() ->
  2149. [{doc, "Ensure that a project with multiple project apps runs the "
  2150. "pre-hooks before all the apps are compiled, and the post "
  2151. "hooks after they are all compiled."}].
  2152. split_project_apps_hooks(Config) ->
  2153. BaseDir = ?config(apps, Config),
  2154. Name1 = rebar_test_utils:create_random_name("app2_"),
  2155. Name2 = rebar_test_utils:create_random_name("app1_"),
  2156. AppDir1 = filename:join([BaseDir, "lib", Name1]),
  2157. AppDir2 = filename:join([BaseDir, "lib", Name2]),
  2158. HookDir = filename:join([BaseDir, "hooks"]),
  2159. Vsn = rebar_test_utils:create_random_vsn(),
  2160. rebar_test_utils:create_app(AppDir1, Name1, Vsn, [kernel, stdlib, list_to_atom(Name2)]),
  2161. rebar_test_utils:create_app(AppDir2, Name2, Vsn, [kernel, stdlib]),
  2162. ok = filelib:ensure_dir(filename:join([AppDir1, "src", "dummy"])),
  2163. ok = filelib:ensure_dir(filename:join([AppDir1, "test", "dummy"])),
  2164. ok = filelib:ensure_dir(filename:join([AppDir2, "src", "dummy"])),
  2165. ok = filelib:ensure_dir(filename:join([AppDir2, "include", "dummy"])),
  2166. ok = filelib:ensure_dir(filename:join([HookDir, "dummy"])),
  2167. Cmd = case os:type() of
  2168. {win32, _} -> "dir /B";
  2169. _ -> "ls"
  2170. end,
  2171. Cfg = fun(Name) ->
  2172. [{pre_hooks, [{compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "pre-compile-"++Name)++"\""},
  2173. {erlc_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "pre-erlc-"++Name)++"\""},
  2174. {app_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "pre-app-"++Name)++"\""}]},
  2175. {post_hooks, [{compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "post-compile-"++Name)++"\""},
  2176. {erlc_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "post-erlc-"++Name)++"\""},
  2177. {app_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "post-app-"++Name)++"\""}]}
  2178. ]
  2179. end,
  2180. ok = file:write_file(filename:join(AppDir1, "rebar.config"),
  2181. io_lib:format("~p.~n~p.", Cfg("app1"))),
  2182. ok = file:write_file(filename:join(AppDir2, "rebar.config"),
  2183. io_lib:format("~p.~n~p.", Cfg("app2"))),
  2184. RebarConfig = Cfg("all"),
  2185. rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"],
  2186. {ok, [{app, Name1}, {app, Name2}]}),
  2187. %% Now for the big party:
  2188. %% - we expect whole pre-hooks to run before either app is compiled
  2189. %% - we don't expect app and erlc hooks on the total run
  2190. %% - we expect app2 to be compiled before app1 (rev alphabetical order)
  2191. %% - we expect all pre-hooks to show up before post-hooks
  2192. %% - the pre-order is: compile->erlc, taking place before any app
  2193. %% is actually compiled, so that analysis can be done on all apps.
  2194. %% - the post-order is more as expected:
  2195. %% - erlc post hook runs right with the app
  2196. %% - app pre hook runs right with the app
  2197. %% - app post hook runs right with the app
  2198. %% - compile post hook runs for each app individually
  2199. %% - we expect app compile post-hooks to show up in order
  2200. %% - we expect whole post-hooks to run last
  2201. CallOrder = [
  2202. "pre-compile-all",
  2203. "pre-compile-app2",
  2204. "pre-compile-app1",
  2205. "pre-erlc-app2",
  2206. "pre-erlc-app1",
  2207. "post-erlc-app2",
  2208. "post-erlc-app1",
  2209. "pre-app-app2",
  2210. "pre-app-app1",
  2211. "post-app-app2",
  2212. "post-app-app1",
  2213. "post-compile-app2",
  2214. "post-compile-app1",
  2215. "post-compile-all"
  2216. ],
  2217. validate_call_order(CallOrder, HookDir),
  2218. ok.
  2219. validate_call_order(Calls, Dir) -> validate_call_order(Calls, Dir, []).
  2220. validate_call_order([], _, _) ->
  2221. ok;
  2222. validate_call_order([Name|T], Dir, Seen) ->
  2223. {ok, Bin} = file:read_file(filename:join(Dir, Name)),
  2224. %% weird list of tokens, but works on lexemes/tokens for backwards compat
  2225. Found = rebar_string:lexemes(binary_to_list(Bin), [$\n, $\r, "\r\n"]),
  2226. NewSeen = [Name|Seen],
  2227. ?assertEqual({Name, Found}, {Name, lists:sort(NewSeen)}),
  2228. validate_call_order(T, Dir, NewSeen).
  2229. app_file_linting(Config) ->
  2230. meck:new(rebar_log, [no_link, passthrough]),
  2231. AppDir = ?config(apps, Config),
  2232. Name = rebar_test_utils:create_random_name("app_file_linting"),
  2233. Vsn = rebar_test_utils:create_random_vsn(),
  2234. rebar_test_utils:create_app(AppDir, Name, Vsn, [foo]),
  2235. _ = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
  2236. History = meck:history(rebar_log),
  2237. Warnings = [{Str, Args} || {_, {rebar_log, log, [warn, Str, Args]}, _} <- History],
  2238. ?assert(none /= proplists:lookup("~p is missing description entry", Warnings)),
  2239. ?assert(none /= proplists:lookup("~p is missing kernel from applications list", Warnings)),
  2240. ?assert(none /= proplists:lookup("~p is missing stdlib from applications list", Warnings)).
  2241. %%
  2242. %% a copy of lib/parsetools/include/yeccpre.hrl so we can test yrl includefile
  2243. yeccpre_hrl() ->
  2244. <<"-type yecc_ret() :: {'error', _} | {'ok', _}.
  2245. -spec parse(Tokens :: list()) -> yecc_ret().
  2246. parse(Tokens) ->
  2247. yeccpars0(Tokens, {no_func, no_line}, 0, [], []).
  2248. -spec parse_and_scan({function() | {atom(), atom()}, [_]}
  2249. | {atom(), atom(), [_]}) -> yecc_ret().
  2250. parse_and_scan({F, A}) ->
  2251. yeccpars0([], {{F, A}, no_line}, 0, [], []);
  2252. parse_and_scan({M, F, A}) ->
  2253. Arity = length(A),
  2254. yeccpars0([], {{fun M:F/Arity, A}, no_line}, 0, [], []).
  2255. -spec format_error(any()) -> [char() | list()].
  2256. format_error(Message) ->
  2257. case io_lib:deep_char_list(Message) of
  2258. true ->
  2259. Message;
  2260. _ ->
  2261. io_lib:write(Message)
  2262. end.
  2263. %% To be used in grammar files to throw an error message to the parser
  2264. %% toplevel. Doesn't have to be exported!
  2265. -compile({nowarn_unused_function, return_error/2}).
  2266. -spec return_error(integer(), any()) -> no_return().
  2267. return_error(Line, Message) ->
  2268. throw({error, {Line, ?MODULE, Message}}).
  2269. -define(CODE_VERSION, \"1.4\").
  2270. yeccpars0(Tokens, Tzr, State, States, Vstack) ->
  2271. try yeccpars1(Tokens, Tzr, State, States, Vstack)
  2272. catch
  2273. error:Error ->
  2274. try yecc_error_type(Error, []) of
  2275. Desc ->
  2276. erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
  2277. [])
  2278. catch _:_ -> erlang:raise(error, Error, [])
  2279. end;
  2280. %% Probably thrown from return_error/2:
  2281. throw: {error, {_Line, ?MODULE, _M}} = Error ->
  2282. Error
  2283. end.
  2284. yecc_error_type(function_clause, _) ->
  2285. not_implemented.
  2286. yeccpars1([Token | Tokens], Tzr, State, States, Vstack) ->
  2287. yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr);
  2288. yeccpars1([], {{F, A},_Line}, State, States, Vstack) ->
  2289. case apply(F, A) of
  2290. {ok, Tokens, Endline} ->
  2291. yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack);
  2292. {eof, Endline} ->
  2293. yeccpars1([], {no_func, Endline}, State, States, Vstack);
  2294. {error, Descriptor, _Endline} ->
  2295. {error, Descriptor}
  2296. end;
  2297. yeccpars1([], {no_func, no_line}, State, States, Vstack) ->
  2298. Line = 999999,
  2299. yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [],
  2300. {no_func, Line});
  2301. yeccpars1([], {no_func, Endline}, State, States, Vstack) ->
  2302. yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [],
  2303. {no_func, Endline}).
  2304. %% yeccpars1/7 is called from generated code.
  2305. %%
  2306. %% When using the {includefile, Includefile} option, make sure that
  2307. %% yeccpars1/7 can be found by parsing the file without following
  2308. %% include directives. yecc will otherwise assume that an old
  2309. %% yeccpre.hrl is included (one which defines yeccpars1/5).
  2310. yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) ->
  2311. yeccpars2(State, element(1, Token), [State1 | States],
  2312. [Token0 | Vstack], Token, Tokens, Tzr);
  2313. yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) ->
  2314. yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]);
  2315. yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) ->
  2316. Line = yecctoken_end_location(Token0),
  2317. yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
  2318. yecc_end(Line), [], {no_func, Line});
  2319. yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) ->
  2320. yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack],
  2321. yecc_end(Line), [], {no_func, Line}).
  2322. %% For internal use only.
  2323. yecc_end({Line,_Column}) ->
  2324. {'$end', Line};
  2325. yecc_end(Line) ->
  2326. {'$end', Line}.
  2327. yecctoken_end_location(Token) ->
  2328. try erl_anno:end_location(element(2, Token)) of
  2329. undefined -> yecctoken_location(Token);
  2330. Loc -> Loc
  2331. catch _:_ -> yecctoken_location(Token)
  2332. end.
  2333. -compile({nowarn_unused_function, yeccerror/1}).
  2334. yeccerror(Token) ->
  2335. Text = yecctoken_to_string(Token),
  2336. Location = yecctoken_location(Token),
  2337. {error, {Location, ?MODULE, [\"syntax error before: \", Text]}}.
  2338. -compile({nowarn_unused_function, yecctoken_to_string/1}).
  2339. yecctoken_to_string(Token) ->
  2340. try erl_scan:text(Token) of
  2341. undefined -> yecctoken2string(Token);
  2342. Txt -> Txt
  2343. catch _:_ -> yecctoken2string(Token)
  2344. end.
  2345. yecctoken_location(Token) ->
  2346. try erl_scan:location(Token)
  2347. catch _:_ -> element(2, Token)
  2348. end.
  2349. -compile({nowarn_unused_function, yecctoken2string/1}).
  2350. yecctoken2string({atom, _, A}) -> io_lib:write_atom(A);
  2351. yecctoken2string({integer,_,N}) -> io_lib:write(N);
  2352. yecctoken2string({float,_,F}) -> io_lib:write(F);
  2353. yecctoken2string({char,_,C}) -> io_lib:write_char(C);
  2354. yecctoken2string({var,_,V}) -> io_lib:format(\"~s\", [V]);
  2355. yecctoken2string({string,_,S}) -> io_lib:write_string(S);
  2356. yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
  2357. yecctoken2string({_Cat, _, Val}) -> io_lib:format(\"~p\", [Val]);
  2358. yecctoken2string({dot, _}) -> \"'.'\";
  2359. yecctoken2string({'$end', _}) -> [];
  2360. yecctoken2string({Other, _}) when is_atom(Other) ->
  2361. io_lib:write_atom(Other);
  2362. yecctoken2string(Other) ->
  2363. io_lib:format(\"~p\", [Other]).
  2364. ">>.