rebar3-3.18.0/0000755000232200023220000000000014164317745013343 5ustar debalancedebalancerebar3-3.18.0/priv/0000755000232200023220000000000014164317745014323 5ustar debalancedebalancerebar3-3.18.0/priv/shell-completion/0000755000232200023220000000000014164317745017601 5ustar debalancedebalancerebar3-3.18.0/priv/shell-completion/fish/0000755000232200023220000000000014164317745020532 5ustar debalancedebalancerebar3-3.18.0/priv/shell-completion/fish/rebar3.fish0000644000232200023220000003751714164317745022600 0ustar debalancedebalance## copy this to ~/.config/fish/completions function __fish_rebar3_needs_command set cmd (commandline -opc) if [ (count $cmd) -eq 1 -a $cmd[1] = 'rebar3' -o $cmd[1] = './rebar3' ] return 0 end return 1 end function __fish_rebar3_using_command set cmd (commandline -opc) if [ (count $cmd) -gt 1 ] if [ $argv[1] = $cmd[2] ] return 0 end end return 1 end ## ➜ ~ rebar3 --help ## Rebar3 is a tool for working with Erlang projects. ## ## ## Usage: rebar [-h] [-v] [] ## ## -h, --help Print this help. ## -v, --version Show version information. ## Task to run. ## ## ## Several tasks are available: ## ## as Higher order provider for running multiple tasks in a sequence as a certain profiles. ## clean Remove compiled beam files from apps. ## compile Compile apps .app.src and .erl files. ## cover Perform coverage analysis. ## ct Run Common Tests. ## deps List dependencies ## dialyzer Run the Dialyzer analyzer on the project. ## do Higher order provider for running multiple tasks in a sequence. ## edoc Generate documentation using edoc. ## escriptize Generate escript archive. ## eunit Run EUnit Tests. ## help Display a list of tasks or help for a given task or subtask. ## new Create new project from templates. ## path Print paths to build dirs in current profile. ## pkgs Get information on a given package. ## release Build release of project. ## relup Create relup of releases. ## report Provide a crash report to be sent to the rebar3 issues page. ## shell Run shell with project apps and deps in path. ## tar Tar archive of release built of project. ## tree Print dependency tree. ## unlock Unlock dependencies. ## unstable Namespace providing commands that are still in flux. ## update Update package index. ## upgrade Upgrade dependencies. ## version Print version for rebar and current Erlang. ## xref Run cross reference analysis. ## ## plugins : ## list List local and global plugins for this project ## upgrade Upgrade plugins ## ## Run 'rebar3 help ' for details. # general options complete -f -c 'rebar3' -n 'not __fish_rebar3_needs_command' -l help -d 'Display the manual of a rebar3 command' complete -f -c 'rebar3' -s h -l help -d "Show the program options" complete -f -c 'rebar3' -s v -l version -d "Show version information" ## included tasks complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a as -d "Higher order task which takes a profile name and list of tasks to run under that profile." ## TODO: 'as' needs to inspect the rebar.config's profiles element complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a clean -d "Removes compiled beam files from apps." complete -f -c 'rebar3' -n '__fish_rebar3_using_command clean' -s a -l all -d "Clean all apps, including the dependencies" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a compile -d "Compile apps .app.src and .erl files." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a cover -d "Perform coverage analysis." complete -f -c 'rebar3' -n '__fish_rebar3_using_command cover' -s r -l reset -d "Resets all cover data" complete -f -c 'rebar3' -n '__fish_rebar3_using_command cover' -s v -l verbose -d "Prints coverage analysis in the terminal." ## ct complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a ct -d "Run Common Tests." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l dir -d "Compile and run all test suites in the specified directories." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l suites -d "Compile and run all test suites specified. Must be specified by full path, either absolute or relative to the current directory." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l group -d "Test groups to run." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l label -d "Test label." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l config -d "Config files to use when running tests." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l allow_user_terms -d "Allow user defined terms in config files." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l logdir -d "The directory in which test logs will be written. Default: _build/test/logs" complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l logopts -d "Options for common test logging." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l verbosity -d "Verbosity." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -s c -l cover -d "Generate cover data." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l include -d "Include folders." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l repeat -d "How often to repeat tests." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l duration -d "Max runtime (format: HHMMSS)." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l until -d "Run until (format: HHMMSS)." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l force_stop -d "Force stop on test timeout." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l basic_html -d "Show basic HTML." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l stylesheet -d "CSS stylesheet to apply to html output." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l decrypt_key -d "Path to key for decrypting config." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l decrypt_file -d "Path to file containing key for decrypting config." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l abort_if_missing_suites -d "Abort if suites are missing." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l multiply_timetraps -d "Multiply timetraps." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l scale_timetraps -d "Scale timetraps." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l create_priv_dir -d "Create priv dir (auto_per_run | auto_per_tc | manual_per_tc)." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l include -d "Directories containing additional include files." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -s v -l verbose -d "Enable verbose output. Default: false." complete -f -c 'rebar3' -n '__fish_rebar3_using_command ct' -l auto_compile -d "Let common test compile test suites instead of rebar3." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a deps -d "List dependencies" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a dialyzer -d "Run the Dialyzer analyzer on the project." complete -f -c 'rebar3' -n '__fish_rebar3_using_command dialyzer' -s u -l update-plt -d "Enable updating the PLT. Default: true" complete -f -c 'rebar3' -n '__fish_rebar3_using_command dialyzer' -s s -l succ-typings -d "Enable success typing analysis. Default: true" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a do -d "Higher order provider for running multiple tasks in a sequence." complete -f -c 'rebar3' -n '__fish_rebar3_using_command do' -a 'compile, clean, ct, cover, deps, dialyzer, edoc, eunit, help, new, pkgs, release, relup, report, shell, tar, unlock, unstable, update, upgrade, version, xref,' ## TODO: do should understand plugins, but now it does not. complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a edoc -d "Generate documentation using edoc." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a escriptize -d "Generate escript archive." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a eunit -d "Run EUnit Tests." complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -l app -d "Comma separated list of application test suites to run. Equivalent to `[{application, App}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -l application -d "Comma separated list of application test suites to run. Equivalent to `[{application, App}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s c -l cover -d "Generate cover data" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s d -l dir -d "Comma separated list of dirs to load tests from. Equivalent to `[{dir, Dir}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunut' -s e -l error_on_warning -d "Error on invalid test specifications instead of warning" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s f -l file -d "Comma separated list of files to load tests from. Equivalent to `[{file, File}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s m -l module -d "Comma separated list of modules to load tests from. Equivalent to `[{module, Module}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s s -l suite -d "Comma separated list of modules to load tests from. Equivalent to `[{module, Module}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s g -l generator -d "Comma separated list of generators (the format is `module:function`) to load tests from. Equivalent to `[{generator, Module, Function}]`" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -s v -l verbose -d "Verbose output" complete -f -c 'rebar3' -n '__fish_rebar3_using_command eunit' -l suite -d "Lists of test suites to run" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a help -d "Display a list of tasks or help for a given task or subtask." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a new -d "Create new project from templates." complete -f -c 'rebar3' -n '__fish_rebar3_using_command new' -s f -l force -d "Overwrite existing files" complete -f -c 'rebar3' -n '__fish_rebar3_using_command new' -a help -d "Display all variables and arguments for each template" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a paths -d "Print paths to build dirs in current profile." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l app -d "Comma separated list of applications to return paths for." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l base -d "Return the `base` path of the current profile." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l bin -d "Return the `bin` path of the current profile." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l ebin -d "Return all `ebin` paths of the current profile`s applications." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l lib -d "Return the `lib` path of the current profile." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l priv -d "Return the `priv` path of the current profile`s applications." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -s s -l separator -d "In case of multiple return paths, the separator character to use to join them." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l src -d "Return the `src` path of the current profile`s applications." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l rel -d "Return the `rel` path of the current profile." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a pkgs -d "List information for a hex package." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a release -d "Build release of project." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a relup -d "Create relup of releases." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a report -d "Provide a crash report to be sent to the rebar3 issues page." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a shell -d "Run shell with project apps and deps in path." complete -f -c 'rebar3' -n '__fish_rebar3_using_command shell' -l config -d "Allows to load a config file, if any. Defaults to the sys_config entry defined for relx if present." complete -f -c 'rebar3' -n '__fish_rebar3_using_command shell' -l name -d "equivalent to erlang`s -name" complete -f -c 'rebar3' -n '__fish_rebar3_using_command shell' -l sname -d "equivalent to erlang`s -sname" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a tar -d "Tar archive of release built of project." complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s n -l relname -d "Specify the name for the release that will be generated" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s v -l relvsn -d "Specify the version for the release" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s g -l goal -d "Specify a target constraint on the system. These are usually the OTP" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s u -l upfrom -d "Only valid with relup target, specify the release to upgrade from" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s o -l output-dir -d "The output directory for the release. This is `./` by default." complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s h -l help -d "Print usage" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s l -l lib-dir -d "Additional dir that should be searched for OTP Apps" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s p -l path -d "Additional dir to add to the code path" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l default-libs -d "Whether to use the default system added lib dirs (means you must add them all manually). Default is true" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s V -l verbose -d "Verbosity level, maybe between 0 and 3 [default: 2]" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s d -l dev-mode -d "Symlink the applications and configuration into the release instead of copying" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s i -l include-erts -d "If true include a copy of erts used to build with, if a path include erts at that path. If false, do not include erts" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s a -l override -d "Provide an app name and a directory to override in the form :" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s c -l config -d "The path to a config file [default: ]" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l overlay_vars -d "Path to a file of overlay variables" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l vm_args -d "Path to a file to use for vm.args" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l sys_config -d "Path to a file to use for sys.config" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l system_libs -d "Path to dir of Erlang system libs" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l version -d "Print relx version" complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s r -l root -d "The project root directory" complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a tree -d "Print dependency tree." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command tree' -s v -l verbose -d "Print repo and branch/tag/ref for git and hg deps." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a unlock -d "Unlock dependencies." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a unstable -d "Namespace providing commands that are still in flux." complete -f -c 'rebar3' -n '__fish_rebar3_using_command unstable' -a 'install upgrade' complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a update -d "Update package index." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a upgrade -d "Upgrade dependencies." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a version -d "Print version for rebar and current Erlang." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a xref -d "Run cross reference analysis." rebar3-3.18.0/priv/shell-completion/bash/0000755000232200023220000000000014164317745020516 5ustar debalancedebalancerebar3-3.18.0/priv/shell-completion/bash/rebar30000644000232200023220000001314414164317745021622 0ustar debalancedebalance# bash completion for rebar3 _rebar3() { local cur prev sopts lopts cmdsnvars COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" if [[ ${prev} == rebar3 ]] ; then sopts="-h -v" lopts="--help --version" cmdsnvars=" \ as \ clean \ compile \ cover \ ct \ deps \ dialyzer \ do \ edoc \ escriptize \ eunit \ help \ new \ path \ pkgs \ plugins \ release \ relup \ report \ shell \ tar \ tree \ unlock \ unstable \ update \ upgrade \ version \ xref \ " elif [[ ${prev} == as ]] ; then : elif [[ ${prev} == clean ]] ; then sopts="-a" lopts="--all" elif [[ ${prev} == compile ]] ; then : elif [[ ${prev} == cover ]] ; then sopts="-r -v" lopts="--reset --verbose" elif [[ ${prev} == ct ]] ; then sopts="-c -v" lopts=" \ --dir \ --suite \ --group \ --case \ --config \ --allow_user_terms \ --logdir \ --logopts \ --verbosity \ --silent_connections \ --stylesheet \ --cover \ --repeat \ --duration \ --until \ --force_stop \ --basic_html \ --stylesheet \ --decrypt_key \ --decrypt_file \ --abort_if_missing_suites \ --multiply_timetraps \ --scale_timetraps \ --create_priv_dir \ --include \ --verbose \ --auto_compile \ " elif [[ ${prev} == deps ]] ; then : elif [[ ${prev} == dialyzer ]] ; then sopts="-u -s" lopts="--update-plt --succ-typings" elif [[ ${prev} == do ]] ; then : elif [[ ${prev} == edoc ]] ; then : elif [[ ${prev} == escriptize ]] ; then : elif [[ ${prev} == eunit ]] ; then sopts="-c -e -v -d -f -m -s -g" lopts="--app --application --cover --dir --error_on_warning --file --module --suite --generator --verbose" elif [[ ${prev} == help ]] ; then : elif [[ ${prev} == new ]] ; then sopts="-f" lopts="--force" elif [[ ${prev} == path ]] ; then sopts="-s" lopts=" \ --app \ --base \ --bin \ --ebin \ --lib \ --priv \ --separator \ --src \ --rel \ " elif [[ ${prev} == pkgs ]] ; then : elif [[ ${prev} == plugins ]] ; then : elif [[ ${prev} == release ]] ; then sopts="-n -v -g -u -o -h -l -p -V -d -i -a -c -r" lopts=" \ --relname \ --relvsn \ --goal \ --upfrom \ --output-dir \ --help \ --lib-dir \ --path \ --default-libs \ --verbose \ --dev-mode \ --include-erts \ --override \ --config \ --overlay_vars \ --vm_args \ --sys_config \ --system_libs \ --version \ --root \ " elif [[ ${prev} == relup ]] ; then sopts="-n -v -g -u -o -h -l -p -V -d -i -a -c -r" lopts=" \ --relname \ --relvsn \ --goal \ --upfrom \ --output-dir \ --help \ --lib-dir \ --path \ --default-libs \ --verbose \ --dev-mode \ --include-erts \ --override \ --config \ --overlay_vars \ --vm_args \ --sys_config \ --system_libs \ --version \ --root \ " elif [[ ${prev} == report ]] ; then : elif [[ ${prev} == shell ]] ; then : elif [[ ${prev} == tar ]] ; then sopts="-n -v -g -u -o -h -l -p -V -d -i -a -c -r" lopts=" \ --relname \ --relvsn \ --goal \ --upfrom \ --output-dir \ --help \ --lib-dir \ --path \ --default-libs \ --verbose \ --dev-mode \ --include-erts \ --override \ --config \ --overlay_vars \ --vm_args \ --sys_config \ --system_libs \ --version \ --root \ " elif [[ ${prev} == tree ]] ; then sopts="-v" lopts="--verbose" elif [[ ${prev} == unstable ]] ; then : elif [[ ${prev} == update ]] ; then : elif [[ ${prev} == upgrade ]] ; then : elif [[ ${prev} == version ]] ; then : elif [[ ${prev} == xref ]] ; then : fi COMPREPLY=( $(compgen -W "${sopts} ${lopts} ${cmdsnvars}" -- ${cur}) ) if [ -n "$COMPREPLY" ] ; then # append space if matched COMPREPLY="${COMPREPLY} " # remove trailing space after equal sign COMPREPLY=${COMPREPLY/%= /=} fi return 0 } complete -o nospace -F _rebar3 rebar3 # Local variables: # mode: shell-script # sh-basic-offset: 4 # sh-indent-comment: t # indent-tabs-mode: nil # End: # ex: ts=4 sw=4 et filetype=sh rebar3-3.18.0/priv/shell-completion/zsh/0000755000232200023220000000000014164317745020405 5ustar debalancedebalancerebar3-3.18.0/priv/shell-completion/zsh/_rebar30000644000232200023220000004215114164317745021650 0ustar debalancedebalance#compdef rebar3 _rebar3 () { typeset -A opt_args local curcontext="$curcontext" state line local ret=1 _arguments -C \ '1: :_rebar3_tasks' \ '*::arg:->args' \ && ret=0 case $state in (args) curcontext="${curcontext%:*:*}:rebar-task-$words[1]:" case $line[1] in (as) _arguments \ '1:name' \ '2: :_rebar3_tasks' \ && ret=0 ;; (clean) _arguments \ '(-a --all)'{-a,--all}'[Clean all apps include deps.]' \ && ret=0 ;; (compile) _message 'no more arguments' && ret=0 ;; (cover) _arguments \ '(-r --reset)'{-r,--reset}'[Reset all coverdata.]' \ '(-v --verbose)'{-v,--verbose}'[Print coverage analysis.]' \ && ret=0 ;; (ct) _arguments \ '(--dir)--dir[List of additional directories containing test suites]:test directory:_files -/' \ '(--suite)--suite[List of test suites to run]:suites' \ '(--group)--group[List of test groups to run]:groups' \ '(--case)--case[List of test cases to run]:cases' \ '(--label)--label[Test label]:label' \ '(--config)--config[List of config files]:config files:_files' \ '(--allow_user_terms)--allow_user_terms' \ '(--logdir)--logdir[Log folder]:log folder:_files -/' \ '(--logopts)--logopts' \ '(--verbosity)--verbosity[Verbosity]:verbosity' \ '(-c --cover)'{-c,--cover}'[Generate cover data]' \ '(--repeat)--repeat[How often to repeat tests]:repeat test count' \ '(--duration)--duration[Max runtime (format: HHMMSS)]:max run time' \ '(--until)--until[Run until (format: HHMMSS)]:run until time' \ '(--force_stop)--force_stop[Force stop on test timeout]:skip_rest' \ '(--basic_html)--basic_html[Show basic HTML]' \ '(--stylesheet)--stylesheet[Stylesheet to use for test results]:stylesheet:_files' \ '(--decrypt_key)--decrypt_key[Path to key for decrypting config]:decrypt key:_files' \ '(--decrypt_file)--decrypt_file[Path to file containing key for decrypting config]:decrypt file:_files' \ '(--abort_if_missing_suites)--abort_if_missing_suites[Abort if suites are missing]:abort missing suites:(true false)' \ '(--multiply_timetraps)--multiply_timetraps' \ '(--scale_timetraps)--scale_timetraps' \ '(--create_priv_dir)--create_priv_dir' \ '(--include)--include[Directories containing additional include files]:includes' \ '(-v --verbose)'{-v,--verbose}'[Print coverage analysis]' \ '(--auto_compile)--auto_compile' \ && ret=0 ;; (deps) _message 'no more arguments' && ret=0 ;; (dialyzer) _arguments \ '(-u --update-plt)'{-u, --update-plt}'[Enable updating the PLT.]' \ '(-s --succ-typings)'{-s, --succ-typings}'[Enable success typing analysis.]' \ && ret=0 ;; (do) _message 'rebar do' && ret=0 ;; (edoc) _message 'rebar edoc' && ret=0 ;; (escriptize) _message 'rebar escriptize' && ret=0 ;; (eunit) _arguments \ '(--app)--app[Comma separated list of application test suites to run]:suites' \ '(--application)--application[Comma separated list of application test suites to run]:applications' \ '(-c --cover)'{-c,--cover}'[Generate cover data]' \ '(-d --dir)'{-d,--dir}'[Comma separated list of dirs to load tests from]:dirs' \ '(-e --error_on_warning)'{-e,--error_on_warning}'[Error on invalid test specifications instead of warning]' \ '(-f --file)'{-f,--file}'[Comma separated list of files to load tests from]:files' \ '(-m --module)'{-m,--module}'[Comma separated list of modules to load tests from]:modules' \ '(-s --suite)'{-s,--suite}'[Comma separated list of modules to load tests from]:modules' \ '(-g --generator)'{-g,--generator}'[Comma separated list of generators (the format is `module:function`) to load tests from.]:{generator, Module, Function}' \ '(-v --verbose)'{-v,--verbose}'[Verbose output]' \ && ret=0 ;; (help) _arguments '1: :_rebar3_tasks' && ret=0 ;; (new) _arguments \ '1:type:(app cmake escript lib plugin release)' \ '2:name:' \ '(-f --force)'{-f,--force}'[ overwrite existing files]' \ && ret=0 ;; (path) _arguments \ '(--app)--app[Comma separated list of applications to return paths for.]:apps' \ '(--base)--base[Return the `base` path of the current profile.]' \ '(--bin)--bin[Return the `bin` path of the current profile.]' \ '(--ebin)--ebin[Return all `ebin` paths of the current profile`s applications.]' \ '(--lib)--lib[Return the `lib` path of the current profile.]' \ '(--priv)--priv[Return the `priv` path of the current profile`s applications.]' \ '(-s --separator)--separator[In case of multiple return paths, the separator character to use to join them.]' \ && ret=0 ;; (pkgs) _message 'List information for a given package.' && ret=0 ;; (plugins) _arguments \ '1:type:(list upgrade)' \ && ret=0 ;; (release) _arguments \ '(-n --relname)'{-n,--relname}'[Specify the name for the release that will be generated.]:relname' \ '(-v --relvsn)'{-n,--relname}'[Specify the version for the release.]:relvsn' \ '(-g --goal)'{-g,--goal}'[Specify a target constraint on the system. These are usually the OTP.]:goal' \ '(-u --upfrom)'{-u,--upfrom}'[Only valid with relup target, specify the release to upgrade from.]:upfrom' \ '(-o --output-dir)'{-o,--output-dir}'[The output directory for the release. This is ./ by default.]:out directory:_files -/' \ '(-l --lib-dir)'{-l,--output-dir}'[Additional dir that should be searched for OTP Apps]:lib directory:_files -/' \ '(-p --path)'{-p,--path}'[Additional dir to add to the code path]:path directory:_files -/' \ '(--default-libs)--default-libs[Whether to use the default system added lib dirs]:default libs:(true false)' \ '(-V --verbose)'{-V,--verbose}'[Verbosity level, maybe between 0 and 3 ,default: 2]:verbosity level:(0 1 2 3)' \ '(-d --dev-mode)'{-d,--dev-mode}'[Symlink the applications and configuration into the release instead of copying]' \ '(-i --include-erts)'{-i,--dev-mode}'[If true include a copy of erts used to build with, if a path include erts at that path. If false, do not include erts]' \ '(-a --override)'{-a,--override}'[Provide an app name and a directory to override in the form :]:override' \ '(-c --config)'{-c,--config}'[The path to a config file]:config file:_files ' \ '(--overlay_vars)--overlay_vars[Path to a file of overlay variables]:overlay variables file:_files' \ '(--vm_args)--vm_args[Path to a file to use for vm.args]:vm args file:_files' \ '(--sys_config)--sys_config[Path to a file to use for sys.config]:sys config file:_files' \ '(--system_libs)--system_libs[Path to dir of Erlang system libs]:system libs:_files -/' \ '(--version)--version[Print relx version]' \ '(-r --root)'{-r,--root}'[The project root directory]:system libs:_files -/' \ && ret=0 ;; (relup) _arguments \ '(-n --relname)'{-n,--relname}'[Specify the name for the release that will be generated.]:relname' \ '(-v --relvsn)'{-n,--relname}'[Specify the version for the release.]:relvsn' \ '(-g --goal)'{-g,--goal}'[Specify a target constraint on the system. These are usually the OTP.]:goal' \ '(-u --upfrom)'{-u,--upfrom}'[Only valid with relup target, specify the release to upgrade from.]:upfrom' \ '(-o --output-dir)'{-o,--output-dir}'[The output directory for the release. This is ./ by default.]:out directory:_files -/' \ '(-l --lib-dir)'{-l,--output-dir}'[Additional dir that should be searched for OTP Apps]:lib directory:_files -/' \ '(-p --path)'{-p,--path}'[Additional dir to add to the code path]:path directory:_files -/' \ '(--default-libs)--default-libs[Whether to use the default system added lib dirs]:default libs:(true false)' \ '(-V --verbose)'{-V,--verbose}'[Verbosity level, maybe between 0 and 3 ,default: 2]:verbosity level:(0 1 2 3)' \ '(-d --dev-mode)'{-d,--dev-mode}'[Symlink the applications and configuration into the release instead of copying]' \ '(-i --include-erts)'{-i,--dev-mode}'[If true include a copy of erts used to build with, if a path include erts at that path. If false, do not include erts]' \ '(-a --override)'{-a,--override}'[Provide an app name and a directory to override in the form :]:override' \ '(-c --config)'{-c,--config}'[The path to a config file]:config file:_files ' \ '(--overlay_vars)--overlay_vars[Path to a file of overlay variables]:overlay variables file:_files' \ '(--vm_args)--vm_args[Path to a file to use for vm.args]:vm args file:_files' \ '(--sys_config)--sys_config[Path to a file to use for sys.config]:sys config file:_files' \ '(--system_libs)--system_libs[Path to dir of Erlang system libs]:system libs:_files -/' \ '(--version)--version[Print relx version]' \ '(-r --root)'{-r,--root}'[The project root directory]:system libs:_files -/' \ && ret=0 ;; (report) _arguments '1: :_rebar3_tasks' && ret=0 ;; (shell) _message 'Start a shell with project and deps preloaded' && ret=0 ;; (tar) _arguments \ '(-n --relname)'{-n,--relname}'[Specify the name for the release that will be generated.]:relname' \ '(-v --relvsn)'{-n,--relname}'[Specify the version for the release.]:relvsn' \ '(-g --goal)'{-g,--goal}'[Specify a target constraint on the system. These are usually the OTP.]:goal' \ '(-u --upfrom)'{-u,--upfrom}'[Only valid with relup target, specify the release to upgrade from.]:upfrom' \ '(-o --output-dir)'{-o,--output-dir}'[The output directory for the release. This is ./ by default.]:out directory:_files -/' \ '(-l --lib-dir)'{-l,--output-dir}'[Additional dir that should be searched for OTP Apps]:lib directory:_files -/' \ '(-p --path)'{-p,--path}'[Additional dir to add to the code path]:path directory:_files -/' \ '(--default-libs)--default-libs[Whether to use the default system added lib dirs]:default libs:(true false)' \ '(-V --verbose)'{-V,--verbose}'[Verbosity level, maybe between 0 and 3 ,default: 2]:verbosity level:(0 1 2 3)' \ '(-d --dev-mode)'{-d,--dev-mode}'[Symlink the applications and configuration into the release instead of copying]' \ '(-i --include-erts)'{-i,--dev-mode}'[If true include a copy of erts used to build with, if a path include erts at that path. If false, do not include erts]' \ '(-a --override)'{-a,--override}'[Provide an app name and a directory to override in the form :]:override' \ '(-c --config)'{-c,--config}'[The path to a config file]:config file:_files ' \ '(--overlay_vars)--overlay_vars[Path to a file of overlay variables]:overlay variables file:_files' \ '(--vm_args)--vm_args[Path to a file to use for vm.args]:vm args file:_files' \ '(--sys_config)--sys_config[Path to a file to use for sys.config]:sys config file:_files' \ '(--system_libs)--system_libs[Path to dir of Erlang system libs]:system libs:_files -/' \ '(--version)--version[Print relx version]' \ '(-r --root)'{-r,--root}'[The project root directory]:system libs:_files -/' \ && ret=0 ;; (tree) _arguments \ '(-v --verbose)'{-v,--verbose}'[Print repo and branch/tag/ref for git and hg deps]' \ && ret=0 ;; (unlock) _arguments \ '*: :_rebar3_list_deps' \ && ret=0 ;; (unstable) _arguments \ '*: :(install upgrade)' \ && ret=0 ;; (update) _message 'rebar update' && ret=0 ;; (upgrade) _arguments \ '*: :_rebar3_list_deps' \ && ret=0 ;; (version) _message 'rebar version' && ret=0 ;; (xref) _message 'rebar xref' && ret=0 esac esac } (( $+functions[_rebar3_tasks] )) || _rebar3_tasks() { local tasks; tasks=( 'as:Higher order provider for running multiple tasks in a sequence as a certain profiles.' 'clean:Remove compiled beam files from apps.' 'compile:Compile apps .app.src and .erl files.' 'cover:Perform coverage analysis.' 'ct:Run Common Tests.' 'deps:List dependencies.' 'dialyzer:Run the Dialyzer analyzer on the project.' 'do:Higher order provider for running multiple tasks in a sequence.' 'edoc:Generate documentation using edoc.' 'escriptize:Generate escript archive.' 'eunit:Run EUnit Tests.' 'help:Display a list of tasks or help for a given task or subtask.' 'new:Create new project from templates.' 'pkgs:List information for a given package.' 'plugins:List or upgrade plugins.' 'release:Build release of project.' 'relup:Create relup from 2 releases.' 'report:Provide a crash report to be sent to the rebar3 issues page.' 'shell:Run shell with project apps and deps in path.' 'tar:Tar archive of release built of project.' 'tree:Print dependency tree.' 'unlock:Unlock dependencies.' 'unstable:Namespace providing commands that are still in flux.' 'update:Update package index.' 'upgrade:Upgrade dependencies.' 'version:Print version for rebar and current Erlang.' 'xref:Run cross reference analysis.' ) _describe -t tasks 'rebar3 tasks' tasks "$@" } (( $+functions[_rebar3_list_deps] )) || _rebar3_list_deps() { local -a cmd packages deps_long deps_long=($PWD/_build/default/lib/*(/)) packages=( ${${deps_long#$PWD/_build/default/lib/}%-*-*} ) compadd "$@" -a packages } _rebar3 "$@" # Local variables: # mode: shell-script # sh-basic-offset: 2 # sh-indent-comment: t # indent-tabs-mode: nil # End: # ex: sw=2 ts=2 et filetype=sh rebar3-3.18.0/priv/templates/0000755000232200023220000000000014164317745016321 5ustar debalancedebalancerebar3-3.18.0/priv/templates/app.template0000644000232200023220000000106014164317745020633 0ustar debalancedebalance{description, "Complete OTP Application structure."}. {variables, [ {name, "mylib", "Name of the OTP application"}, {desc, "An OTP application", "Short description of the app"} ]}. {template, "app.erl", "{{name}}/src/{{name}}_app.erl"}. {template, "sup.erl", "{{name}}/src/{{name}}_sup.erl"}. {template, "otp_app.app.src", "{{name}}/src/{{name}}.app.src"}. {template, "app_rebar.config", "{{name}}/rebar.config"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "README.md", "{{name}}/README.md"}. rebar3-3.18.0/priv/templates/README.md0000644000232200023220000000007414164317745017601 0ustar debalancedebalance{{name}} ===== {{desc}} Build ----- $ rebar3 compile rebar3-3.18.0/priv/templates/LICENSE0000644000232200023220000002505414164317745017334 0ustar debalancedebalance Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright {{copyright_year}}, {{author_name}} <{{author_email}}>. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. rebar3-3.18.0/priv/templates/vm.args0000644000232200023220000000007214164317745017620 0ustar debalancedebalance-sname {{name}} -setcookie {{name}}_cookie +K true +A30 rebar3-3.18.0/priv/templates/sys.config0000644000232200023220000000004214164317745020322 0ustar debalancedebalance{{=@@ @@=}} [ {@@name@@, []} ]. rebar3-3.18.0/priv/templates/otp_lib.app.src0000644000232200023220000000033114164317745021236 0ustar debalancedebalance{application, {{name}}, [{description, "{{desc}}"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {licenses, ["Apache 2.0"]}, {links, []} ]}. rebar3-3.18.0/priv/templates/lib.template0000644000232200023220000000101214164317745020616 0ustar debalancedebalance{description, "Complete OTP Library application (no processes) structure"}. {variables, [ {name, "mylib", "Name of the OTP library application"}, {desc, "An OTP library", "Short description of the app"} ]}. {template, "mod.erl", "{{name}}/src/{{name}}.erl"}. {template, "otp_lib.app.src", "{{name}}/src/{{name}}.app.src"}. {template, "rebar.config", "{{name}}/rebar.config"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "README.md", "{{name}}/README.md"}. rebar3-3.18.0/priv/templates/otp_app.app.src0000644000232200023220000000040214164317745021247 0ustar debalancedebalance{{=@@ @@=}} {application, @@name@@, [{description, "@@desc@@"}, {vsn, "0.1.0"}, {registered, []}, {mod, {@@name@@_app, []}}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {licenses, ["Apache 2.0"]}, {links, []} ]}. rebar3-3.18.0/priv/templates/relx_rebar.config0000644000232200023220000000177114164317745021643 0ustar debalancedebalance{{=@@ @@=}} {erl_opts, [debug_info]}. {deps, []}. {relx, [{release, {@@name@@, "0.1.0"}, [@@name@@, sasl]}, {mode, dev}, %% automatically picked up if the files %% exist but can be set manually, which %% is required if the names aren't exactly %% sys.config and vm.args {sys_config, "./config/sys.config"}, {vm_args, "./config/vm.args"} %% the .src form of the configuration files do %% not require setting RELX_REPLACE_OS_VARS %% {sys_config_src, "./config/sys.config.src"}, %% {vm_args_src, "./config/vm.args.src"} ]}. {profiles, [{prod, [{relx, [%% prod is the default mode when prod %% profile is used, so does not have %% to be explicitly included like this {mode, prod} %% use minimal mode to exclude ERTS %% {mode, minimal} ] }]}]}. rebar3-3.18.0/priv/templates/escript.template0000644000232200023220000000103514164317745021526 0ustar debalancedebalance{description, "Complete escriptized application structure"}. {variables, [ {name, "mylib", "Name of the OTP application to be escriptized"}, {desc, "An escript", "Short description of the project"} ]}. {template, "escript_mod.erl", "{{name}}/src/{{name}}.erl"}. {template, "otp_lib.app.src", "{{name}}/src/{{name}}.app.src"}. {template, "escript_rebar.config", "{{name}}/rebar.config"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "escript_README.md", "{{name}}/README.md"}. rebar3-3.18.0/priv/templates/Makefile0000644000232200023220000000444214164317745017765 0ustar debalancedebalance# Based on c_src.mk from erlang.mk by Loic Hoguin CURDIR := $(shell pwd) BASEDIR := $(abspath $(CURDIR)/..) PROJECT ?= $(notdir $(BASEDIR)) PROJECT := $(strip $(PROJECT)) ERTS_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts/erts-~ts/include/\", [code:root_dir(), erlang:system_info(version)])." -s init stop) ERL_INTERFACE_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, include)])." -s init stop) ERL_INTERFACE_LIB_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, lib)])." -s init stop) C_SRC_DIR = $(CURDIR) C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so # System type and C compiler/flags. UNAME_SYS := $(shell uname -s) ifeq ($(UNAME_SYS), Darwin) CC ?= cc CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes CXXFLAGS ?= -O3 -finline-functions -Wall LDFLAGS ?= -flat_namespace -undefined suppress else ifeq ($(UNAME_SYS), FreeBSD) CC ?= cc CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes CXXFLAGS ?= -O3 -finline-functions -Wall else ifeq ($(UNAME_SYS), Linux) CC ?= gcc CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes CXXFLAGS ?= -O3 -finline-functions -Wall endif CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lei LDFLAGS += -shared # Verbosity. c_verbose_0 = @echo " C " $(?F); c_verbose = $(c_verbose_$(V)) cpp_verbose_0 = @echo " CPP " $(?F); cpp_verbose = $(cpp_verbose_$(V)) link_verbose_0 = @echo " LD " $(@F); link_verbose = $(link_verbose_$(V)) SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \)) OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(C_SRC_OUTPUT): $(OBJECTS) @mkdir -p $(BASEDIR)/priv/ $(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT) %.o: %.c $(COMPILE_C) $(OUTPUT_OPTION) $< %.o: %.cc $(COMPILE_CPP) $(OUTPUT_OPTION) $< %.o: %.C $(COMPILE_CPP) $(OUTPUT_OPTION) $< %.o: %.cpp $(COMPILE_CPP) $(OUTPUT_OPTION) $< clean: @rm -f $(C_SRC_OUTPUT) $(OBJECTS) rebar3-3.18.0/priv/templates/cmake.template0000644000232200023220000000015414164317745021136 0ustar debalancedebalance{description, "Standalone Makefile for building C/C++ in c_src"}. {template, "Makefile", "c_src/Makefile"}. rebar3-3.18.0/priv/templates/umbrella.template0000644000232200023220000000150014164317745021655 0ustar debalancedebalance{description, "OTP structure for executable programs (alias of 'release' template)"}. {variables, [ {name, "myapp", "Name of the OTP release. An app with this name will also be created."}, {desc, "An OTP application", "Short description of the release's main app's purpose"} ]}. {template, "app.erl", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}_app.erl"}. {template, "sup.erl", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}_sup.erl"}. {template, "otp_app.app.src", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}.app.src"}. {template, "relx_rebar.config", "{{name}}/rebar.config"}. {template, "sys.config", "{{name}}/config/sys.config"}. {template, "vm.args", "{{name}}/config/vm.args"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "README.md", "{{name}}/README.md"}. rebar3-3.18.0/priv/templates/rebar.config0000644000232200023220000000004514164317745020602 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}.rebar3-3.18.0/priv/templates/plugin_README.md0000644000232200023220000000060014164317745021152 0ustar debalancedebalance{{=@@ @@=}} @@name@@ ===== @@desc@@ Build ----- $ rebar3 compile Use --- Add the plugin to your rebar config: {plugins, [ {@@name@@, {git, "https://host/user/@@name@@.git", {tag, "0.1.0"}}} ]}. Then just call your plugin directly in an existing application: $ rebar3 @@name@@ ===> Fetching @@name@@ ===> Compiling @@name@@ rebar3-3.18.0/priv/templates/plugin.template0000644000232200023220000000106614164317745021357 0ustar debalancedebalance{description, "Rebar3 plugin project structure"}. {variables, [ {name, "myplugin", "Name of the plugin"}, {desc, "A rebar plugin", "Short description of the plugin's purpose"} ]}. {template, "plugin.erl", "{{name}}/src/{{name}}.erl"}. {template, "provider.erl", "{{name}}/src/{{name}}_prv.erl"}. {template, "otp_lib.app.src", "{{name}}/src/{{name}}.app.src"}. {template, "rebar.config", "{{name}}/rebar.config"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "plugin_README.md", "{{name}}/README.md"}. rebar3-3.18.0/priv/templates/escript_rebar.config0000644000232200023220000000040414164317745022332 0ustar debalancedebalance{erl_opts, [no_debug_info]}. {deps, []}. {escript_incl_apps, [{{name}}]}. {escript_main_app, {{name}}}. {escript_name, {{name}}}. {escript_emu_args, "%%! +sbtu +A1\n"}. %% Profiles {profiles, [{test, [{erl_opts, [debug_info]} ]}]}. rebar3-3.18.0/priv/templates/release.template0000644000232200023220000000145114164317745021477 0ustar debalancedebalance{description, "OTP Release structure for executable programs"}. {variables, [ {name, "myapp", "Name of the OTP release. An app with this name will also be created."}, {desc, "An OTP application", "Short description of the release's main app's purpose"} ]}. {template, "app.erl", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}_app.erl"}. {template, "sup.erl", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}_sup.erl"}. {template, "otp_app.app.src", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}.app.src"}. {template, "relx_rebar.config", "{{name}}/rebar.config"}. {template, "sys.config", "{{name}}/config/sys.config"}. {template, "vm.args", "{{name}}/config/vm.args"}. {template, "gitignore", "{{name}}/.gitignore"}. {template, "LICENSE", "{{name}}/LICENSE"}. {template, "README.md", "{{name}}/README.md"}. rebar3-3.18.0/priv/templates/sup.erl0000644000232200023220000000213114164317745017631 0ustar debalancedebalance{{=@@ @@=}} %%%------------------------------------------------------------------- %% @doc @@name@@ top level supervisor. %% @end %%%------------------------------------------------------------------- -module(@@name@@_sup). -behaviour(supervisor). -export([start_link/0]). -export([init/1]). -define(SERVER, ?MODULE). start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %% sup_flags() = #{strategy => strategy(), % optional %% intensity => non_neg_integer(), % optional %% period => pos_integer()} % optional %% child_spec() = #{id => child_id(), % mandatory %% start => mfargs(), % mandatory %% restart => restart(), % optional %% shutdown => shutdown(), % optional %% type => worker(), % optional %% modules => modules()} % optional init([]) -> SupFlags = #{strategy => one_for_all, intensity => 0, period => 1}, ChildSpecs = [], {ok, {SupFlags, ChildSpecs}}. %% internal functions rebar3-3.18.0/priv/templates/mod.erl0000644000232200023220000000004114164317745017577 0ustar debalancedebalance-module({{name}}). -export([]). rebar3-3.18.0/priv/templates/plugin.erl0000644000232200023220000000025414164317745020324 0ustar debalancedebalance-module({{name}}). -export([init/1]). -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> {ok, State1} = {{name}}_prv:init(State), {ok, State1}. rebar3-3.18.0/priv/templates/escript_README.md0000644000232200023220000000015314164317745021330 0ustar debalancedebalance{{name}} ===== {{desc}} Build ----- $ rebar3 escriptize Run --- $ _build/default/bin/{{name}} rebar3-3.18.0/priv/templates/escript_mod.erl0000644000232200023220000000073214164317745021337 0ustar debalancedebalance-module({{name}}). %% API exports -export([main/1]). %%==================================================================== %% API functions %%==================================================================== %% escript Entry point main(Args) -> io:format("Args: ~p~n", [Args]), erlang:halt(0). %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/priv/templates/app.erl0000644000232200023220000000056214164317745017610 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc {{name}} public API %% @end %%%------------------------------------------------------------------- -module({{name}}_app). -behaviour(application). -export([start/2, stop/1]). start(_StartType, _StartArgs) -> {{name}}_sup:start_link(). stop(_State) -> ok. %% internal functions rebar3-3.18.0/priv/templates/app_rebar.config0000644000232200023220000000015714164317745021446 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}. {shell, [ % {config, "config/sys.config"}, {apps, [{{name}}]} ]}. rebar3-3.18.0/priv/templates/gitignore0000644000232200023220000000021114164317745020225 0ustar debalancedebalance.rebar3 _* .eunit *.o *.beam *.plt *.swp *.swo .erlang.cookie ebin log erl_crash.dump .rebar logs _build .idea *.iml rebar3.crashdump *~ rebar3-3.18.0/priv/templates/provider.erl0000644000232200023220000000225114164317745020657 0ustar debalancedebalance-module({{name}}_prv). -export([init/1, do/1, format_error/1]). -define(PROVIDER, {{name}}). -define(DEPS, [app_discovery]). %% =================================================================== %% Public API %% =================================================================== -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> Provider = providers:create([ {name, ?PROVIDER}, % The 'user friendly' name of the task {module, ?MODULE}, % The module implementation of the task {bare, true}, % The task can be run by the user, always true {deps, ?DEPS}, % The list of dependencies {example, "rebar3 {{name}}"}, % How to use the plugin {opts, []}, % list of options understood by the plugin {short_desc, "{{desc}}"}, {desc, "{{desc}}"} ]), {ok, rebar_state:add_provider(State, Provider)}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> {ok, State}. -spec format_error(any()) -> iolist(). format_error(Reason) -> io_lib:format("~p", [Reason]). rebar3-3.18.0/pr2relnotes.sh0000755000232200023220000000114114164317745016156 0ustar debalancedebalance#!/usr/bin/env sh if [ -z $1 ] then echo "usage: $0 [pull-request-url]" exit 0 fi export url=${2:-"https://github.com/erlang/rebar3/pull/"} git log --merges --pretty=medium $1..HEAD | \ awk -v url=$url ' # first line of a merge commit entry /^commit / {mode="new"} # merge commit default message mode=="new" && / +Merge pull request/ { page_id=substr($4, 2, length($4)-1); mode="started"; next; } # line of content including title mode=="started" && / [^ ]+/ { print "- [" substr($0, 5) "](" url page_id ")"; mode="done" }' rebar3-3.18.0/test/0000755000232200023220000000000014164317745014322 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE.erl0000644000232200023220000001326614164317745017753 0ustar debalancedebalance%%% This suite can't run tests for built-in templates because %%% they require being escriptize and we currently don't support %%% this in here! -module(rebar_new_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [app_git_user, app_hg_user, app_with_fallbacks, app_with_flags1, app_with_flags2, plugin_tpl]. init_per_testcase(plugin_tpl, Config) -> application:load(rebar), DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("plugin_tpl"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), ec_file:copy(filename:join([DataDir, "plugin_tpl"]), AppsDir, [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), GlobalDir = filename:join([DataDir, "cache"]), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{global_rebar_dir, GlobalDir} ,{root_dir, AppsDir}]), mock_home_dir(DataDir), mock_empty_escript_templates(), [{apps, AppsDir}, {state, State}, {name, Name} | Config]; init_per_testcase(Case, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0), Name = rebar_test_utils:create_random_name(atom_to_list(Case)), Data = ?config(data_dir, Config), mock_home_dir(Data), mock_empty_escript_templates(), [{name, Name} | Config]. end_per_testcase(_, Config) -> meck:unload(), Config. mock_home_dir(Path) -> meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, template_dir, fun(_) -> Path end). mock_empty_escript_templates() -> %% Can't find escript templates unless we run %% from the escript, which obviously crashes these here tests. meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, escript_foldl, fun(_,_,_) -> {ok, []} end). app_git_user(Config) -> meck:expect(rebar_utils, sh, fun("git config --global user.name", _) -> {ok, "gitname"}; ("git config --global user.email", _) -> {ok, "git@email.com"} end), Name = ?config(name, Config), rebar_test_utils:run_and_check( Config, [], ["new", "test_app", Name, "author_name="], {ok, []} ), validate_files( Config, Name, [{"LICENSE", ["", "git@email.com"]}, {"README.md", [Name]}, {".gitignore", []}, {"rebar.config", []}, {filename:join(["src", Name++".app.src"]), [Name]}, {filename:join(["src", Name++"_sup.erl"]), [Name]}, {filename:join(["src", Name++"_app.erl"]), [Name]} ]). app_with_fallbacks(Config) -> meck:expect(rebar_utils, sh, fun(_, _) -> {error, fallback} end), Name = ?config(name, Config), rebar_test_utils:run_and_check( Config, [], ["new", "test_app", Name], {ok, []} ), validate_files( Config, Name, [{"LICENSE", ["Anonymous", "anonymous@example.org"]}, {"README.md", [Name]}, {".gitignore", []}, {"rebar.config", []}, {filename:join(["src", Name++".app.src"]), [Name]}, {filename:join(["src", Name++"_sup.erl"]), [Name]}, {filename:join(["src", Name++"_app.erl"]), [Name]} ]). app_hg_user(Config) -> meck:expect(rebar_utils, sh, fun("hg showconfig ui.username", _) -> {ok, "hgname "}; (_, _) -> {error, fallback} end), Name = ?config(name, Config), rebar_test_utils:run_and_check( Config, [], ["new", "test_app", Name], {ok, []} ), validate_files( Config, Name, [{"LICENSE", ["hgname", "hg@email.com"]}, {"README.md", [Name]}, {".gitignore", []}, {"rebar.config", []}, {filename:join(["src", Name++".app.src"]), [Name]}, {filename:join(["src", Name++"_sup.erl"]), [Name]}, {filename:join(["src", Name++"_app.erl"]), [Name]} ]). app_with_flags1(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check( Config, [], ["new", "test_app", "-f", Name], {ok, []} ), validate_files( Config, Name, [{"LICENSE", []}, {"README.md", []}, {".gitignore", []}, {"rebar.config", []}, {filename:join(["src", Name++".app.src"]), [Name]}, {filename:join(["src", Name++"_sup.erl"]), [Name]}, {filename:join(["src", Name++"_app.erl"]), [Name]} ]). app_with_flags2(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check( Config, [], ["new", "-f", "test_app", Name], {ok, []} ), validate_files( Config, Name, [{"LICENSE", []}, {"README.md", []}, {".gitignore", []}, {"rebar.config", []}, {filename:join(["src", Name++".app.src"]), [Name]}, {filename:join(["src", Name++"_sup.erl"]), [Name]}, {filename:join(["src", Name++"_app.erl"]), [Name]} ]). plugin_tpl(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check( Config, [], ["new", "-f", "tpl", Name], {ok, []} ), Result = filename:join(["src", Name++".erl"]), % In CWD {ok, Bin} = file:read_file(Result), {match, _} = re:run(Bin, Name, [multiline,global]). validate_files(_Config, Name, Checks) -> [begin Path = filename:join([Name, File]), ct:pal("validating ~s for content", [Path]), {ok, Bin} = file:read_file(Path), [{match, _} = re:run(Bin, Pattern, [multiline,global]) || Pattern <- Patterns] end || {File, Patterns} <- Checks], ok. rebar3-3.18.0/test/rebar_eunit_SUITE_data/0000755000232200023220000000000014164317745020563 5ustar debalancedebalancerebar3-3.18.0/test/rebar_eunit_SUITE_data/inflate0000755000232200023220000000076714164317745022145 0ustar debalancedebalance#!/usr/bin/env escript main(["basic_app"]) -> case filelib:is_file("basic_app.zip") of true -> zip:unzip("basic_app.zip"), halt(0); false -> io:format("unable to locate basic_app.zip~n", []), halt(1) end; main(["multi_app"]) -> case filelib:is_file("multi_app.zip") of true -> zip:unzip("multi_app.zip"), halt(0); false -> io:format("unable to locate multi_app.zip~n", []), halt(1) end, halt(0); main(_) -> io:format("usage: inflate basic_app | multi_app~n", []), halt(1).rebar3-3.18.0/test/rebar_eunit_SUITE_data/basic_app.zip0000644000232200023220000000330714164317745023233 0ustar debalancedebalancePK case filelib:is_dir("basic_app") of true -> zip:create("basic_app.zip", ["basic_app"]), halt(0); false -> io:format("unable to locate basic_app directory~n", []), halt(1) end; main(["multi_app"]) -> case filelib:is_dir("multi_app") of true -> zip:create("multi_app.zip", ["multi_app"]), halt(0); false -> io:format("unable to locate multi_app directory~n", []), halt(1) end, halt(0); main(_) -> io:format("usage: deflate basic_app | multi_app~n", []), halt(1).rebar3-3.18.0/test/rebar_eunit_SUITE_data/multi_app.zip0000644000232200023220000001255214164317745023306 0ustar debalancedebalancePK` B; tVpa5u]+R,M(AG;#Œa/ƻwJmPK- ӌFm"Aʔrn4~ \1}"UFvF~f('8s0 zGT+8ݱ;ʱNPN-$qpxPKnF߄`ifG :Zo4I^n@ZƧ_PK-/Ԓ[7!XQ۾/MRkb RSr PK--69`h ue9L"B?YuI>/D{g'{73dPK֡PK Rsyscfg_app/config/UT w`w`ux PK * RԨ%%syscfg_app/config/cmd2.configUT @w`ޒw`ux [{syscfg_app, [{cmd_cfg2, true}]}]. PK R|l&&syscfg_app/config/file2.configUT w`7w`ux [{syscfg_app, [{file_cfg2, true}]}]. PK $ Rɞ%%syscfg_app/config/cmd1.configUT 4w`גw`ux [{syscfg_app, [{cmd_cfg1, true}]}]. PK  R;%%syscfg_app/config/file1.configUT w`w`ux [{syscfg_app, [{file_cfg1, true}]}]. PK R~49Ssyscfg_app/rebar.configUT ˓w`˓w`ux N-,/()QRt%C?-3'PQB6 rqPK  R Asyscfg_app/UTw`ux PK  RAEsyscfg_app/src/UTw`ux PKpRZ!syscfg_app/src/syscfg_app.app.srcUTw`ux PK RÇA}syscfg_app/src/syscfg_app.erlUTw`ux PK RA_syscfg_app/config/UTw`ux PK * RԨ%%syscfg_app/config/cmd2.configUT@w`ux PK R|l&&'syscfg_app/config/file2.configUTw`ux PK $ Rɞ%%syscfg_app/config/cmd1.configUT4w`ux PK  R;%%!syscfg_app/config/file1.configUTw`ux PK R~49Ssyscfg_app/rebar.configUT˓w`ux PK (rebar3-3.18.0/test/rebar_xref_SUITE_data/0000755000232200023220000000000014164317745020403 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/0000755000232200023220000000000014164317745022412 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/0000755000232200023220000000000014164317745023355 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/0000755000232200023220000000000014164317745025742 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/0000755000232200023220000000000014164317745026531 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2.app.src0000644000232200023220000000044414164317745032410 0ustar debalancedebalance{application, rebar_issue2, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { rebar_issue2_app, []}}, {applications, [kernel, stdlib, rebar_issue1 ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_sup.erl0000644000232200023220000000200214164317745032503 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc rebar_issue2 top level supervisor. %% @end %%%------------------------------------------------------------------- -module(rebar_issue2_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_app.erl0000644000232200023220000000140214164317745032457 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc rebar_issue2 public API %% @end %%%------------------------------------------------------------------- -module(rebar_issue2_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> rebar_issue2_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/0000755000232200023220000000000014164317745025741 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/rebar.config0000644000232200023220000000035614164317745030227 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}. {xref_checks,[ undefined_function_calls, undefined_functions, locals_not_used, deprecated_function_calls, deprecated_functions ]}. {provider_hooks, [{post, [{compile, xref}]}]}. rebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/0000755000232200023220000000000014164317745026530 5ustar debalancedebalancerebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1.app.src0000644000232200023220000000042214164317745032402 0ustar debalancedebalance{application, rebar_issue1, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { rebar_issue1_app, []}}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_app.erl0000644000232200023220000000140214164317745032455 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc rebar_issue1 public API %% @end %%%------------------------------------------------------------------- -module(rebar_issue1_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> rebar_issue1_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_sup.erl0000644000232200023220000000200214164317745032501 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc rebar_issue1 top level supervisor. %% @end %%%------------------------------------------------------------------- -module(rebar_issue1_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_as_SUITE.erl0000644000232200023220000001611714164317745017563 0ustar debalancedebalance-module(rebar_as_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, all/0, as_basic/1, as_multiple_profiles/1, as_multiple_tasks/1, as_multiple_profiles_multiple_tasks/1, as_comma_placement/1, as_comma_then_space/1, as_dir_name/1, as_with_task_args/1, warn_on_empty_profile/1, error_on_empty_tasks/1, clean_as_profile/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config, "as_"). all() -> [as_basic, as_multiple_profiles, as_multiple_tasks, as_multiple_profiles_multiple_tasks, as_comma_placement, as_comma_then_space, as_dir_name, as_with_task_args, warn_on_empty_profile, error_on_empty_tasks, clean_as_profile]. as_basic(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_basic_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "default", "compile"], {ok, [{app, Name}]}). as_multiple_profiles(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_multiple_profiles_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo", ",", "bar", "compile"], {ok, [{app, Name}]}). as_multiple_tasks(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_multiple_tasks_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo", "clean", ",", "compile"], {ok, [{app, Name}]}). as_multiple_profiles_multiple_tasks(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_multiple_profiles_multiple_tasks_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo", ",", "bar", "clean", ",", "compile"], {ok, [{app, Name}]}). as_comma_placement(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_comma_placement_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo,bar", ",", "baz", ",qux", "compile"], {ok, [{app, Name}]}). as_comma_then_space(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_comma_then_space_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo,", "bar,", "baz", "compile"], {ok, [{app, Name}]}). as_dir_name(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_dir_name_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo,bar,baz", "compile"], {ok, [{app, Name}]}), true = filelib:is_dir(filename:join([AppDir, "_build", "foo+bar+baz"])). as_with_task_args(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_with_task_args_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "default", "compile"], {ok, [{app, Name}]}), rebar_test_utils:run_and_check(Config, [], ["as", "default", "clean", "-a"], {ok, [{app, Name, invalid}]}). warn_on_empty_profile(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_warn_empty_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), meck:new(rebar_log, [passthrough]), rebar_test_utils:run_and_check(Config, [], ["as", "fake1,fake2", "compile"], {ok, [{app, Name}]}), History = meck:history(rebar_log), ?assert(warn_match("fake1", History)), ?assert(warn_match("fake2", History)), meck:unload(rebar_log), ok. error_on_empty_tasks(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("as_error_empty_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), meck:new(rebar_log, [passthrough]), rebar_test_utils:run_and_check(Config, [], ["as", "default"], {error, "At least one task must be specified when using `as`"}), ok. warn_match(App, History) -> lists:any( fun({_, {rebar_log,log, [warn, "No entry for profile ~ts in config.", [ArgApp]]}, _}) -> ArgApp =:= App ; (_) -> false end, History). clean_as_profile(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("clean_as_profile_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["as", "foo", "compile"], {ok, [{app, Name, valid}]}), rebar_test_utils:run_and_check(Config, [], ["clean", "-a", "-p", "foo"], {ok, [{app, Name, invalid}]}). rebar3-3.18.0/test/rebar_hooks_SUITE.erl0000644000232200023220000002363714164317745020310 0ustar debalancedebalance-module(rebar_hooks_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> meck:unload(). init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). end_per_testcase(_, _Config) -> catch meck:unload(). all() -> [build_and_clean_app, run_hooks_once, run_hooks_once_profiles, escriptize_artifacts, run_hooks_for_plugins, deps_hook_namespace, bare_compile_hooks_default_ns, deps_clean_hook_namespace, eunit_app_hooks, sub_app_hooks, root_hooks, drop_hook_args]. %% Test post provider hook cleans compiled project app, leaving it invalid build_and_clean_app(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name, valid}]}), RConfFile = rebar_test_utils:create_config(AppDir, [{provider_hooks, [{post, [{compile, clean}]}]}]), {ok, RConf} = file:consult(RConfFile), rebar_test_utils:run_and_check(Config, RConf, ["compile"], {ok, [{app, Name, invalid}]}). escriptize_artifacts(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Artifact = "{{profile_dir}}/bin/"++Name, RConfFile = rebar_test_utils:create_config(AppDir, [ {escript_name, list_to_atom(Name)} ,{artifacts, [Artifact]} ]), {ok, RConf} = file:consult(RConfFile), try rebar_test_utils:run_and_check(Config, RConf, ["compile"], return) catch {error, {rebar_prv_compile, {missing_artifact, Artifact}}} -> ok end, RConfFile1 = rebar_test_utils:create_config(AppDir, [ {escript_name, list_to_atom(Name)} ,{artifacts, [Artifact]} ,{provider_hooks, [{post, [{compile, escriptize}]}]} ]), {ok, RConf1} = file:consult(RConfFile1), rebar_test_utils:run_and_check(Config, RConf1, ["compile"], {ok, [{app, Name, valid} ,{file, filename:join([AppDir, "_build/default/bin", Name])}]}). run_hooks_once(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), RebarConfig = [{pre_hooks, [{compile, "mkdir \"$REBAR_ROOT_DIR/blah\""}]}], rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name, valid}]}). %% test that even if a hook is defined at the project level in a used profile %% the hook is not run for each application in the project umbrella run_hooks_once_profiles(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), RebarConfig = [{profiles, [{hooks, [{pre_hooks, [{compile, "mkdir \"$REBAR_ROOT_DIR/blah\""}]}]}]}], rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "hooks", "compile"], {ok, [{app, Name, valid}]}). deps_hook_namespace(Config) -> mock_git_resource:mock([{deps, [{some_dep, "0.0.1"}]}]), Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", []}]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConfig = [ {deps, TopDeps}, {overrides, [ {override, some_dep, [ {provider_hooks, [ {pre, [ {compile, clean} ]} ]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{dep, "some_dep"}]} ). %% tests that hooks to compile when running bare compile run in the default namespace bare_compile_hooks_default_ns(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), HookFile = filename:join([?config(priv_dir, Config), "bare-post.hook"]), Cmd = case os:type() of {win32, _} -> "dir"; _ -> "ls" end, ConfOpts = [{provider_hooks, [{post, [{compile, clean}]}]}, {post_hooks, [{compile, Cmd ++ " > " ++ HookFile}]}], RConfFile = rebar_test_utils:create_config(AppDir, ConfOpts), {ok, RConf} = file:consult(RConfFile), rebar_test_utils:run_and_check( Config, RConf, ["bare", "compile", "--paths", "."], {ok, []} ), %% check that hooks did actually run ?assertMatch({ok, _}, file:read_file(HookFile)), ok. deps_clean_hook_namespace(Config) -> mock_git_resource:mock([{deps, [{some_dep, "0.0.1"}]}]), Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", []}]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConfig = [ {deps, TopDeps}, {overrides, [ {override, some_dep, [ {provider_hooks, [ {pre, [ {compile, clean} ]} ]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["clean"], {ok, [{dep, "some_dep"}]} ). %% Checks that a hook that is defined on an app (not a top level hook of a project with subapps) is run eunit_app_hooks(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RConfFile = rebar_test_utils:create_config(AppDir, [ {escript_name, list_to_atom(Name)} ,{provider_hooks, [{post, [{eunit, escriptize}]}]} ]), {ok, RConf} = file:consult(RConfFile), rebar_test_utils:run_and_check(Config, RConf, ["eunit"], {ok, [{app, Name, valid} ,{file, filename:join([AppDir, "_build/test/bin", Name])}]}). run_hooks_for_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PluginName = rebar_test_utils:create_random_name("plugin1_"), mock_git_resource:mock([{config, [{pre_hooks, [{compile, "echo whatsup > randomfile"}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}} ]}]), {ok, RConf} = file:consult(RConfFile), rebar_test_utils:run_and_check(Config, RConf, ["compile"], {ok, [{app, Name, valid}, {plugin, PluginName}, {file, filename:join([AppDir, "_build", "default", "plugins", PluginName, "randomfile"])}]}). %% test that a subapp of a project keeps its hooks sub_app_hooks(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(SubAppsDir, [{provider_hooks, [{post, [{compile, clean}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, []), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name, invalid}]} ). %% test that hooks at the top level don't run in the subapps root_hooks(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(SubAppsDir, [{provider_hooks, [{post, [{compile, clean}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{pre_hooks, [{compile, "mkdir \"$REBAR_ROOT_DIR/blah\""}]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name, invalid}]} ). drop_hook_args(Config) -> RebarConfig = [ {provider_hooks, [ {pre, [{eunit, path}]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["eunit", "--cover=false"], {ok, []} ). rebar3-3.18.0/test/rebar_alias_SUITE.erl0000644000232200023220000001451114164317745020245 0ustar debalancedebalance-module(rebar_alias_SUITE). -compile([export_all]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config, "alias_"). end_per_testcase(_, _Config) -> ok. all() -> [command, args, many, override_default, no_circular, release, check_namespaces, create_lib]. command() -> [{doc, "Runs multiple regular commands as one alias"}]. command(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_command_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{test, [compile, {unlock,"-a"}]}]}], %% compile job ran rebar_test_utils:run_and_check(Config, RebarConfig, ["test"], {ok, [{app, Name}]}), %% unlock job also ran Lockfile = filename:join(?config(apps, Config), "rebar.lock"), ?assertNot(filelib:is_file(Lockfile)), ok. args() -> [{doc, "Runs multiple regular commands as one alias, some of " "which have default arguments"}]. args(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_args_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{test, [{eunit,"-c"}, cover]}]}], %% test job ran (compiled and succeeded) rebar_test_utils:run_and_check(Config, RebarConfig, ["test"], {ok, [{app, Name}]}), %% cover job also ran, meaning eunit had coverage on, otherwise %% the index file is not generated. CoverFile = filename:join([?config(apps, Config), "_build", "test", "cover", "index.html"]), ?assert(filelib:is_file(CoverFile)), ok. many() -> [{doc, "Multiple aliases may be registered"}]. many(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_args_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{test, [{eunit,"-c"}, cover]}, {nolock, [compile, {unlock,"-a"}]}]}], %% test job ran (compiled and succeeded) rebar_test_utils:run_and_check(Config, RebarConfig, ["test"], {ok, [{app, Name}]}), rebar_test_utils:run_and_check(Config, RebarConfig, ["nolock"], {ok, [{app, Name}]}), %% both jobs ran (see args/1 and command/1) CoverFile = filename:join([?config(apps, Config), "_build", "test", "cover", "index.html"]), ?assert(filelib:is_file(CoverFile)), Lockfile = filename:join(?config(apps, Config), "rebar.lock"), ?assertNot(filelib:is_file(Lockfile)), ok. override_default() -> [{doc, "An alias cannot take over a default provider"}]. override_default(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_override_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{compile, [help]}]}], %% App compiles anyway rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), ok. no_circular() -> [{doc, "An alias cannot define itself as itself"}, {timetrap, 2000}]. no_circular(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_circular_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{test, [help, {test,"-a"}, compile]}]}], %% Code does not deadlock forever and errors by not knowing %% the command rebar_test_utils:run_and_check(Config, RebarConfig, ["test"], {error, [$C,$o,$m,$m,$a,$n,$d,$ ,"test",$ ,$n,$o,$t,$ , $f,$o,$u,$n,$d]}), ok. release() -> [{doc, "An alias for a release command"}]. release(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_release_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{relx, [{release, {skipped_release, Vsn}, []}, {release, {the_release, Vsn}, [list_to_atom(Name)]}, {lib_dirs, [AppDir]}]}, {alias, [{the_rel1, [clean, {release, "-n the_release"}]}, {the_rel2, [clean, {release, "--relname=the_release"}]}]}], rebar_test_utils:run_and_check( Config, RebarConfig, ["the_rel1"], {ok, [{release, the_release, Vsn, false}]}), rebar_test_utils:run_and_check( Config, RebarConfig, ["the_rel2"], {ok, [{release, the_release, Vsn, false}]}), ok. check_namespaces() -> [{doc, "Test calling commands with namespaces from rebar3"}]. check_namespaces(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("alias_args_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{test, [{eunit,"-c"}, {plugins, list}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["test"], {ok, [{app, Name}]}), ok. create_lib() -> [{doc, "Test calling commands with namespaces from rebar3"}]. create_lib(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("create_lib_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{alias, [{test, [compile, {do, "new lib shouldexist"}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["test"], {ok, [{app, Name}]}), AppFile = filename:join(?config(apps, Config), "../../../../shouldexist/src/shouldexist.app.src"), ?assert(filelib:is_file(AppFile)), ok. rebar3-3.18.0/test/rebar_install_deps_SUITE.erl0000644000232200023220000004344614164317745021646 0ustar debalancedebalance-module(rebar_install_deps_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). all() -> [{group, git}, {group, pkg}, {group, mixed}]. groups() -> [{unique, [], [flat, pick_highest_left, pick_highest_right, pick_smallest1, pick_smallest2, circular1, circular2, circular_skip, fail_conflict, default_profile, nondefault_profile, nondefault_pick_highest]}, {git, [], [{group, unique}]}, {pkg, [], [{group, unique}]}, {mixed, [], [ m_flat1, m_flat2, m_circular1, m_circular2, m_pick_source1, m_pick_source2, m_pick_source3, m_pick_source4, m_pick_source5, m_pick_source6, m_source_to_pkg, m_pkg_level1, m_pkg_level2, m_pkg_level3, m_pkg_level3_alpha_order ]} ]. init_per_suite(Config) -> application:start(meck), Config. end_per_suite(_Config) -> application:stop(meck). init_per_group(git, Config) -> [{deps_type, git} | Config]; init_per_group(pkg, Config) -> [{deps_type, pkg} | Config]; init_per_group(mixed, Config) -> [{deps_type, mixed} | Config]; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. init_per_testcase(Case, Config) when is_atom(Case) -> DepsType = ?config(deps_type, Config), init_per_testcase({DepsType, Case}, Config); init_per_testcase({mixed, Case}, Config) -> {Deps, Warnings, Expect} = mdeps(Case), Expected = case Expect of {ok, List} -> {ok, format_expected_mdeps(List)}; Other -> Other end, mock_warnings(), [{expect, Expected}, {warnings, format_expected_mixed_warnings(Warnings)} | setup_project(Case, Config, rebar_test_utils:expand_deps(mixed, Deps))]; init_per_testcase({DepsType, Case}, Config) -> {Deps, Warnings, Expect} = deps(Case), Expected = case Expect of {ok, List} -> {ok, format_expected_deps(List)}; Other -> Other end, mock_warnings(), [{expect, Expected}, {warnings, Warnings} | setup_project(Case, Config, rebar_test_utils:expand_deps(DepsType, Deps))]. end_per_testcase(_, Config) -> meck:unload(), Config. format_expected_deps(Deps) -> lists:append([case Dep of {N,V} -> [{dep, N, V}, {lock, N, V}]; N -> [{dep, N}, {lock, N}] end || Dep <- Deps]). format_expected_mdeps(Deps) -> %% for mixed deps, lowercase is a package, uppercase is source. %% We can't check which was used from the dep, but the lock contains %% the type and we can use that information. lists:append([ case Dep of {N,V} when hd(N) >= $a, hd(N) =< $z -> UN = rebar_string:uppercase(N), [{dep, UN, V}, {lock, pkg, UN, V}]; {N,V} when hd(N) >= $A, hd(N) =< $Z -> [{dep, N, V}, {lock, src, N, V}]; N when hd(N) >= $a, hd(N) =< $z -> UN = rebar_string:uppercase(N), [{dep, UN}, {lock, pkg, UN, "0.0.0"}]; N when hd(N) >= $A, hd(N) =< $Z -> [{dep, N}, {lock, src, N, "0.0.0"}] end || Dep <- Deps]). format_expected_mixed_warnings(none) -> none; format_expected_mixed_warnings(Warnings) -> [case W of {N, Vsn} when hd(N) >= $a, hd(N) =< $z -> {pkg, rebar_string:uppercase(N), Vsn}; {N, Vsn} when hd(N) >= $A, hd(N) =< $Z -> {git, N, Vsn}; N when hd(N) >= $a, hd(N) =< $z -> {pkg, rebar_string:uppercase(N), "0.0.0"}; N when hd(N) >= $A, hd(N) =< $Z -> {git, N, "0.0.0"} end || W <- Warnings]. %% format: %% {Spec, %% [Warning], %% {ok, Result} | {error, Reason}} %% %% Spec is a list of levelled dependencies of two possible forms: %% - {"Name", Spec} %% - {"Name", "Vsn", Spec} %% %% Warnings are going to match on mocked ?WARN(...) %% calls to be evaluated. An empty list means we do not care about %% warnings, not that no warnings will be printed. This means %% the list of warning isn't interpreted to be exhaustive, and more %% warnings may be generated than are listed. deps(flat) -> {[{"B", []}, {"C", []}], [], {ok, ["B", "C"]}}; deps(pick_highest_left) -> {[{"B", [{"C", "2.0.0", []}]}, {"C", "1.0.0", []}], [{"C","2.0.0"}], {ok, ["B", {"C", "1.0.0"}]}}; deps(pick_highest_right) -> {[{"B", "1.0.0", []}, {"C", [{"B", "2.0.0", []}]}], [{"B","2.0.0"}], {ok, [{"B","1.0.0"}, "C"]}}; deps(pick_smallest1) -> {[{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}], [{"D","2.0.0"}], %% we pick D1 because B < C {ok, ["B","C",{"D","1.0.0"}]}}; deps(pick_smallest2) -> {[{"C", [{"D", "2.0.0", []}]}, {"B", [{"D", "1.0.0", []}]}], [{"D","2.0.0"}], %% we pick D1 because B < C {ok, ["B","C",{"D","1.0.0"}]}}; deps(circular1) -> {[{"B", [{"A", []}]}, % A is the top-level app {"C", []}], [], {error, {rebar_prv_install_deps, {cycles, [[<<"A">>,<<"B">>]]}}}}; deps(circular2) -> {[{"B", [{"C", [{"B", []}]}]}, {"C", []}], [], {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}}; deps(circular_skip) -> %% Never spot the circular dep due to being to low in the deps tree %% in source deps {[{"B", [{"C", "2.0.0", [{"B", []}]}]}, {"C", "1.0.0", [{"D",[]}]}], [{"C","2.0.0"}], {ok, ["B", {"C","1.0.0"}, "D"]}}; deps(fail_conflict) -> {[{"B", [{"C", "2.0.0", []}]}, {"C", "1.0.0", []}], [{"C","2.0.0"}], rebar_abort}; deps(default_profile) -> {[{"B", []}, {"C", []}], [], {ok, ["B", "C"]}}; deps(nondefault_profile) -> {[{"B", []}, {"C", []}], [], {ok, ["B", "C"]}}; deps(nondefault_pick_highest) -> %% This is all handled in setup_project {[],[],{ok,[]}}. %% format: %% Same as `deps/1' except "A" is a source dep %% and "a" is a package dep. mdeps(m_flat1) -> {[{"c", []}, {"B", []}], [], {ok, ["B","c"]}}; mdeps(m_flat2) -> {[{"B", []}, {"c", []}], [], {ok, ["B","c"]}}; mdeps(m_circular1) -> {[{"b", [{"a",[]}]}], % "A" is the top app [], {error, {rebar_prv_install_deps, {cycles, [[<<"A">>,<<"B">>]]}}}}; mdeps(m_circular2) -> {[{"B", [{"c", [{"b", []}]}]}], [], {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}}; mdeps(m_pick_source1) -> {[{"B", [{"D", []}]}, {"c", [{"d", []}]}], ["d"], {ok, ["B", "c", "D"]}}; mdeps(m_pick_source2) -> %% The order of declaration is important. {[{"b", []}, {"B", []}], [], {ok, ["b"]}}; mdeps(m_pick_source3) -> {[{"B", []}, {"b", []}], [], {ok, ["B"]}}; mdeps(m_pick_source4) -> {[{"b", [{"d", "1.0.0", []}]}, {"C", [{"D", "1.0.0", []}]}], [{"D", "1.0.0"}], {ok, ["b", "C", {"d", "1.0.0"}]}}; mdeps(m_pick_source5) -> {[{"B", [{"d", "1.0.0", []}]}, {"C", [{"D", "1.0.0", []}]}], [{"D", "1.0.0"}], {ok, ["B", "C", {"d", "1.0.0"}]}}; mdeps(m_pick_source6) -> {[{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "1.0.0", []}]}], none, {ok, ["B", "C", {"D", "1.0.0"}]}}; mdeps(m_source_to_pkg) -> {[{"B", [{"c",[{"d", []}]}]}], [], {ok, ["B", "c", "d"]}}; mdeps(m_pkg_level1) -> {[{"B", [{"D", [{"e", "2.0.0", []}]}]}, {"C", [{"e", "1.0.0", []}]}], [{"e","2.0.0"}], {ok, ["B","C","D",{"e","1.0.0"}]}}; mdeps(m_pkg_level2) -> {[{"B", [{"e", "1.0.0", []}]}, {"C", [{"D", [{"e", "2.0.0", []}]}]}], [{"e","2.0.0"}], {ok, ["B","C","D",{"e","1.0.0"}]}}; mdeps(m_pkg_level3_alpha_order) -> {[{"B", [{"d", [{"f", "1.0.0", []}]}]}, {"C", [{"E", [{"f", "2.0.0", []}]}]}], [{"f","2.0.0"}], {ok, ["B","C","d","E",{"f","1.0.0"}]}}; mdeps(m_pkg_level3) -> {[{"B", [{"d", [{"f", "1.0.0", []}]}]}, {"C", [{"E", [{"G", [{"f", "2.0.0", []}]}]}]}], [{"f","2.0.0"}], {ok, ["B","C","d","E","G",{"f","1.0.0"}]}}. setup_project(fail_conflict, Config0, Deps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( Config0, "fail_conflict_"++atom_to_list(DepsType)++"_" ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}, {deps_error_on_conflict, true}]), {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), [{rebarconfig, RebarConf} | Config]; setup_project(nondefault_profile, Config0, Deps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( Config0, "nondefault_profile_"++atom_to_list(DepsType)++"_" ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{profiles, [ {nondef, [{deps, TopDeps}]} ]}]), {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), [{rebarconfig, RebarConf} | Config]; setup_project(nondefault_pick_highest, Config0, _) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( Config0, "nondefault_pick_highest_"++atom_to_list(DepsType)++"_" ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), DefaultDeps = rebar_test_utils:expand_deps(DepsType, [{"B", [{"C", "1.0.0", []}]}]), ProfileDeps = rebar_test_utils:expand_deps(DepsType, [{"C", "2.0.0", []}]), DefaultTop = rebar_test_utils:top_level_deps(DefaultDeps), ProfileTop = rebar_test_utils:top_level_deps(ProfileDeps), RebarConf = rebar_test_utils:create_config( AppDir, [{deps, DefaultTop}, {profiles, [{nondef, [{deps, ProfileTop}]}]}] ), case DepsType of git -> {SrcDeps, _} = rebar_test_utils:flat_deps(DefaultDeps++ProfileDeps), mock_git_resource:mock([{deps, SrcDeps}]); pkg -> {_, PkgDeps} = rebar_test_utils:flat_deps(DefaultDeps++ProfileDeps), mock_pkg_resource:mock([{pkgdeps, PkgDeps}]) end, [{rebarconfig, RebarConf} | Config]; setup_project(Case, Config0, Deps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( Config0, atom_to_list(Case)++"_installdeps_"++atom_to_list(DepsType)++"_" ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]), {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), [{rebarconfig, RebarConf} | Config]. mock_warnings() -> %% just let it do its thing, we check warnings through %% the call log. meck:new(rebar_log, [no_link, passthrough]). %%% TESTS %%% flat(Config) -> run(Config). pick_highest_left(Config) -> run(Config). pick_highest_right(Config) -> run(Config). pick_smallest1(Config) -> run(Config). pick_smallest2(Config) -> run(Config). circular1(Config) -> run(Config). circular2(Config) -> run(Config). circular_skip(Config) -> run(Config). fail_conflict(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], ?config(expect, Config) ), check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)). default_profile(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), AppDir = ?config(apps, Config), {ok, Apps} = Expect = ?config(expect, Config), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], Expect ), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "profile", "lock"], Expect ), check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)), BuildDir = filename:join([AppDir, "_build"]), [?assertMatch({ok, #file_info{type=directory}}, file:read_file_info(filename:join([BuildDir, "default", "lib", App]))) || {dep, App} <- Apps], [?assertMatch({ok, #file_info{type=directory}}, % somehow symlinks return dirs file:read_file_info(filename:join([BuildDir, "profile", "lib", App]))) || {dep, App} <- Apps], %% A second run to another profile also links default to the right spot rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], Expect ), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "other", "lock"], Expect ), [?assertMatch({ok, #file_info{type=directory}}, % somehow symlinks return dirs file:read_file_info(filename:join([BuildDir, "other", "lib", App]))) || {dep, App} <- Apps]. nondefault_profile(Config) -> %% The dependencies here are saved directly to the {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), AppDir = ?config(apps, Config), {ok, AppLocks} = ?config(expect, Config), try rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "nondef", "lock"], {ok, AppLocks} ), error(generated_locks) catch error:generated_locks -> error(generated_locks); _:_ -> ok end, Apps = [App || App = {dep, _} <- AppLocks], Expect = {ok, Apps}, rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "nondef", "lock"], Expect ), check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)), BuildDir = filename:join([AppDir, "_build"]), [?assertMatch({error, enoent}, file:read_file_info(filename:join([BuildDir, "default", "lib", App]))) || {dep, App} <- Apps], [?assertMatch({ok, #file_info{type=directory}}, file:read_file_info(filename:join([BuildDir, "nondef", "lib", App]))) || {dep, App} <- Apps], %% A second run to another profile doesn't link dependencies rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "other", "lock"], Expect ), [?assertMatch({error, enoent}, file:read_file_info(filename:join([BuildDir, "default", "lib", App]))) || {dep, App} <- Apps]. nondefault_pick_highest(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{dep, "B"}, {lock, "B"}, {lock, "C", "1.0.0"}, {dep, "C", "1.0.0"}], "default"} ), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "nondef", "lock"], {ok, [{dep, "B"}, {lock, "B"}, {lock, "C", "1.0.0"}, {dep, "C", "2.0.0"}], "nondef"} ), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{dep, "B"}, {lock, "B"}, {dep, "C", "1.0.0"}, {lock, "C", "1.0.0"}], "default"} ), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "nondef", "lock"], {ok, [{dep, "B"}, {lock, "B"}, {lock, "C", "1.0.0"}, {dep, "C", "2.0.0"}], "nondef"} ). m_flat1(Config) -> run(Config). m_flat2(Config) -> run(Config). m_circular1(Config) -> run(Config). m_circular2(Config) -> run(Config). m_pick_source1(Config) -> run(Config). m_pick_source2(Config) -> run(Config). m_pick_source3(Config) -> run(Config). m_pick_source4(Config) -> run(Config). m_pick_source5(Config) -> run(Config). m_pick_source6(Config) -> run(Config). m_source_to_pkg(Config) -> run(Config). m_pkg_level1(Config) -> run(Config). m_pkg_level2(Config) -> run(Config). m_pkg_level3(Config) -> run(Config). m_pkg_level3_alpha_order(Config) -> run(Config). run(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], ?config(expect, Config) ), check_warnings(warning_calls(), ?config(warnings, Config), ?config(deps_type, Config)). warning_calls() -> History = meck:history(rebar_log), [{Str, Args} || {_, {rebar_log, log, [warn, Str, Args]}, _} <- History]. error_calls() -> History = meck:history(rebar_log), [{Str, Args} || {_, {rebar_log, log, [error, Str, Args]}, _} <- History]. check_warnings(_, [], _) -> ok; check_warnings(Warns, [{Type, Name, Vsn} | Rest], mixed) -> ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]), ?assert(in_warnings(Type, Warns, Name, Vsn)), check_warnings(Warns, Rest, mixed); check_warnings(Warns, [{Name, Vsn} | Rest], Type) -> ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]), ?assert(in_warnings(Type, Warns, Name, Vsn)), check_warnings(Warns, Rest, Type); check_warnings(Warns, none, _Type) -> ct:pal("Checking that there were no warnings", []), ?assert(Warns == []). in_warnings(git, Warns, NameRaw, VsnRaw) -> Name = iolist_to_binary(NameRaw), Vsn = iolist_to_binary([$",VsnRaw,$"]), 1 =< length([1 || {_, [[AppName, $\s,$(,$f,$r,$o,$m,$\s,[${,["git",$,, _URL, $,,[${,["tag",$,, AppVsn], $}]],$}],$)]]} <- Warns, iolist_to_binary(AppName) =:= Name, iolist_to_binary(AppVsn) =:= Vsn]); in_warnings(pkg, Warns, NameRaw, VsnRaw) -> Name = iolist_to_binary(NameRaw), Vsn = iolist_to_binary(VsnRaw), 1 =< length([1 || {_, [[AppName, $\s,$v, AppVsn]]} <- Warns, iolist_to_binary(AppName) =:= Name, iolist_to_binary(AppVsn) =:= Vsn]). rebar3-3.18.0/test/rebar_compiler_dag_SUITE.erl0000644000232200023220000004135314164317745021605 0ustar debalancedebalance-module(rebar_compiler_dag_SUITE). -compile([export_all, nowarn_export_all]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). all() -> [exists, {group, with_project}]. groups() -> %% The tests in this group are dirty, the order is specific %% and required across runs for tests to work. [{with_project, [sequence], [ find_structure, app_sort, propagate_include_app1a, propagate_include_app1b, propagate_include_app2, propagate_behaviour, propagate_app1_ptrans, propagate_app2_ptrans, propagate_app2_ptrans_hrl ]} ]. init_per_suite(Config) -> rebar_compiler_erl:module_info(), % ensure it is loaded Config. end_per_suite(Config) -> Config. init_per_group(with_project, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "apps"), AppDir = ?config(apps, NewConfig), Name1 = rebar_test_utils:create_random_name("app1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [kernel, stdlib]), Name3 = rebar_test_utils:create_random_name("app3_"), Vsn3 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name3]), Name3, Vsn3, [kernel, stdlib]), apply_project(AppDir, [{app1, Name1}, {app2, Name2}, {app3, Name3}], project()), [{app_names, [Name1, Name2, Name3]}, {vsns, [Vsn1, Vsn2, Vsn3]} | NewConfig]; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. exists(Config) -> %% Create a DAG Priv = ?config(priv_dir, Config), G = rebar_compiler_dag:init(Priv, compilermod, "label", [crit_meta]), rebar_compiler_dag:store_artifact(G, "somefile", "someartifact", [written]), rebar_compiler_dag:maybe_store(G, Priv, compilermod, "label", [crit_meta]), rebar_compiler_dag:terminate(G), ?assertEqual(valid, rebar_compiler_dag:status(Priv, compilermod, "label", [crit_meta])), ?assertEqual(not_found, rebar_compiler_dag:status(Priv, compilermad, "label", [crit_meta])), ?assertEqual(not_found, rebar_compiler_dag:status(Priv, compilermod, "lobel", [crit_meta])), ?assertEqual(bad_meta, rebar_compiler_dag:status(Priv, compilermod, "label", [crit_zeta])), ok. project() -> [{app1, [ {"src/app1.erl", "-module(app1).\n" "-include(\"app1_a.hrl\").\n" "-include(\"app1_b.hrl\").\n" "-include_lib(\"{{app2}}/include/app2.hrl\").\n" "-compile({parse_transform, app1_trans}).\n" "-compile({parse_transform, {app3, []}}).\n" "-behaviour(app2).\n" "-export([cb/0]).\n" "cb() -> {?APP1A, ?APP1B, ?APP2}.\n"}, {"src/app1_trans.erl", "-module(app1_trans).n" "-export([parse_transform/2]).\n" "parse_transform(Forms, _Opts) -> Forms.\n"}, {"src/app1_a.hrl", "-define(APP1A, 1).\n"}, {"include/app1_b.hrl", "-define(APP1B, 1).\n"} ]}, {app2, [ {"src/app2.erl", "-module(app2).\n" "-callback cb() -> term().\n"}, {"include/app2.hrl", "-include(\"app2_resolve.hrl\").\n" "-define(APP2, 1).\n"}, {"src/app2_resolve.hrl", "this file should be found but never is"}, {"include/never_found.hrl", "%% just comments"} ]}, {app3, [ {"src/app3.erl", "-module(app3).\n" "-include_lib(\"{{app2}}/include/app2.hrl\").\n" "-include(\"app3_resolve.hrl\").\n" "-export([parse_transform/2]).\n" "parse_transform(Forms, _Opts) -> Forms.\n"}, {"src/app3_resolve.hrl", "-behaviour(app2).\n" "-export([cb/0]).\n" "cb() -> {}.\n" "%% this file should be found"} ]} ]. find_structure() -> [{doc, "ensure a proper digraph is built with all files"}]. find_structure(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], Edges = [{V1,V2} || E <- digraph:edges(G), {_,V1,V2,_} <- [digraph:edge(G, E)]], %% All timestamps are the same since we just created the thing {_, Stamp} = hd(FileStamps), Matches = [ {"/src/app1.erl", Stamp}, {"/src/app1_trans.erl", Stamp}, {"/src/app1_a.hrl", Stamp}, {"/include/app1_b.hrl", Stamp}, {"/src/app2.erl", Stamp}, {"/include/app2.hrl", Stamp}, {"/include/app2.hrl", Stamp}, {"/src/app3.erl", Stamp}, {"/src/app3_resolve.hrl", Stamp} ], matches(Matches, FileStamps), ?assertEqual(undefined, find_match(".*/never_found.hrl", FileStamps)), ?assertEqual(undefined, find_match(".*/app2_resolve.hrl", FileStamps)), ct:pal("Edges: ~p", [Edges]), edges([ {"/src/app1.erl", "/src/app1_a.hrl"}, {"/src/app1.erl", "/include/app1_b.hrl"}, {"/src/app1.erl", "/src/app2.erl"}, {"/src/app1.erl", "/include/app2.hrl"}, {"/src/app1.erl", "/src/app1_trans.erl"}, {"/src/app1.erl", "/src/app3.erl"}, {"/src/app3.erl", "/include/app2.hrl"}, {"/src/app3.erl", "/src/app3_resolve.hrl"} ], Edges, FileStamps), ok. app_sort() -> [{doc, "once the digraph is complete, we can sort apps by dependency order"}]. app_sort(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), analyze_apps(G, AppNames, AppDir), AppPaths = [ {AppName, filename:join([AppDir, "apps", AppName])} || AppName <- AppNames ], ?assertEqual([lists:nth(2, AppNames), lists:nth(3, AppNames), lists:nth(1, AppNames)], rebar_compiler_dag:compile_order(G, AppPaths, ".erl", ".beam")), ok. propagate_include_app1a() -> [{doc, "changing the app1a header file propagates to its dependents"}]. propagate_include_app1a(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(1, AppNames), "src/app1_a.hrl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing [Stamp1, Stamp2] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", Stamp2}, {"/src/app1_trans.erl", Stamp1}, {"/src/app1_a.hrl", Stamp2}, {"/include/app1_b.hrl", Stamp1}, {"/src/app2.erl", Stamp1}, {"/include/app2.hrl", Stamp1}, {"/src/app3.erl", Stamp1}, {"/src/app3_resolve.hrl", Stamp1} ], matches(Matches, FileStamps), ok. propagate_include_app1b() -> [{doc, "changing the app1b header file propagates to its dependents"}]. propagate_include_app1b(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(1, AppNames), "include/app1_b.hrl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing [Stamp1, Stamp2, Stamp3] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", Stamp3}, {"/src/app1_trans.erl", Stamp1}, {"/src/app1_a.hrl", Stamp2}, {"/include/app1_b.hrl", Stamp3}, {"/src/app2.erl", Stamp1}, {"/include/app2.hrl", Stamp1}, {"/src/app3.erl", Stamp1}, {"/src/app3_resolve.hrl", Stamp1} ], matches(Matches, FileStamps), ok. propagate_include_app2() -> [{doc, "changing the app2 header file propagates to its dependents"}]. propagate_include_app2(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(2, AppNames), "include/app2.hrl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing [S1, S2, S3, S4] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", S4}, {"/src/app1_trans.erl", S1}, {"/src/app1_a.hrl", S2}, {"/include/app1_b.hrl", S3}, {"/src/app2.erl", S1}, {"/include/app2.hrl", S4}, {"/src/app3.erl", S4}, {"/src/app3_resolve.hrl", S1} ], matches(Matches, FileStamps), ok. propagate_behaviour() -> [{doc, "changing the behaviour file propagates to its dependents"}]. propagate_behaviour(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(2, AppNames), "src/app2.erl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing [S1, S2, S3, S4, S5] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", S5}, {"/src/app1_trans.erl", S1}, {"/src/app1_a.hrl", S2}, {"/include/app1_b.hrl", S3}, {"/src/app2.erl", S5}, {"/include/app2.hrl", S4}, {"/src/app3.erl", S5}, {"/src/app3_resolve.hrl", S1} ], matches(Matches, FileStamps), ok. propagate_app1_ptrans() -> [{doc, "changing an app-local parse transform propagates to its dependents"}]. propagate_app1_ptrans(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(1, AppNames), "src/app1_trans.erl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing [S1, S2, S3, S4, S5, S6] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", S6}, {"/src/app1_trans.erl", S6}, {"/src/app1_a.hrl", S2}, {"/include/app1_b.hrl", S3}, {"/src/app2.erl", S5}, {"/include/app2.hrl", S4}, {"/src/app3.erl", S5}, {"/src/app3_resolve.hrl", S1} ], matches(Matches, FileStamps), ok. propagate_app2_ptrans() -> [{doc, "changing an app-foreign parse transform propagates to its dependents"}]. propagate_app2_ptrans(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(3, AppNames), "src/app3.erl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing [S1, S2, S3, S4, S5, S6, S7] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", S7}, {"/src/app1_trans.erl", S6}, {"/src/app1_a.hrl", S2}, {"/include/app1_b.hrl", S3}, {"/src/app2.erl", S5}, {"/include/app2.hrl", S4}, {"/src/app3.erl", S7}, {"/src/app3_resolve.hrl", S1} ], matches(Matches, FileStamps), ok. propagate_app2_ptrans_hrl() -> %% the app-foreign ptrans' foreign hrl dep is tested by propagate_include_app2 as well [{doc, "changing an app-foreign parse transform's local hrl propagates to its dependents"}]. propagate_app2_ptrans_hrl(Config) -> AppDir = ?config(apps, Config), AppNames = ?config(app_names, Config), %% assume an empty graph G = digraph:new([acyclic]), next_second(), F = filename:join([AppDir, "apps", lists:nth(3, AppNames), "src/app3_resolve.hrl"]), bump_file(F), analyze_apps(G, AppNames, AppDir), FileStamps = [digraph:vertex(G, V) || V <- digraph:vertices(G)], %% All timestamps are the same since we just created the thing %% S1 and S7 are gone from the propagation now [S2, S3, S4, S5, S6, S8] = lists:usort([S || {_, S} <- FileStamps]), Matches = [ {"/src/app1.erl", S8}, {"/src/app1_trans.erl", S6}, {"/src/app1_a.hrl", S2}, {"/include/app1_b.hrl", S3}, {"/src/app2.erl", S5}, {"/include/app2.hrl", S4}, {"/src/app3.erl", S8}, {"/src/app3_resolve.hrl", S8} ], matches(Matches, FileStamps), ok. %%%%%%%%%%%%%%% %%% HELPERS %%% %%%%%%%%%%%%%%% apply_project(_BaseDir, _Names, []) -> ok; apply_project(BaseDir, Names, [{_AppName, []}|Rest]) -> apply_project(BaseDir, Names, Rest); apply_project(BaseDir, Names, [{AppName, [File|Files]}|Rest]) -> apply_file(BaseDir, Names, AppName, File), apply_project(BaseDir, Names, [{AppName, Files}|Rest]). apply_file(BaseDir, Names, App, {FileName, Contents}) -> AppName = proplists:get_value(App, Names), FilePath = filename:join([BaseDir, "apps", AppName, FileName]), ok = filelib:ensure_dir(FilePath), file:write_file(FilePath, apply_template(Contents, Names)). apply_template("", _) -> ""; apply_template("{{" ++ Text, Names) -> {Var, Rest} = parse_to_var(Text), App = list_to_atom(Var), proplists:get_value(App, Names) ++ apply_template(Rest, Names); apply_template([H|T], Names) -> [H|apply_template(T, Names)]. parse_to_var(Str) -> parse_to_var(Str, []). parse_to_var("}}"++Rest, Acc) -> {lists:reverse(Acc), Rest}; parse_to_var([H|T], Acc) -> parse_to_var(T, [H|Acc]). analyze_apps(G, AppNames, AppDir) -> populate_app(G, lists:nth(1, AppNames), AppNames, AppDir, ["app1.erl", "app1_trans.erl"]), populate_app(G, lists:nth(2, AppNames), AppNames, AppDir, ["app2.erl"]), populate_app(G, lists:nth(3, AppNames), AppNames, AppDir, ["app3.erl"]), rebar_compiler_dag:populate_deps(G, ".erl", [{".beam", "ebin/"}]), rebar_compiler_dag:propagate_stamps(G), %% manually clear the dirty bit for ease of validation digraph:del_vertex(G, '$r3_dirty_bit'). populate_app(G, Name, AppNames, AppDir, Sources) -> InDirs = [filename:join([AppDir, "apps", AppName, "src"]) || AppName <- AppNames] ++ [filename:join([AppDir, "apps", AppName, "include"]) || AppName <- AppNames], AbsSources = [filename:join([AppDir, "apps", Name, "src", Src]) || Src <- Sources], DepOpts = [{includes, [filename:join([AppDir, "apps", Name, "src"]), filename:join([AppDir, "apps", Name, "include"]) ]}, {include_libs, [filename:join([AppDir, "apps"])]} ], rebar_compiler_dag:populate_sources( G, rebar_compiler_erl, InDirs, AbsSources, DepOpts ). find_match(Regex, FileStamps) -> try [throw(F) || {F, _} <- FileStamps, re:run(F, Regex) =/= nomatch], undefined catch throw:F -> {ok, F} end. matches([], _) -> ok; matches([{R, Stamp} | T], FileStamps) -> case find_match(R, FileStamps) of {ok, F} -> ?assertEqual(Stamp, proplists:get_value(F, FileStamps)), matches(T, FileStamps); undefined -> ?assertEqual({R, Stamp}, FileStamps) end. edges([], _, _) -> ok; edges([{A,B}|T], Edges, Files) -> {ok, AbsA} = find_match(A, Files), {ok, AbsB} = find_match(B, Files), ?assert(lists:member({AbsA, AbsB}, Edges)), edges(T, Edges, Files). bump_file(F) -> {ok, Bin} = file:read_file(F), file:write_file(F, [Bin, "\n"]). next_second() -> %% Sleep until the next second. Rather than just doing a %% sleep(1000) call, sleep for the amount of time required %% to reach the next second as seen by the OS; this can save us %% a few hundred milliseconds per test by triggering shorter delays. {Mega, Sec, Micro} = os:timestamp(), Now = (Mega*1000000 + Sec)*1000 + round(Micro/1000), Ms = (trunc(Now / 1000)*1000 + 1000) - Now, %% add a 50ms for jitter since the exact amount sometimes causes failures timer:sleep(max(Ms+50, 1000)). rebar3-3.18.0/test/rebar_plugins_SUITE.erl0000644000232200023220000004074014164317745020640 0ustar debalancedebalance-module(rebar_plugins_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, all/0, compile_plugins/1, compile_global_plugins/1, complex_plugins/1, list/1, upgrade/1, upgrade_project_plugin/1, upgrade_no_args/1, sub_app_plugins/1, sub_app_plugin_overrides/1, project_plugins/1, use_checkout_plugins/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). end_per_testcase(_, _Config) -> catch meck:unload(). all() -> [compile_plugins, compile_global_plugins, complex_plugins, list, upgrade, upgrade_project_plugin, sub_app_plugins, sub_app_plugin_overrides, project_plugins, use_checkout_plugins]. %% Tests that compiling a project installs and compiles the plugins of deps compile_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), Plugins = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Plugins), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}]}, {config, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ list_to_atom(DepName) ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PluginName}, {dep, DepName}]} ). %% Tests that compiling a project installs and compiles the global plugins compile_global_plugins(Config) -> AppDir = ?config(apps, Config), GlobalDir = filename:join(AppDir, "global"), GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), mock_git_resource:mock([{deps, [{list_to_atom(PluginName), Vsn}, {list_to_atom(PluginName), Vsn2}, {{iolist_to_binary(DepName), iolist_to_binary(Vsn)}, []}]}]), rebar_test_utils:create_config(GlobalConfigDir, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}} ]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}} ]}, {plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}} ]}]), {ok, RConf} = file:consult(RConfFile), %% Runs global plugin install rebar3:init_config(), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {global_plugin, PluginName, Vsn}, {plugin, PluginName, Vsn2}, {dep, DepName}]} ), meck:unload(rebar_dir). %% Tests installing of plugin with transitive deps complex_plugins(Config) -> AppDir = ?config(apps, Config), meck:new(rebar_dir, [passthrough]), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), DepName2 = rebar_test_utils:create_random_name("dep2_"), DepName3 = rebar_test_utils:create_random_name("dep3_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), Deps = rebar_test_utils:expand_deps(git, [{PluginName, Vsn2, [{DepName2, Vsn, [{DepName3, Vsn, []}]}]} ,{DepName, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}} ]}, {plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}} ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PluginName, Vsn2}, {plugin, DepName2}, {plugin, DepName3}, {dep, DepName}]} ), meck:unload(rebar_dir). list(Config) -> rebar_test_utils:run_and_check( Config, [], ["plugins", "list"], {ok, []} ). upgrade(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]} ]), %% beam file to verify plugin is actually compiled PluginBeam = filename:join([AppDir, "_build", "default", "plugins", PkgName, "ebin", [PkgName, ".beam"]]), RConfFile = rebar_test_utils:create_config(AppDir, [{plugins, [list_to_atom(PkgName)]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName, <<"0.1.1">>}]} ), catch mock_pkg_resource:unmock(), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.3">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}, {upgrade, [PkgName]} ]), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["plugins", "upgrade", PkgName], {ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName, <<"0.1.3">>}]} ), rebar_test_utils:run_and_check( Config, RConf, ["plugins", "upgrade", "--all"], {ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName}]} ). upgrade_project_plugin(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{project_plugins, [list_to_atom(PkgName)]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PkgName, <<"0.1.1">>}]} ), catch mock_pkg_resource:unmock(), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.3">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}, {upgrade, [PkgName]} ]), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["plugins", "upgrade", PkgName], {ok, [{app, Name}, {plugin, PkgName, <<"0.1.3">>}]} ). upgrade_no_args(Config) -> try rebar_test_utils:run_and_check(Config, [], ["plugins", "upgrade"], return) catch {error, {rebar_prv_plugins_upgrade, no_arg}} -> ok end, ok. sub_app_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}, {{list_to_binary(PluginName), list_to_binary(Vsn)}, []}]}]), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(SubAppsDir, [{deps, [{list_to_binary(DepName), list_to_binary(Vsn)}]}, {plugins, [list_to_atom(PluginName)]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ list_to_atom(DepName) ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, DepName}, {plugin, PluginName}]} ). %% Tests that overrides in a dep that includes a plugin are applied to plugin fetching sub_app_plugin_overrides(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), Dep2Name = rebar_test_utils:create_random_name("dep2_"), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), Vsn2 = rebar_test_utils:create_random_vsn(), Deps = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, [{DepName, Vsn, []}]}, {DepName, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(Dep2Name), list_to_binary(Vsn)}, []}]}, {config, [{plugins, [{list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}}]}, %% Dep2 overrides the plugin's deps to have vsn2 of dep1 {overrides, [{override, list_to_atom(PluginName), [{deps, [{list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn2}}}]}]}]}]}]), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [{list_to_binary(Dep2Name), list_to_binary(Vsn)}]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, Dep2Name, Vsn}, {plugin, DepName, Vsn2}, {plugin, PluginName}]} ). %% Check that project plugins are first in providers even if they override defaults but that %% normal plugins do not project_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = "compile_plugin", PluginName2 = "release", Plugins = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, []}, {PluginName2, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Plugins), mock_git_resource:mock([{deps, SrcDeps}], create_plugin), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}]}, {config, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ list_to_atom(DepName) ]}, {project_plugins, [ {list_to_atom(PluginName2), {git, "http://site.com/user/"++PluginName2++".git", {tag, Vsn}}}]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. {ok, State} = rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PluginName}, {plugin, PluginName2}, {dep, DepName}]} ), %% Should have 2 release providers but only 1 compile provider Release = [P || P <- rebar_state:providers(State), providers:impl(P) =:= release, providers:namespace(P) =:= default], Compile = [P || P <- rebar_state:providers(State), providers:impl(P) =:= compile, providers:namespace(P) =:= default], ?assertEqual(length(Release), 2), ?assertEqual(length(Compile), 1). use_checkout_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PluginName = "checkedout", CheckoutsDir = filename:join(AppDir, "_checkouts/checkedout"), rebar_test_utils:create_plugin(CheckoutsDir, PluginName, "1.0.0", []), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, []}, {plugins, [list_to_atom(PluginName)]}]), {ok, RConf} = file:consult(RConfFile), %% Verify we can run the plugin ?assertMatch({ok, _}, rebar_test_utils:run_and_check( Config, RConf, ["checkedout"], {ok, []} )). rebar3-3.18.0/test/rebar_ct_SUITE.erl0000644000232200023220000020105414164317745017562 0ustar debalancedebalance-module(rebar_ct_SUITE). -export([all/0, groups/0, init_per_group/2, end_per_group/2]). -export([basic_app_default_dirs/1, basic_app_default_beams/1, basic_app_ct_macro/1, multi_app_default_dirs/1, multi_app_default_beams/1, multi_app_ct_macro/1, no_ct_suite/1, single_app_dir/1, single_extra_dir/1, single_unmanaged_dir/1, single_suite/1, single_extra_suite/1, single_unmanaged_suite/1, multi_suite/1, all_suite/1, single_dir_and_single_suite/1, suite_at_root/1, suite_at_app_root/1, data_dir_correct/1, cmd_label/1, cmd_config/1, cmd_spec/1, cmd_join_specs/1, cmd_allow_user_terms/1, cmd_logdir/1, cmd_logopts/1, cmd_verbosity/1, cmd_repeat/1, cmd_duration/1, cmd_until/1, cmd_force_stop/1, cmd_basic_html/1, cmd_stylesheet/1, cmd_decrypt_key/1, cmd_decrypt_file/1, cmd_abort_if_missing_suites/1, cmd_multiply_timetraps/1, cmd_scale_timetraps/1, cmd_create_priv_dir/1, cmd_include_dir/1, cmd_sys_config/1, cfg_opts/1, cfg_arbitrary_opts/1, cfg_cover_spec/1, cfg_atom_suites/1, cover_compiled/1, cover_export_name/1, misspecified_ct_opts/1, misspecified_ct_compile_opts/1, misspecified_ct_first_files/1, testspec/1, testspec_at_root/1, testspec_parse_error/1, cmd_vs_cfg_opts/1, single_testspec_in_ct_opts/1, compile_only/1]). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). all() -> [{group, basic_app}, {group, multi_app}, {group, dirs_and_suites}, {group, data_dirs}, {group, ct_opts}, {group, cover}, cfg_opts, cfg_arbitrary_opts, cfg_cover_spec, cfg_atom_suites, misspecified_ct_opts, misspecified_ct_compile_opts, misspecified_ct_first_files, testspec, testspec_at_root, testspec_parse_error, cmd_vs_cfg_opts, single_testspec_in_ct_opts, compile_only, no_ct_suite]. groups() -> [{basic_app, [], [basic_app_default_dirs, basic_app_default_beams, basic_app_ct_macro]}, {multi_app, [], [multi_app_default_dirs, multi_app_default_beams, multi_app_ct_macro]}, {dirs_and_suites, [], [single_app_dir, single_extra_dir, single_unmanaged_dir, single_suite, single_extra_suite, single_unmanaged_suite, multi_suite, all_suite, single_dir_and_single_suite, suite_at_root, suite_at_app_root]}, {data_dirs, [], [data_dir_correct]}, {ct_opts, [], [cmd_label, cmd_config, cmd_spec, cmd_join_specs, cmd_allow_user_terms, cmd_logdir, cmd_logopts, cmd_verbosity, cmd_repeat, cmd_duration, cmd_until, cmd_force_stop, cmd_basic_html, cmd_stylesheet, cmd_decrypt_key, cmd_decrypt_file, cmd_abort_if_missing_suites, cmd_multiply_timetraps, cmd_scale_timetraps, cmd_create_priv_dir, cmd_include_dir, cmd_sys_config]}, {cover, [], [cover_compiled, cover_export_name]}]. init_per_group(basic_app, Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name(atom_to_list(basic_app) ++ "_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Suite = filename:join([AppDir, "test", Name ++ "_SUITE.erl"]), ok = filelib:ensure_dir(Suite), ok = file:write_file(Suite, test_suite(Name)), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), Tests = rebar_prv_common_test:prepare_tests(State), {ok, NewState} = rebar_prv_common_test:compile(State, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), [{result, Opts}, {appnames, [Name]}, {compile_state, NewState}|C]; init_per_group(multi_app, Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_"), AppDir = ?config(apps, C), Name1 = rebar_test_utils:create_random_name(atom_to_list(multi_app) ++ "_"), Vsn1 = rebar_test_utils:create_random_vsn(), AppDir1 = filename:join([AppDir, "apps", Name1]), rebar_test_utils:create_app(AppDir1, Name1, Vsn1, [kernel, stdlib]), Suite1 = filename:join([AppDir1, "test", Name1 ++ "_SUITE.erl"]), ok = filelib:ensure_dir(Suite1), ok = file:write_file(Suite1, test_suite(Name1)), Name2 = rebar_test_utils:create_random_name(atom_to_list(multi_app) ++ "_"), Vsn2 = rebar_test_utils:create_random_vsn(), AppDir2 = filename:join([AppDir, "apps", Name2]), rebar_test_utils:create_app(AppDir2, Name2, Vsn2, [kernel, stdlib]), Suite2 = filename:join([AppDir2, "test", Name2 ++ "_SUITE.erl"]), ok = filelib:ensure_dir(Suite2), ok = file:write_file(Suite2, test_suite(Name2)), Suite3 = filename:join([AppDir, "test", "extras_SUITE.erl"]), ok = filelib:ensure_dir(Suite3), ok = file:write_file(Suite3, test_suite("extras")), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), Tests = rebar_prv_common_test:prepare_tests(State), {ok, NewState} = rebar_prv_common_test:compile(State, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), [{result, Opts}, {appnames, [Name1, Name2]}, {compile_state, NewState}|C]; init_per_group(dirs_and_suites, Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_"), AppDir = ?config(apps, C), Name1 = rebar_test_utils:create_random_name(atom_to_list(dirs_and_suites) ++ "_"), Vsn1 = rebar_test_utils:create_random_vsn(), AppDir1 = filename:join([AppDir, "apps", Name1]), rebar_test_utils:create_app(AppDir1, Name1, Vsn1, [kernel, stdlib]), Suite1 = filename:join([AppDir1, "test", Name1 ++ "_SUITE.erl"]), ok = filelib:ensure_dir(Suite1), ok = file:write_file(Suite1, test_suite(Name1)), Name2 = rebar_test_utils:create_random_name(atom_to_list(dir_and_suites) ++ "_"), Vsn2 = rebar_test_utils:create_random_vsn(), AppDir2 = filename:join([AppDir, "apps", Name2]), rebar_test_utils:create_app(AppDir2, Name2, Vsn2, [kernel, stdlib]), Suite2 = filename:join([AppDir2, "test", Name2 ++ "_SUITE.erl"]), ok = filelib:ensure_dir(Suite2), ok = file:write_file(Suite2, test_suite(Name2)), Suite3 = filename:join([AppDir, "test", "extras_SUITE.erl"]), ok = filelib:ensure_dir(Suite3), ok = file:write_file(Suite3, test_suite("extras")), Suite4 = filename:join([AppDir, "root_SUITE.erl"]), ok = file:write_file(Suite4, test_suite("root")), ok = file:write_file(filename:join([AppDir, "root_SUITE.hrl"]), <<>>), ok = filelib:ensure_dir(filename:join([AppDir, "root_SUITE_data", "dummy.txt"])), ok = file:write_file(filename:join([AppDir, "root_SUITE_data", "some_data.txt"]), <<>>), Suite5 = filename:join([AppDir, "apps", Name2, "app_root_SUITE.erl"]), ok = file:write_file(Suite5, test_suite("app_root")), ok = file:write_file(filename:join([AppDir, "apps", Name2, "app_root_SUITE.hrl"]), <<>>), ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "app_root_SUITE_data", "dummy.txt"])), ok = file:write_file(filename:join([AppDir, "apps", Name2, "app_root_SUITE_data", "some_data.txt"]), <<>>), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), [{s, State}, {appnames, [Name1, Name2]}|C]; init_per_group(ct_opts, Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_opts"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_opts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), [{result, State}, {name, Name}|C]; init_per_group(cover, Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_opts"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_opts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), [{result, State}, {name, Name}|C]; init_per_group(_, Config) -> Config. end_per_group(_Group, _Config) -> ok. basic_app_default_dirs(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(appnames, Config), Result = ?config(result, Config), Expect = filename:join([AppDir, "_build", "test", "lib", Name, "test"]), Dir = proplists:get_value(dir, Result), [Expect] = Dir. basic_app_default_beams(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(appnames, Config), File = filename:join([AppDir, "_build", "test", "lib", Name, "test", Name ++ "_SUITE.beam"]), true = filelib:is_file(File). basic_app_ct_macro(Config) -> State = ?config(compile_state, Config), [App] = rebar_state:project_apps(State), Opts = rebar_app_info:opts(App), ErlOpts = dict:fetch(erl_opts, Opts), true = lists:member({d, 'COMMON_TEST'}, ErlOpts). multi_app_default_dirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(appnames, Config), Result = ?config(result, Config), Expect1 = filename:absname(filename:join([AppDir, "_build", "test", "lib", Name1, "test"])), Expect2 = filename:absname(filename:join([AppDir, "_build", "test", "lib", Name2, "test"])), Expect3 = filename:absname(filename:join([AppDir, "_build", "test", "extras", "test"])), Dirs = proplists:get_value(dir, Result), true = (lists:sort([Expect1, Expect2, Expect3]) == lists:sort(Dirs)). multi_app_default_beams(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(appnames, Config), File1 = filename:join([AppDir, "_build", "test", "lib", Name1, "test", Name1 ++ "_SUITE.beam"]), File2 = filename:join([AppDir, "_build", "test", "lib", Name2, "test", Name2 ++ "_SUITE.beam"]), File3 = filename:join([AppDir, "_build", "test", "extras", "test", "extras_SUITE.beam"]), true = filelib:is_file(File1), true = filelib:is_file(File2), true = filelib:is_file(File3). multi_app_ct_macro(Config) -> State = ?config(compile_state, Config), Apps = rebar_state:project_apps(State), lists:foreach(fun(App) -> Opts = rebar_app_info:opts(App), ErlOpts = dict:fetch(erl_opts, Opts), true = lists:member({d, 'COMMON_TEST'}, ErlOpts) end, Apps). no_ct_suite(Config0) -> Config = rebar_test_utils:init_rebar_state(Config0), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("no_ct_suite_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), {ok, State} = rebar_test_utils:run_and_check(Config, [], ["as", "test", "lock"], return), {ok, Opts} = rebar_prv_common_test:prepare_tests(State), undefined = proplists:get_value(dir, Opts), undefined = proplists:get_value(suite, Opts), undefined = proplists:get_value(spec, Opts), ok. single_app_dir(Config) -> AppDir = ?config(apps, Config), [Name1, _Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--dir=" ++ filename:join([AppDir, "apps", Name1, "test"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([AppDir, "_build", "test", "lib", Name1, "test"]), Dir = proplists:get_value(dir, Opts), [Expect] = Dir. single_extra_dir(Config) -> AppDir = ?config(apps, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--dir=" ++ filename:join([AppDir, "test"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([AppDir, "_build", "test", "extras", "test"]), Dir = proplists:get_value(dir, Opts), [Expect] = Dir. single_unmanaged_dir(Config) -> PrivDir = ?config(priv_dir, Config), State = ?config(s, Config), Suite = filename:join([PrivDir, "unmanaged_dir", "unmanaged_dir_SUITE.erl"]), ok = filelib:ensure_dir(Suite), ok = file:write_file(Suite, test_suite("unmanaged_dir")), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--dir=" ++ filename:absname(filename:join([PrivDir, "unmanaged_dir"]))]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([PrivDir, "unmanaged_dir"]), Dir = proplists:get_value(dir, Opts), [Expect] = Dir. single_suite(Config) -> AppDir = ?config(apps, Config), [Name1, _Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "apps", Name1, "test", Name1 ++ "_SUITE"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([AppDir, "_build", "test", "lib", Name1, "test", Name1 ++ "_SUITE"]), Suite = proplists:get_value(suite, Opts), [Expect] = Suite. single_extra_suite(Config) -> AppDir = ?config(apps, Config), [_Name1, _Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "test", "extra_SUITE"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([AppDir, "_build", "test", "extras", "test", "extra_SUITE"]), Suite = proplists:get_value(suite, Opts), [Expect] = Suite. single_unmanaged_suite(Config) -> PrivDir = ?config(priv_dir, Config), [_Name1, _Name2] = ?config(appnames, Config), State = ?config(s, Config), Suite = filename:join([PrivDir, "unmanaged", "unmanaged_SUITE.erl"]), ok = filelib:ensure_dir(Suite), ok = file:write_file(Suite, test_suite("unmanaged")), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:absname(filename:join([PrivDir, "unmanaged", "unmanaged_SUITE"]))]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([PrivDir, "unmanaged", "unmanaged_SUITE"]), SuitePath = proplists:get_value(suite, Opts), [Expect] = SuitePath. multi_suite(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "apps", Name1, "test", Name1 ++ "_SUITE," ++ AppDir, "apps", Name2, "test", Name2 ++ "_SUITE"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect1 = filename:join([AppDir, "_build", "test", "lib", Name1, "test", Name1 ++ "_SUITE"]), Expect2 = filename:join([AppDir, "_build", "test", "lib", Name2, "test", Name2 ++ "_SUITE"]), Suites = proplists:get_value(suite, Opts), true = (lists:sort([Expect1, Expect2]) == lists:sort(Suites)). all_suite(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "apps", Name1, "test", Name1 ++ "_SUITE," ++ AppDir, "apps", Name2, "test", Name2 ++ "_SUITE," ++ AppDir, "test", "extra_SUITE"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect1 = filename:join([AppDir, "_build", "test", "lib", Name1, "test", Name1 ++ "_SUITE"]), Expect2 = filename:join([AppDir, "_build", "test", "lib", Name2, "test", Name2 ++ "_SUITE"]), Expect3 = filename:join([AppDir, "_build", "test", "extras", "test", "extra_SUITE"]), Suites = proplists:get_value(suite, Opts), true = (lists:sort([Expect1, Expect2, Expect3]) == lists:sort(Suites)). single_dir_and_single_suite(Config) -> AppDir = ?config(apps, Config), [_Name1, _Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--dir=" ++ filename:join([AppDir, "test"]), "--suite=extra_SUITE"]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Expect = filename:join([AppDir, "_build", "test", "extras", "test"]), Dir = proplists:get_value(dir, Opts), [Expect] = Dir, Suite = proplists:get_value(suite, Opts), ["extra_SUITE"] = Suite. suite_at_root(Config) -> AppDir = ?config(apps, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "root_SUITE"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Suite = proplists:get_value(suite, Opts), Expected = filename:join([AppDir, "_build", "test", "extras", "root_SUITE"]), [Expected] = Suite, TestHrl = filename:join([AppDir, "_build", "test", "extras", "root_SUITE.hrl"]), true = filelib:is_file(TestHrl), TestBeam = filename:join([AppDir, "_build", "test", "extras", "root_SUITE.beam"]), true = filelib:is_file(TestBeam), DataDir = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data"]), true = filelib:is_dir(DataDir), DataFile = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data", "some_data.txt"]), true = filelib:is_file(DataFile), %% Same test again, but using relative path to the suite from the %% project root {ok,Cwd} = file:get_cwd(), ok = file:set_cwd(AppDir), rebar_file_utils:rm_rf("_build"), {ok, GetOptResult2} = getopt:parse(GetOptSpec, ["--suite=" ++ "root_SUITE"]), State3 = rebar_state:command_parsed_args(State1, GetOptResult2), Tests2 = rebar_prv_common_test:prepare_tests(State3), {ok, NewState2} = rebar_prv_common_test:compile(State3, Tests2), {ok, T2} = Tests2, Opts2 = rebar_prv_common_test:translate_paths(NewState2, T2), ok = file:set_cwd(Cwd), Suite2 = proplists:get_value(suite, Opts2), [Expected] = Suite2, true = filelib:is_file(TestHrl), true = filelib:is_file(TestBeam), true = filelib:is_dir(DataDir), true = filelib:is_file(DataFile), ok. suite_at_app_root(Config) -> AppDir = ?config(apps, Config), [_Name1, Name2] = ?config(appnames, Config), State = ?config(s, Config), LibDirs = rebar_dir:lib_dirs(State), State1 = rebar_app_discover:do(State, LibDirs), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "apps", Name2, "app_root_SUITE"])]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(State2), {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), {ok, T} = Tests, Opts = rebar_prv_common_test:translate_paths(NewState, T), Suite = proplists:get_value(suite, Opts), Expected = filename:join([AppDir, "_build", "test", "lib", Name2, "app_root_SUITE"]), [Expected] = Suite, TestHrl = filename:join([AppDir, "_build", "test", "lib", Name2, "app_root_SUITE.hrl"]), true = filelib:is_file(TestHrl), TestBeam = filename:join([AppDir, "_build", "test", "lib", Name2, "app_root_SUITE.beam"]), true = filelib:is_file(TestBeam), DataDir = filename:join([AppDir, "_build", "test", "lib", Name2, "app_root_SUITE_data"]), true = filelib:is_dir(DataDir), DataFile = filename:join([AppDir, "_build", "test", "lib", Name2, "app_root_SUITE_data", "some_data.txt"]), true = filelib:is_file(DataFile), %% Same test again using relative path to the suite from the project root {ok,Cwd} = file:get_cwd(), ok = file:set_cwd(AppDir), rebar_file_utils:rm_rf("_build"), {ok, GetOptResult2} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join(["apps", Name2, "app_root_SUITE"])]), State3 = rebar_state:command_parsed_args(State1, GetOptResult2), Tests2 = rebar_prv_common_test:prepare_tests(State3), {ok, NewState2} = rebar_prv_common_test:compile(State3, Tests2), {ok, T2} = Tests2, Opts2 = rebar_prv_common_test:translate_paths(NewState2, T2), ok = file:set_cwd(Cwd), Suite2 = proplists:get_value(suite, Opts2), [Expected] = Suite2, true = filelib:is_file(TestHrl), true = filelib:is_file(TestBeam), true = filelib:is_dir(DataDir), true = filelib:is_file(DataFile), ok. %% this test probably only fails when this suite is run via rebar3 with the --cover flag data_dir_correct(Config) -> DataDir = ?config(data_dir, Config), Parts = filename:split(DataDir), ["rebar_ct_SUITE_data","test","rebar","lib",_,"_build"|_] = lists:reverse(Parts). cmd_label(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--label=this_is_a_label"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({label, "this_is_a_label"}, TestOpts). cmd_config(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--config=config/foo,config/bar,config/baz"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({config, ["config/foo", "config/bar", "config/baz"]}, TestOpts). cmd_spec(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--spec=foo.spec,bar.spec,baz.spec"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({spec, ["foo.spec", "bar.spec", "baz.spec"]}, TestOpts). cmd_join_specs(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--join_specs=true"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({join_specs, true}, TestOpts). cmd_allow_user_terms(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--allow_user_terms=true"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({allow_user_terms, true}, TestOpts). cmd_logdir(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--logdir=/tmp/ct_logs"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({logdir, "/tmp/ct_logs"}, TestOpts). cmd_logopts(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--logopts=no_src,no_nl"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({logopts, [no_src, no_nl]}, TestOpts). cmd_verbosity(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--verbosity=43"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({verbosity, 43}, TestOpts). cmd_repeat(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--repeat=3"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({repeat, 3}, TestOpts). cmd_duration(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--duration=001500"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({duration, "001500"}, TestOpts). cmd_until(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--until=001500"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({until, "001500"}, TestOpts). cmd_force_stop(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--force_stop=skip_rest"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({force_stop, skip_rest}, TestOpts). cmd_basic_html(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--basic_html"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({basic_html, true}, TestOpts). cmd_stylesheet(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--stylesheet=resources/tests.css"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({stylesheet, "resources/tests.css"}, TestOpts). cmd_decrypt_key(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--decrypt_key==ac467e30"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({decrypt_key, "=ac467e30"}, TestOpts). cmd_decrypt_file(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--decrypt_file=../keyfile.pem"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({decrypt_file, "../keyfile.pem"}, TestOpts). cmd_abort_if_missing_suites(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--abort_if_missing_suites"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({abort_if_missing_suites, true}, TestOpts). cmd_multiply_timetraps(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--multiply_timetraps=3"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({multiply_timetraps, 3}, TestOpts). cmd_scale_timetraps(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--scale_timetraps"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({scale_timetraps, true}, TestOpts). cmd_create_priv_dir(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--create_priv_dir=manual_per_tc"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(NewState), true = lists:member({create_priv_dir, manual_per_tc}, TestOpts). cmd_include_dir(Config) -> State = ?config(result, Config), AppDir = ?config(apps, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--include=foo/bar/baz,qux"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(NewState), {ok, _} = rebar_prv_common_test:compile(NewState, Tests), Name = ?config(name, Config), Beam = filename:join([AppDir, "_build", "test", "lib", Name, "ebin", Name ++ ".beam"]), {ok, {_, [{compile_info, Info}]}} = beam_lib:chunks(Beam, [compile_info]), CompileOpts = proplists:get_value(options, Info), true = lists:member({i, "foo/bar/baz"}, CompileOpts), true = lists:member({i, "qux"}, CompileOpts). cmd_sys_config(Config) -> State = ?config(result, Config), AppDir = ?config(apps, Config), Name = ?config(name, Config), AppName = list_to_atom(Name), {ok, _} = rebar_prv_common_test:prepare_tests(State), ?assertEqual(undefined, application:get_env(AppName, key)), CfgFile = filename:join([AppDir, "config", "cfg_sys.config"]), ok = filelib:ensure_dir(CfgFile), ok = file:write_file(CfgFile, cfg_sys_config_file(AppName)), OtherCfgFile = filename:join([AppDir, "config", "other.config"]), ok = filelib:ensure_dir(OtherCfgFile), ok = file:write_file(OtherCfgFile, other_sys_config_file(AppName)), RebarConfig = [{ct_opts, [{sys_config, CfgFile}]}], {ok, State1} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "test", "lock"], return), {ok, _} = rebar_prv_common_test:prepare_tests(State1), ?assertEqual({ok, cfg_value}, application:get_env(AppName, key)), ?assertEqual({ok, other_cfg_value}, application:get_env(AppName, other_key)), Providers = rebar_state:providers(State1), Namespace = rebar_state:namespace(State1), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), CmdFile = filename:join([AppDir, "config", "cmd_sys.config"]), ok = filelib:ensure_dir(CmdFile), ok = file:write_file(CmdFile, cmd_sys_config_file(AppName)), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--sys_config="++CmdFile]), State2 = rebar_state:command_parsed_args(State1, GetOptResult), {ok, _} = rebar_prv_common_test:prepare_tests(State2), ?assertEqual({ok ,cmd_value}, application:get_env(AppName, key)). cfg_opts(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_opts_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_opts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_opts, [{label, "this_is_a_label"}, {decrypt_file, "../keyfile.pem"}]}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(State), true = lists:member({label, "this_is_a_label"}, TestOpts), true = lists:member({decrypt_file, "../keyfile.pem"}, TestOpts). %% allow even nonsensical opts to be passed to ct_run for futureproofing cfg_arbitrary_opts(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_arbitrary_opts_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_arbitrary_opts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_opts, [{foo, 1}, {bar, 2}, {baz, 3}]}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(State), true = lists:member({foo, 1}, TestOpts), true = lists:member({bar, 2}, TestOpts), true = lists:member({baz, 3}, TestOpts). cfg_cover_spec(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_cover_spec_opts_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_cover_spec_opts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_opts, [Opt = {cover, "spec/foo.spec"}]}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(State), false = lists:member(Opt, TestOpts). cfg_atom_suites(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_atom_suites_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_atom_suites_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_opts, [{suite, [foo, bar, baz]}]}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(State), true = lists:member({suite, ["foo", "bar", "baz"]}, TestOpts). cover_compiled(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--cover"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(NewState), {ok, _} = rebar_prv_common_test:compile(NewState, Tests), Name = ?config(name, Config), Mod = list_to_atom(Name), {file, _} = cover:is_compiled(Mod). cover_export_name(Config) -> State = ?config(result, Config), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--cover", "--cover_export_name=export_name"]), NewState = rebar_state:command_parsed_args(State, GetOptResult), Tests = rebar_prv_common_test:prepare_tests(NewState), {ok, _} = rebar_prv_common_test:compile(NewState, Tests), rebar_prv_common_test:maybe_write_coverdata(NewState), Name = ?config(name, Config), Mod = list_to_atom(Name), {file, _} = cover:is_compiled(Mod), Dir = rebar_dir:profile_dir(rebar_state:opts(NewState), [default, test]), ct:pal("DIR ~s", [Dir]), true = filelib:is_file(filename:join([Dir, "cover", "export_name.coverdata"])). misspecified_ct_opts(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_atom_suites_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_atom_suites_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_opts, {basic_html, false}}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), {error, {rebar_prv_common_test, Error}} = rebar_prv_common_test:prepare_tests(State), {badconfig, {"Value `~p' of option `~p' must be a list", {{basic_html, false}, ct_opts}}} = Error. misspecified_ct_compile_opts(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_atom_suites_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_atom_suites_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_compile_opts, {d, whatever}}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), Tests = rebar_prv_common_test:prepare_tests(State), {error, {rebar_prv_common_test, Error}} = rebar_prv_common_test:compile(State, Tests), {badconfig, {"Value `~p' of option `~p' must be a list", {{d, whatever}, ct_compile_opts}}} = Error. misspecified_ct_first_files(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cfg_atom_suites_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cfg_atom_suites_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_first_files, some_file}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), Tests = rebar_prv_common_test:prepare_tests(State), {error, {rebar_prv_common_test, Error}} = rebar_prv_common_test:compile(State, Tests), {badconfig, {"Value `~p' of option `~p' must be a list", {some_file, ct_first_files}}} = Error. testspec(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_testspec_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_testspec_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Spec1 = filename:join([AppDir, "test", "some.spec"]), ok = filelib:ensure_dir(Spec1), ok = file:write_file(Spec1, "{suites,\".\",all}.\n"), Spec2 = filename:join([AppDir, "specs", "another.spec"]), ok = filelib:ensure_dir(Spec2), Suites2 = filename:join([AppDir,"suites","*"]), ok = filelib:ensure_dir(Suites2), ok = file:write_file(Spec2, "{suites,\"../suites/\",all}.\n"), {ok,Wd} = file:get_cwd(), ok = file:set_cwd(AppDir), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), %% Testspec in "test" directory {ok, GetOptResult1} = getopt:parse(GetOptSpec, ["--spec","test/some.spec"]), State1 = rebar_state:command_parsed_args(State, GetOptResult1), Tests1 = rebar_prv_common_test:prepare_tests(State1), {ok, NewState1} = rebar_prv_common_test:compile(State1, Tests1), {ok, T1} = Tests1, Opts1= rebar_prv_common_test:translate_paths(NewState1, T1), %% check that extra src dir is added [App1] = rebar_state:project_apps(NewState1), ["test"] = rebar_dir:extra_src_dirs(rebar_app_info:opts(App1)), %% check that path is translated ExpectedSpec1 = filename:join([AppDir, "_build", "test", "lib", Name, "test", "some.spec"]), [ExpectedSpec1] = proplists:get_value(spec, Opts1), %% Testspec in directory other than "test" {ok, GetOptResult2} = getopt:parse(GetOptSpec, ["--spec","specs/another.spec"]), State2 = rebar_state:command_parsed_args(State, GetOptResult2), Tests2 = {ok, T2} =rebar_prv_common_test:prepare_tests(State2), {ok, NewState2} = rebar_prv_common_test:compile(State2, Tests2), Opts2= rebar_prv_common_test:translate_paths(NewState2, T2), %% check that extra src dirs are added [App2] = rebar_state:project_apps(NewState2), ["specs","suites","test"] = lists:sort(rebar_dir:extra_src_dirs(rebar_app_info:opts(App2))), %% check that paths are translated ExpectedSpec2 = filename:join([AppDir, "_build", "test", "lib", Name, "specs", "another.spec"]), [ExpectedSpec2] = proplists:get_value(spec, Opts2), ok = file:set_cwd(Wd), ok. testspec_at_root(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_testspec_at_root_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_testspec_at_root_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir1 = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(AppDir1, Name, Vsn, [kernel, stdlib]), Spec1 = filename:join([AppDir, "root.spec"]), ok = filelib:ensure_dir(Spec1), ok = file:write_file(Spec1, "{suites,\"test\",all}."), Spec2 = filename:join([AppDir, "root1.spec"]), ok = file:write_file(Spec2, "{suites,\".\",all}."), Spec3 = filename:join([AppDir, "root2.spec"]), ok = file:write_file(Spec3, "{suites,\"suites\",all}."), Suite1 = filename:join(AppDir,"root_SUITE.erl"), ok = file:write_file(Suite1, test_suite("root")), Suite2 = filename:join([AppDir,"suites","test_SUITE.erl"]), ok = filelib:ensure_dir(Suite2), ok = file:write_file(Suite2, test_suite("test")), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), SpecArg1 = rebar_string:join([Spec1,Spec2,Spec3],","), {ok, GetOptResult1} = getopt:parse(GetOptSpec, ["--spec",SpecArg1]), State1 = rebar_state:command_parsed_args(State, GetOptResult1), Tests1 = rebar_prv_common_test:prepare_tests(State1), {ok, NewState1} = rebar_prv_common_test:compile(State1, Tests1), {ok, T1} = Tests1, Opts1= rebar_prv_common_test:translate_paths(NewState1, T1), %% check that extra src dir is added ExtraDir = filename:join([AppDir, "_build", "test", "extras"]), [ExtraDir,"suites","test"] = rebar_dir:extra_src_dirs(rebar_state:opts(NewState1)), %% check that path is translated ExpectedSpec1 = filename:join([AppDir, "_build", "test", "extras", "root.spec"]), ExpectedSpec2 = filename:join([AppDir, "_build", "test", "extras", "root1.spec"]), ExpectedSpec3 = filename:join([AppDir, "_build", "test", "extras", "root2.spec"]), [ExpectedSpec1,ExpectedSpec2,ExpectedSpec3] = lists:sort(proplists:get_value(spec, Opts1)), %% check that test specs are copied [ExpectedSpec1,ExpectedSpec2,ExpectedSpec3] = lists:sort(filelib:wildcard(filename:join([AppDir, "_build", "test", "extras", "*.spec"]))), %% Same test again, using relative path {ok,Cwd} = file:get_cwd(), ok = file:set_cwd(AppDir), ok = rebar_file_utils:rm_rf("_build"), SpecArg2 = "root.spec,root1.spec,root2.spec", {ok, GetOptResult2} = getopt:parse(GetOptSpec, ["--spec",SpecArg2]), State2 = rebar_state:command_parsed_args(State, GetOptResult2), Tests2 = rebar_prv_common_test:prepare_tests(State2), {ok, NewState2} = rebar_prv_common_test:compile(State2, Tests2), {ok, T2} = Tests2, Opts2= rebar_prv_common_test:translate_paths(NewState2, T2), %% check that extra src dir is added [ExtraDir,"suites","test"] = rebar_dir:extra_src_dirs(rebar_state:opts(NewState2)), %% check that path is translated [ExpectedSpec1,ExpectedSpec2,ExpectedSpec3] = lists:sort(proplists:get_value(spec, Opts2)), %% check that test specs are copied [ExpectedSpec1,ExpectedSpec2,ExpectedSpec3] = lists:sort(filelib:wildcard(filename:join([AppDir, "_build", "test", "extras", "root*.spec"]))), ok = file:set_cwd(Cwd), ok. testspec_parse_error(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_testspec_error"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_testspec_error"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Spec1 = filename:join([AppDir, "test", "nonexisting.spec"]), Spec2 = filename:join([AppDir, "test", "some.spec"]), ok = filelib:ensure_dir(Spec2), ok = file:write_file(Spec2, ".\n"), {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), %% Non existing testspec {ok, GetOptResult1} = getopt:parse(GetOptSpec, ["--spec",Spec1]), State1 = rebar_state:command_parsed_args(State, GetOptResult1), Tests1 = rebar_prv_common_test:prepare_tests(State1), {error, {rebar_prv_common_test, {error_reading_testspec, {Spec1,"no such file or directory"}}}} = rebar_prv_common_test:compile(State1, Tests1), %% Syntax error {ok, GetOptResult2} = getopt:parse(GetOptSpec, ["--spec",Spec2]), State2 = rebar_state:command_parsed_args(State, GetOptResult2), Tests2 = rebar_prv_common_test:prepare_tests(State2), {error, {rebar_prv_common_test, {error_reading_testspec, {Spec2,"1: syntax error before: '.'"}}}} = rebar_prv_common_test:compile(State2, Tests2), ok. cmd_vs_cfg_opts(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_cmd_vs_cfg_opts_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_cmd_vs_cfg_opts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{ct_opts, [{spec,"mytest.spec"}, {dir,"test"}, {suite,"some_SUITE"}, {group,"some_group"}, {testcase,"some_test"}]}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), {ok, TestOpts} = rebar_prv_common_test:prepare_tests(State), true = lists:member({spec, "mytest.spec"}, TestOpts), true = lists:member({dir, "test"}, TestOpts), true = lists:member({suite, "some_SUITE"}, TestOpts), true = lists:member({group, "some_group"}, TestOpts), true = lists:member({testcase, "some_test"}, TestOpts), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), {ok, GetOptResult1} = getopt:parse(GetOptSpec, ["--spec","test/some.spec"]), State1 = rebar_state:command_parsed_args(State, GetOptResult1), {ok, TestOpts1} = rebar_prv_common_test:prepare_tests(State1), true = lists:member({spec, ["test/some.spec"]}, TestOpts1), false = lists:keymember(dir, 1, TestOpts1), false = lists:keymember(suite, 1, TestOpts1), false = lists:keymember(group, 1, TestOpts1), false = lists:keymember(testcase, 1, TestOpts1), {ok, GetOptResult2} = getopt:parse(GetOptSpec, ["--suite","test/some_SUITE"]), State2 = rebar_state:command_parsed_args(State, GetOptResult2), {ok, TestOpts2} = rebar_prv_common_test:prepare_tests(State2), true = lists:member({suite, ["test/some_SUITE"]}, TestOpts2), false = lists:keymember(spec, 1, TestOpts2), false = lists:keymember(dir, 1, TestOpts2), false = lists:keymember(group, 1, TestOpts2), false = lists:keymember(testcase, 1, TestOpts2), {ok, GetOptResult3} = getopt:parse(GetOptSpec, ["--group","[g1,g2],g3"]), State3 = rebar_state:command_parsed_args(State, GetOptResult3), {ok, TestOpts3} = rebar_prv_common_test:prepare_tests(State3), true = lists:member({group, [[g1,g2],g3]}, TestOpts3), false = lists:keymember(suite, 1, TestOpts3), false = lists:keymember(spec, 1, TestOpts3), false = lists:keymember(dir, 1, TestOpts3), false = lists:keymember(testcase, 1, TestOpts3), ok. single_testspec_in_ct_opts(Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_testspec_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name("ct_testspec_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Spec = filename:join([AppDir, "test", "some.spec"]), ok = filelib:ensure_dir(Spec), ok = file:write_file(Spec, "{suites,\".\",all}.\n"), {ok,Wd} = file:get_cwd(), ok = file:set_cwd(AppDir), RebarConfig = [{ct_opts, [{spec,"test/some.spec"}]}], {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return), Providers = rebar_state:providers(State), Namespace = rebar_state:namespace(State), CommandProvider = providers:get_provider(ct, Providers, Namespace), GetOptSpec = providers:opts(CommandProvider), %% Testspec in "test" directory {ok, GetOptResult1} = getopt:parse(GetOptSpec, []), State1 = rebar_state:command_parsed_args(State, GetOptResult1), Tests1 = rebar_prv_common_test:prepare_tests(State1), {ok, T1} = Tests1, "test/some.spec" = proplists:get_value(spec,T1), {ok, _NewState} = rebar_prv_common_test:compile(State1, Tests1), ok = file:set_cwd(Wd), ok. compile_only(Config) -> C = rebar_test_utils:init_rebar_state(Config, "compile_only_"), AppDir = ?config(apps, C), Name = rebar_test_utils:create_random_name(atom_to_list(basic_app) ++ "_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Suite = filename:join([AppDir, "test", Name ++ "_SUITE.erl"]), ok = filelib:ensure_dir(Suite), ok = file:write_file(Suite, test_suite(Name)), {ok, _State} = rebar_test_utils:run_and_check(C, [], ["ct", "--compile_only"], {ok, [{app,Name}], "test"}). %% helper for generating test data test_suite(Name) -> io_lib:format("-module(~ts_SUITE).\n" "-compile(export_all).\n" "all() -> [some_test].\n" "some_test(_) -> ok.\n", [Name]). cmd_sys_config_file(AppName) -> io_lib:format("[{~ts, [{key, cmd_value}]}].", [AppName]). cfg_sys_config_file(AppName) -> io_lib:format("[{~ts, [{key, cfg_value}]}, \"config/other\"].", [AppName]). other_sys_config_file(AppName) -> io_lib:format("[{~ts, [{other_key, other_cfg_value}]}].", [AppName]). rebar3-3.18.0/test/rebar_dist_utils_SUITE.erl0000644000232200023220000001041414164317745021335 0ustar debalancedebalance%%% This suite currently only tests for options parsing since we do %%% not know if epmd will be running to actually boot nodes. -module(rebar_dist_utils_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). all() -> [from_config, from_cli, overlap, from_config_profile]. init_per_testcase(_, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name]), Name, Vsn, [kernel, stdlib]), Config. end_per_testcase(_, _) -> ok. from_config(Config) -> ShortConfig = [{dist_node, [{sname, 'a@localhost'}, {setcookie, abc}]}], LongConfig = [{dist_node, [{name, 'a@localhost.x'}, {setcookie, abc}]}], BothConfig = [{dist_node, [{sname, 'a@localhost'}, {name, 'a@localhost.x'}, {setcookie,abc}]}], NoConfig = [], CookieConfig = [{dist_node, [{setcookie, def}]}], NoCookie = [{dist_node, [{sname, 'a@localhost'}]}], {ok, State0} = rebar_test_utils:run_and_check(Config, ShortConfig, ["version"], return), {undefined, 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State0), {ok, State1} = rebar_test_utils:run_and_check(Config, LongConfig, ["version"], return), {'a@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State1), %% only support the first name found, side-effect of wanting profile support {ok, State2} = rebar_test_utils:run_and_check(Config, BothConfig, ["version"], return), {undefined, 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State2), {ok, State3} = rebar_test_utils:run_and_check(Config, NoConfig, ["version"], return), {undefined, undefined, []} = rebar_dist_utils:find_options(State3), {ok, State4} = rebar_test_utils:run_and_check(Config, CookieConfig, ["version"], return), {undefined, undefined, [{setcookie, def}]} = rebar_dist_utils:find_options(State4), {ok, State5} = rebar_test_utils:run_and_check(Config, NoCookie, ["version"], return), {undefined, 'a@localhost', []} = rebar_dist_utils:find_options(State5), ok. from_cli(Config) -> {ok, State0} = rebar_test_utils:run_and_check(Config, [], ["version"], return), {undefined, undefined, []} = rebar_dist_utils:find_options(State0), State1 = rebar_state:command_parsed_args(State0, {[{sname, 'a@localhost'}, {setcookie,abc}], []}), {undefined, 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State1), State2 = rebar_state:command_parsed_args(State0, {[{name, 'a@localhost.x'}, {setcookie,abc}], []}), {'a@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State2), State3 = rebar_state:command_parsed_args(State0, {[{sname, 'a@localhost'}, {name, 'a@localhost.x'}, {setcookie,abc}], []}), {'a@localhost.x', 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State3), State4 = rebar_state:command_parsed_args(State0, {[{setcookie,def}], []}), {undefined, undefined, [{setcookie, def}]} = rebar_dist_utils:find_options(State4), State5 = rebar_state:command_parsed_args(State0, {[{sname, 'a@localhost'}], []}), {undefined, 'a@localhost', []} = rebar_dist_utils:find_options(State5), ok. overlap(Config) -> %% Make sure that CLI config takes over rebar config without clash for names, though %% cookies can pass through RebarConfig = [{dist_node, [{sname, 'a@localhost'}, {setcookie, abc}]}], {ok, State0} = rebar_test_utils:run_and_check(Config, RebarConfig, ["version"], return), State1 = rebar_state:command_parsed_args(State0, {[{name, 'b@localhost.x'}], []}), {'b@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State1), ok. from_config_profile(Config) -> %% running as a profile does not create name clashes RebarConfig = [{dist_node, [{sname, 'a@localhost'}, {setcookie, abc}]}, {profiles, [ {fake, [{dist_node, [{name, 'a@localhost.x'}]}]} ]}], {ok, State0} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as","fake","version"], return), {'a@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State0), ok. rebar3-3.18.0/test/rebar_release_SUITE.erl0000644000232200023220000004076414164317745020605 0ustar debalancedebalance-module(rebar_release_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [release, config_file, dev_mode_release, profile_dev_mode_override_release, tar, profile_ordering_sys_config_extend, profile_ordering_sys_config_extend_3_tuple_merge, extend_release, user_output_dir, profile_overlays, profile_overlay_merge, overlay_vars]. init_per_testcase(Case, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0), Name = rebar_test_utils:create_random_name(atom_to_list(Case)), AppDir = ?config(apps, Config), application:load(rebar), ok = ec_file:mkdir_p(AppDir), State = rebar_state:new([{base_dir, filename:join([AppDir, "_build"])}]), rebar_test_utils:create_app(AppDir, Name, "1.0.0", [kernel, stdlib]), [{name, Name}, {apps, AppDir}, {state, State} | Config]. end_per_testcase(_, Config) -> meck:unload(), Config. release(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {lib_dirs, [AppDir]}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["release"], {ok, [{release, list_to_atom(Name), Vsn, false}]} ). config_file(Config) -> AppDir = ?config(apps, Config), Name = list_to_atom(?config(name, Config)), %% Release build fails if no relx config exists ?assertError({error, {relx, no_releases_in_system}}, rebar_test_utils:run_and_check(Config, [], ["release"], result)), %% Write relx.config RelxConfig = fun(Vsn) -> [{release, {Name, Vsn}, [Name]}, {lib_dirs, [AppDir]}] end, rebar_test_utils:create_config(AppDir, "relx.config", RelxConfig("1.0.0")), %% Release is built with relx.config (default) rebar_test_utils:run_and_check(Config, [], ["release"], {ok, [{release, Name, "1.0.0", false}]}), %% Release is built with custom.config (--config) rebar_test_utils:create_config(AppDir, "custom.config", RelxConfig("2.0.0")), rebar_test_utils:run_and_check(Config, [], ["release", "--config", "custom.config"], {ok, [{release, Name, "2.0.0", false}]}), %% Fail due to non-existing file ?assertError({error, {rebar_relx, {config_file, "no_exist.config", enoent}}}, rebar_test_utils:run_and_check(Config, [], ["release", "--config", "no_exist.config"], result)), %% Fail due to non-existing file, even with relx config in rebar.config ?assertError({error, {rebar_relx, {config_file, "no_exist.config", enoent}}}, rebar_test_utils:run_and_check(Config, [{relx, RelxConfig("3.0.0")}], ["release", "--config", "no_exist.config"], result)), %% rebar.config overrides relx.config if both exist rebar_test_utils:run_and_check(Config, [{relx, RelxConfig("4.0.0")}], ["release"], {ok, [{release, Name, "4.0.0", false}]}). dev_mode_release(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {lib_dirs, [AppDir]}, {dev_mode, true}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["release"], {ok, [{release, list_to_atom(Name), Vsn, true}]} ). profile_dev_mode_override_release(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {lib_dirs, [AppDir]}, {dev_mode, true}]}, {profiles, [{ct, [{relx, [{dev_mode, false}]}]}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "ct", "release"], {ok, [{release, list_to_atom(Name), Vsn, false}]} ). tar(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {lib_dirs, [AppDir]}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["tar"], {ok, [{release, list_to_atom(Name), Vsn, false}, {tar, Name, Vsn}]} ). %% Test that the order of release config args is not lost. If it is extend would fail. extend_release(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {release, {extended, Vsn, {extend, list_to_atom(Name)}}, []}, {lib_dirs, [AppDir]}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["release", "-n", "extended"], {ok, [{release, extended, Vsn, false}]} ). %% Ensure proper ordering of sys_config and extended releases in profiles profile_ordering_sys_config_extend(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", TestSysConfig = filename:join(AppDir, "test.config"), OtherSysConfig = filename:join(AppDir, "other.config"), ok = file:write_file(TestSysConfig, "[]."), ok = file:write_file(OtherSysConfig, "[{some, content}]."), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {sys_config, OtherSysConfig}, {lib_dirs, [AppDir]}]}, {profiles, [{extended, [{relx, [ {sys_config, TestSysConfig}]}]}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "extended", "release"], {ok, [{release, list_to_atom(Name), Vsn, false}]} ), ReleaseDir = filename:join([AppDir, "./_build/extended/rel/", Name, "releases", Vsn]), {ok, [[]]} = file:consult(filename:join(ReleaseDir, "sys.config")). %% test that tup_umerge works with tuples of different sizes profile_ordering_sys_config_extend_3_tuple_merge(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", TestSysConfig = filename:join(AppDir, "test.config"), OtherSysConfig = filename:join(AppDir, "other.config"), ok = file:write_file(TestSysConfig, "[]."), ok = file:write_file(OtherSysConfig, "[{some, content}]."), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {sys_config, OtherSysConfig}, {lib_dirs, [AppDir]}]}, {profiles, [{extended, [{relx, [ {release, {extended, Vsn, {extend, list_to_atom(Name)}}, []}, {sys_config, TestSysConfig}]}]}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "extended", "release", "-n", Name], {ok, [{release, list_to_atom(Name), Vsn, false}]} ), ReleaseDir = filename:join([AppDir, "./_build/extended/rel/", Name, "releases", Vsn]), {ok, [[]]} = file:consult(filename:join(ReleaseDir, "sys.config")). user_output_dir(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), ReleaseDir = filename:join(AppDir, "./_rel"), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {lib_dirs, [AppDir]}, {dev_mode, true}]}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["release", "-o", ReleaseDir], {ok, []} ), ?assertNotMatch([], filelib:wildcard(filename:join([ReleaseDir, Name, "releases", Vsn, "*"]))). profile_overlays(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", file:write_file(filename:join(AppDir, "dev.file"), "dev.\n"), file:write_file(filename:join(AppDir, "prod.file"), "prod.\n"), file:write_file(filename:join(AppDir, "dev.vars"), "{env, \"dev\"}.\n"), file:write_file(filename:join(AppDir, "prod.vars"), "{env, \"prod\"}.\n"), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, %% Paths are relative, but to cwd in relx, not the project root as %% seen by rebar3 (in non-test cases, they're the same). %% Work around by being explicit. [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {overlay_vars, filename:join(AppDir, "dev.vars")}, {overlay, [{mkdir, "randomdir"}, {copy, filename:join(AppDir,"./dev.file"), "profile.file"}, {copy, filename:join(AppDir,"./dev.file"), "{{env}}.file"}, {chmod, 8#00770, "profile.file"}]}, {lib_dirs, [AppDir]}]}, {profiles, [{prod, [{relx, [ {debug_info, keep}, {overlay_vars, filename:join(AppDir, "prod.vars")}, {overlay, [{mkdir, "otherrandomdir"}, {copy, filename:join(AppDir, "./prod.file"), "{{env}}.file"}, {copy, filename:join(AppDir, "./prod.file"), "profile.file"}, {chmod, 8#00770, "profile.file"}]} ]}] }]} ])), ReleaseDir = filename:join([AppDir, "./_build/prod/rel/", Name]), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "prod", "release"], {ok, [{release, list_to_atom(Name), Vsn, false}, {dir, filename:join(ReleaseDir, "otherrandomdir")}, {dir, filename:join(ReleaseDir, "randomdir")}]} ), ?assertMatch({ok,[prod]}, file:consult(filename:join(ReleaseDir, "profile.file"))), ?assertMatch({ok,[prod]}, file:consult(filename:join(ReleaseDir, "prod.file"))), ok. profile_overlay_merge (_Config) -> % when profile and relx overlays both exist, the profile overlays should be % first, then the relx overlays, all the rest of the config should come % after, rebar_relx:merge_overlays/1 should do this. RelxOverlay = [{mkdir, "1_from_relx"}, {mkdir, "2_from_relx"}], ProfileOverlay = [{mkdir, "0_from_other_profile"}], OtherConfig = [{other1, config}, {other2, config}], % test with no overlays ?assertEqual([{overlay,[]}] ++ OtherConfig, rebar_relx:merge_overlays(OtherConfig)), % test with relx only, just move overlays to the top RelxOnly = OtherConfig ++ [{overlay, RelxOverlay}], ?assertEqual([{overlay, RelxOverlay}]++OtherConfig, rebar_relx:merge_overlays(RelxOnly)), % now test with a profile (profiles end up after relx overlays ProfilesToMerge = OtherConfig ++ [{overlay, RelxOverlay}, {overlay, ProfileOverlay}], ?assertEqual([{overlay, ProfileOverlay ++ RelxOverlay}] ++ OtherConfig, rebar_relx:merge_overlays(ProfilesToMerge)). overlay_vars(Config) -> AppDir = ?config(apps, Config), Name = ?config(name, Config), Vsn = "1.0.0", {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{relx, [{release, {list_to_atom(Name), Vsn}, [list_to_atom(Name)]}, {overlay, [ {template, filename:join([AppDir, "config/app.config"]), "releases/{{release_version}}/sys.config"} ]}, {overlay_vars, filename:join([AppDir, "config/vars.config"])}, {lib_dirs, [AppDir]}]} ])), ok = filelib:ensure_dir(filename:join([AppDir, "config", "dummy"])), OverlayVars = [{var_int, 1}, {var_string, "\"test\""}, {var_bin_string, "<<\"test\">>"}, {var_tuple, "{t, ['atom']}"}, {var_list, "[a, b, c, 'd']"}, {var_bin, "<<23, 24, 25>>"}], rebar_test_utils:create_config(AppDir, filename:join([AppDir, "config", "vars.config"]), OverlayVars), AppConfig = [[{var_int, {{var_int}}}, {var_string, {{{var_string}}}}, {var_bin_string, {{{var_bin_string}}}}, {var_tuple, {{{var_tuple}}}}, {var_list, {{{var_list}}}}, {var_bin, {{{var_bin}}}}, {var_profile_string, {{profile_string}}}]], % this comes from `rebar3' rebar_test_utils:create_config(AppDir, filename:join([AppDir, "config", "app.config"]), AppConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["release"], {ok, [{release, list_to_atom(Name), Vsn, false}]}), %% now consult the sys.config file to make sure that is has the expected %% format ExpectedSysconfig = [{var_int, 1}, {var_string, "test"}, {var_bin_string, <<"test">>}, {var_tuple, {t, ['atom']}}, {var_list, [a, b, c, 'd']}, {var_bin, <<23, 24, 25>>}, {var_profile_string, 'default'}], {ok, [ExpectedSysconfig]} = file:consult(filename:join([AppDir, "_build/default/rel", Name, "releases", Vsn, "sys.config"])). rebar3-3.18.0/test/rebar_pkg_repos_SUITE.erl0000644000232200023220000005445514164317745021160 0ustar debalancedebalance%% Test suite for the handling hexpm repo configurations -module(rebar_pkg_repos_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include("rebar.hrl"). all() -> [default_repo, repo_merging, repo_replacing, auth_read_write_read, auth_remove_from_config, auth_merging, auth_config_errors, organization_merging, {group, resolve_version}]. groups() -> [{resolve_version, [use_first_repo_match, use_exact_with_hash, fail_repo_update, ignore_match_in_excluded_repo, optional_prereleases]}]. init_per_group(resolve_version, Config) -> Repo1 = <<"test-repo-1">>, Repo2 = <<"test-repo-2">>, Repo3 = <<"test-repo-3">>, Hexpm = <<"hexpm">>, Repos = [Repo1, Repo2, Repo3, Hexpm], Deps = [{"A", "0.1.1", <<"inner checksum">>, <<"good outer checksum">>, Repo1, false}, {"A", "0.1.1", <<"inner checksum">>, <<"good outer checksum">>, Repo2, false}, {"B", "1.0.0", Repo1, false}, {"B", "2.0.0", Repo2, false}, {"B", "1.4.0", Repo3, false}, {"B", "1.4.3", Hexpm, false}, {"B", "1.4.6", Hexpm, #{reason => 'RETIRED_INVALID'}}, {"B", "1.5.0", Hexpm, false}, {"B", "1.5.6-rc.0", Hexpm, true}, {"C", "1.3.1", <<"inner checksum">>, <<"bad outer checksum">>, Repo1, false}, {"C", "1.3.1", <<"inner checksum">>, <<"good outer checksum">>, Repo2, false}], [{deps, Deps}, {repos, Repos} | Config]; init_per_group(_, Config) -> Config. end_per_group(_, _) -> ok. init_per_testcase(use_first_repo_match, Config) -> Deps = ?config(deps, Config), Repos = ?config(repos, Config), State = setup_deps_and_repos(Deps, Repos), meck:new(rebar_packages, [passthrough, no_link]), %% fail when the first repo is updated since it doesn't have a matching package %% should continue anyway meck:expect(rebar_packages, update_package, fun(_, _, _State) -> ok end), meck:expect(rebar_packages, verify_table, fun(_State) -> true end), [{state, State} | Config]; init_per_testcase(use_exact_with_hash, Config) -> Deps = ?config(deps, Config), Repos = ?config(repos, Config), State = setup_deps_and_repos(Deps, Repos), meck:new(rebar_packages, [passthrough, no_link]), %% fail when the first repo is updated since it doesn't have a matching package %% should continue anyway meck:expect(rebar_packages, update_package, fun(_, _, _State) -> ok end), meck:expect(rebar_packages, verify_table, fun(_State) -> true end), [{state, State} | Config]; init_per_testcase(fail_repo_update, Config) -> Deps = ?config(deps, Config), Repos = ?config(repos, Config), State = setup_deps_and_repos(Deps, Repos), meck:new(rebar_packages, [passthrough, no_link]), %% fail when the first repo is updated since it doesn't have a matching package %% should continue anyway [Repo1 | _] = Repos, meck:expect(rebar_packages, update_package, fun(_, #{name := Repo}, _State) when Repo =:= Repo1 -> fail; (_, _, _State) -> ok end), meck:expect(rebar_packages, verify_table, fun(_State) -> true end), [{state, State} | Config]; init_per_testcase(ignore_match_in_excluded_repo, Config) -> Deps = ?config(deps, Config), Repos = [Repo1, _, Repo3 | _] = ?config(repos, Config), %% drop repo1 and repo2 from the repos to be used by the pkg resource State = setup_deps_and_repos(Deps, [R || R <- Repos, R =/= Repo3, R =/= Repo1]), meck:new(rebar_packages, [passthrough, no_link]), %% fail when the first repo is updated since it doesn't have a matching package %% should continue anyway [_, _, Repo3 | _] = Repos, meck:expect(rebar_packages, update_package, fun(_, _, _State) -> ok end), meck:expect(rebar_packages, verify_table, fun(_State) -> true end), [{state, State} | Config]; init_per_testcase(optional_prereleases, Config) -> Deps = ?config(deps, Config), Repos = ?config(repos, Config), State = setup_deps_and_repos(Deps, Repos), meck:new(rebar_packages, [passthrough, no_link]), meck:expect(rebar_packages, update_package, fun(_, _, _State) -> ok end), meck:expect(rebar_packages, verify_table, fun(_State) -> true end), [{state, State} | Config]; init_per_testcase(Case, Config) when Case =:= auth_merging ; Case =:= auth_config_errors ; Case =:= auth_remove_from_config ; Case =:= auth_read_write_read -> meck:new(file, [passthrough, no_link, unstick]), meck:new(rebar_packages, [passthrough, no_link]), Config; init_per_testcase(organization_merging, Config) -> meck:new(file, [passthrough, no_link, unstick]), meck:new(rebar_packages, [passthrough, no_link]), Config; init_per_testcase(_, Config) -> Config. end_per_testcase(Case, _Config) when Case =:= auth_merging ; Case =:= auth_config_errors ; Case =:= organization_merging ; Case =:= auth_remove_from_config ; Case =:= auth_read_write_read -> meck:unload(file), meck:unload(rebar_packages); end_per_testcase(Case, _Config) when Case =:= use_first_repo_match ; Case =:= use_exact_with_hash ; Case =:= fail_repo_update ; Case =:= ignore_match_in_excluded_repo ; Case =:= optional_prereleases -> meck:unload(rebar_packages); end_per_testcase(_, _) -> ok. default_repo(_Config) -> Repo1 = #{name => <<"hexpm">>, api_key => <<"asdf">>}, MergedRepos = rebar_hex_repos:repos([{repos, [Repo1]}]), ?assertMatch([#{name := <<"hexpm">>, api_key := <<"asdf">>, api_url := <<"https://hex.pm/api">>}], MergedRepos). repo_merging(_Config) -> Repo1 = #{name => <<"repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, Result = rebar_hex_repos:merge_repos([Repo1, Repo2, #{name => <<"repo-2">>, api_url => <<"repo-2/api">>, repo_url => <<"bad url">>, repo_verify => true}, #{name => <<"repo-1">>, api_url => <<"bad url">>, repo_verify => true}, #{name => <<"repo-2">>, api_url => <<"repo-2/api-2">>, repo_url => <<"other/repo">>}]), ?assertMatch([#{name := <<"repo-1">>, api_url := <<"repo-1/api">>, repo_verify := true}, #{name := <<"repo-2">>, api_url := <<"repo-2/api">>, repo_url := <<"repo-2/repo">>, repo_verify := false}], Result). repo_replacing(_Config) -> Repo1 = #{name => <<"repo-1">>, repo_name => <<"repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"repo-2">>, repo_name => <<"repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, ?assertMatch([Repo1, Repo2, #{name := <<"hexpm">>}], rebar_hex_repos:repos([{repos, [Repo1]}, {repos, [Repo2]}])), %% use of replace is ignored if found in later entries than the first ?assertMatch([Repo1, Repo2, #{name := <<"hexpm">>}], rebar_hex_repos:repos([{repos, [Repo1]}, {repos, replace, [Repo2]}])), ?assertMatch([Repo1], rebar_hex_repos:repos([{repos, replace, [Repo1]}, {repos, [Repo2]}])). auth_merging(_Config) -> Repo1 = #{name => <<"repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]), meck:expect(file, consult, fun(_) -> {ok, [#{<<"repo-1">> => #{read_key => <<"read key">>, write_key => <<"write key">>}, <<"repo-2">> => #{read_key => <<"read key 2">>, repos_key => <<"repos key 2">>, write_key => <<"write key 2">>}, <<"hexpm">> => #{write_key => <<"write key hexpm">>}}]} end), ?assertMatch({ok, #resource{state=#{repos := [#{name := <<"repo-1">>, read_key := <<"read key">>, write_key := <<"write key">>}, #{name := <<"repo-2">>, read_key := <<"read key 2">>, repos_key := <<"repos key 2">>, write_key := <<"write key 2">>}, #{name := <<"hexpm">>, write_key := <<"write key hexpm">>}]}}}, rebar_pkg_resource:init(pkg, State)), ok. auth_config_errors(_Config) -> Repo1 = #{name => <<"repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]), meck:expect(file, consult, fun(_) -> {error, {3,erl_parse,["syntax error before: ","'=>'"]}} end), ?assertThrow(rebar_abort, rebar_pkg_resource:init(pkg, State)), meck:expect(file, consult, fun(_) -> {error, enoent} end), {ok, #resource{state=#{ repos := [ UpdatedRepo1, UpdatedRepo2, DefaultRepo ]}}} = rebar_pkg_resource:init(pkg, State), ?assertEqual(undefined, maps:get(write_key, UpdatedRepo1, undefined)), ?assertEqual(undefined, maps:get(read_key, UpdatedRepo1, undefined)), ?assertEqual(undefined, maps:get(repos_key, UpdatedRepo1, undefined)), ?assertEqual(undefined, maps:get(write_key, UpdatedRepo2, undefined)), ?assertEqual(undefined, maps:get(repos_key, UpdatedRepo2, undefined)), ?assertEqual(undefined, maps:get(read_key, UpdatedRepo2, undefined)), ?assertEqual(undefined, maps:get(write_key, DefaultRepo, undefined)), ok. auth_read_write_read(_Config) -> Repo1 = #{name => <<"hexpm:repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"hexpm:repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]), meck:expect(file, consult, fun(_) -> {ok, [#{<<"hexpm:repo-1">> => #{read_key => <<"read key">>}, <<"hexpm:repo-2">> => #{read_key => <<"read key 2">>, repos_key => <<"repos key 2">>, write_key => <<"write key 2">>}}]} end), meck:expect(file, write_file, fun(_File, CfgBin, _) -> case binary:match(CfgBin, <<"foo">>) of nomatch -> Err = "expected auth config binary with key <<\"foo\">>", meck:exception(error, {expected, Err}); _ -> ok end end), rebar_hex_repos:update_auth_config(#{<<"foo">> => <<200>>}, State). auth_remove_from_config(_Config) -> Repo1 = #{name => <<"hexpm:repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"hexpm:repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]), meck:expect(file, consult, fun(_) -> {ok, [#{<<"hexpm:repo-1">> => #{read_key => <<"read key">>}, <<"hexpm:repo-2">> => #{read_key => <<"read key 2">>, repos_key => <<"repos key 2">>, write_key => <<"write key 2">>}}]} end), meck:expect(file, write_file, fun(_File, CfgBin, _) -> case binary:match(CfgBin, <<"hexpm:repo-1">>) of nomatch -> ok; _ -> Err = "expected auth config binary without key <<\"hexpm:repo-1\">>", meck:exception(error, {expected, Err}) end end), rebar_hex_repos:remove_from_auth_config(<<"hexpm:repo-1">>, State). organization_merging(_Config) -> Repo1 = #{name => <<"hexpm:repo-1">>, api_url => <<"repo-1/api">>}, Repo2 = #{name => <<"hexpm:repo-2">>, repo_url => <<"repo-2/repo">>, repo_verify => false}, State = rebar_state:new([{hex, [{repos, [Repo1, Repo2]}]}]), meck:expect(file, consult, fun(_) -> {ok, [#{<<"hexpm:repo-1">> => #{read_key => <<"read key">>}, <<"hexpm:repo-2">> => #{read_key => <<"read key 2">>, repos_key => <<"repos key 2">>, write_key => <<"write key 2">>}, <<"hexpm">> => #{write_key => <<"write key hexpm">>}}]} end), ?assertMatch({ok, #resource{state=#{repos := [#{name := <<"hexpm:repo-1">>, parent := <<"hexpm">>, repo_name := <<"repo-1">>, api_repository := <<"repo-1">>, repo_organization := <<"repo-1">>, read_key := <<"read key">>, write_key := <<"write key hexpm">>}, #{name := <<"hexpm:repo-2">>, parent := <<"hexpm">>, repo_name := <<"repo-2">>, api_repository := <<"repo-2">>, repo_organization := <<"repo-2">>, read_key := <<"read key 2">>, repos_key := <<"repos key 2">>, write_key := <<"write key 2">>}, #{name := <<"hexpm">>, repo_name := <<"hexpm">>, api_repository := undefined, repo_organization := undefined, write_key := <<"write key hexpm">>}]}}}, rebar_pkg_resource:init(pkg, State)), ok. use_first_repo_match(Config) -> State = ?config(state, Config), ?assertMatch({ok,{package,{<<"B">>, {{2,0,0}, {[],[]}}, Repo2}, <<"inner checksum">>,<<"outer checksum">>, false, []}, #{name := Repo2, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"> 1.4.0">>, undefined, undefined, ?PACKAGE_TABLE, State)), ?assertMatch({ok,{package,{<<"B">>, {{1,4,0}, {[],[]}}, Repo3}, <<"inner checksum">>,<<"outer checksum">>, false, []}, #{name := Repo3, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined, undefined, ?PACKAGE_TABLE, State)). %% tests that even though an easier repo has C-1.3.1 it doesn't use it since its hash is different use_exact_with_hash(Config) -> State = ?config(state, Config), ?assertMatch({ok,{package,{<<"C">>, {{1,3,1}, {[],[]}}, Repo2}, <<"inner checksum">>, <<"good outer checksum">>, false, []}, #{name := Repo2, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"C">>, <<"1.3.1">>, <<"inner checksum">>, <<"good outer checksum">>, ?PACKAGE_TABLE, State)). fail_repo_update(Config) -> State = ?config(state, Config), ?assertMatch({ok,{package,{<<"B">>, {{1,4,0}, {[],[]}}, Repo3}, <<"inner checksum">>,<<"outer checksum">>, false, []}, #{name := Repo3, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined, undefined, ?PACKAGE_TABLE, State)). ignore_match_in_excluded_repo(Config) -> State = ?config(state, Config), Repos = ?config(repos, Config), ?assertMatch({ok,{package,{<<"B">>, {{1,4,6}, {[],[]}}, Hexpm}, <<"inner checksum">>,<<"outer checksum">>, #{reason := 'RETIRED_INVALID'}, []}, #{name := Hexpm, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined, undefined, ?PACKAGE_TABLE, State)), [_, Repo2 | _] = Repos, ?assertMatch({ok,{package,{<<"A">>, {{0,1,1}, {[],[]}}, Repo2}, <<"inner checksum">>, <<"good outer checksum">>, false, []}, #{name := Repo2, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"A">>, <<"0.1.1">>, <<"inner checksum">>, <<"good outer checksum">>, ?PACKAGE_TABLE, State)). optional_prereleases(Config) -> State = ?config(state, Config), ?assertMatch({ok,{package,{<<"B">>, {{1,5,0}, {[],[]}}, Hexpm}, <<"inner checksum">>,<<"outer checksum">>, false, []}, #{name := Hexpm, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"~> 1.5.0">>, undefined, undefined, ?PACKAGE_TABLE, State)), ?assertMatch({ok,{package,{<<"B">>, {{1,5,6}, {[<<"rc">>,0],[]}}, Hexpm}, <<"inner checksum">>,<<"outer checksum">>, true, []}, #{name := Hexpm, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"1.5.6-rc.0">>, <<"inner checksum">>, <<"outer checksum">>, ?PACKAGE_TABLE, State)), %% allow prerelease through configuration State1 = rebar_state:set(State, deps_allow_prerelease, true), ?assertMatch({ok,{package,{<<"B">>, {{1,5,6}, {[<<"rc">>,0],[]}}, Hexpm}, <<"inner checksum">>,<<"outer checksum">>, true, []}, #{name := Hexpm, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"~> 1.5.0">>, <<"inner checksum">>, <<"outer checksum">>, ?PACKAGE_TABLE, State1)). %% setup_deps_and_repos(Deps, Repos) -> catch ets:delete(?PACKAGE_TABLE), true = rebar_packages:new_package_table(), insert_deps(Deps), State = rebar_state:new([{hex, [{repos, [#{name => R} || R <- Repos]}]}]), rebar_state:create_resources([{pkg, rebar_pkg_resource}], State). insert_deps(Deps) -> lists:foreach(fun({Name, Version, Repo, Retired}) -> ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(Name), ec_semver:parse(Version), rebar_utils:to_binary(Repo)}, dependencies=[], retired=Retired, inner_checksum = <<"inner checksum">>, outer_checksum = <<"outer checksum">>}); ({Name, Version, InnerChecksum, OuterChecksum, Repo, Retired}) -> ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(Name), ec_semver:parse(Version), rebar_utils:to_binary(Repo)}, dependencies=[], retired=Retired, inner_checksum = InnerChecksum, outer_checksum = OuterChecksum}) end, Deps). rebar3-3.18.0/test/mock_git_resource.erl0000644000232200023220000001200114164317745020523 0ustar debalancedebalance%%% Mock a git resource and create an app magically for each URL submitted. -module(mock_git_resource). -export([mock/0, mock/1, mock/2, unmock/0]). -define(MOD, rebar_git_resource). %%%%%%%%%%%%%%%%% %%% Interface %%% %%%%%%%%%%%%%%%%% %% @doc same as `mock([])'. mock() -> mock([]). %% @doc Mocks a fake version of the git resource fetcher that creates %% empty applications magically, rather than trying to download them. %% Specific config options are explained in each of the private functions. -spec mock(Opts) -> ok when Opts :: [Option], Option :: {update, [App]} | {default_vsn, Vsn} | {override_vsn, [{App, Vsn}]} | {deps, [{App, [Dep]}]}, App :: string(), Dep :: {App, string(), {git, string()} | {git, string(), term()}} | {pkg, App, term()}, Vsn :: string(). mock(Opts) -> mock(Opts, create_app). mock(Opts, CreateType) -> meck:new(?MOD, [no_link, passthrough]), mock_lock(Opts), mock_update(Opts), mock_vsn(Opts), mock_download(Opts, CreateType), ok. unmock() -> meck:unload(?MOD). %%%%%%%%%%%%%%% %%% Private %%% %%%%%%%%%%%%%%% %% @doc creates values for a lock file. The refs are fake, but %% tags and existing refs declared for a dependency are preserved. mock_lock(_) -> meck:expect( ?MOD, lock, fun(AppInfo, _) -> case rebar_app_info:source(AppInfo) of {git, Url, {tag, Ref}} -> {git, Url, {ref, Ref}}; {git, Url, {ref, Ref}} -> {git, Url, {ref, Ref}}; {git, Url} -> {git, Url, {ref, "0.0.0"}}; {git, Url, _} -> {git, Url, {ref, "0.0.0"}} end end). %% @doc The config passed to the `mock/2' function can specify which apps %% should be updated on a per-name basis: `{update, ["App1", "App3"]}'. mock_update(Opts) -> ToUpdate = proplists:get_value(upgrade, Opts, []), % ct:pal("TOUp: ~p", [ToUpdate]), meck:expect( ?MOD, needs_update, fun(AppInfo, _) -> {git, Url, _Ref} = rebar_app_info:source(AppInfo), App = app(Url), % ct:pal("Needed update? ~p (~p) -> ~p", [App, {Url,_Ref}, lists:member(App, ToUpdate)]), lists:member(App, ToUpdate) end). %% @doc Tries to fetch a version from the `*.app.src' file or otherwise %% just returns random stuff, avoiding to check for the presence of git. %% This probably breaks the assumption that stable references are returned. %% %% This function can't respect the `override_vsn' option because if the %% .app.src file isn't there, we can't find the app name either. mock_vsn(Opts) -> Default = proplists:get_value(default_vsn, Opts, "0.0.0"), meck:expect( ?MOD, make_vsn, fun(AppInfo, _) -> Dir = rebar_app_info:dir(AppInfo), case filelib:wildcard("*.app.src", filename:join([Dir,"src"])) of [AppSrc] -> {ok, App} = file:consult(AppSrc), Vsn = proplists:get_value(vsn, App), {plain, Vsn}; _ -> {plain, Default} end end). %% @doc For each app to download, create a dummy app on disk instead. %% The configuration for this one (passed in from `mock/1') includes: %% %% - Specify a version, branch, ref, or tag via the `{git, URL, {_, Vsn}' %% format to specify a path. %% - If there is no version submitted (`{git, URL}'), the function instead %% reads from the `override_vsn' proplist (`{override_vsn, {"App1","1.2.3"}'), %% and otherwise uses the value associated with `default_vsn'. %% - Dependencies for each application must be passed of the form: %% `{deps, [{"app1", [{app2, ".*", {git, ...}}]}]}' -- basically %% the `deps' option takes a key/value list of terms to output directly %% into a `rebar.config' file to describe dependencies. mock_download(Opts, CreateType) -> Deps = proplists:get_value(deps, Opts, []), Config = proplists:get_value(config, Opts, []), Default = proplists:get_value(default_vsn, Opts, "0.0.0"), Overrides = proplists:get_value(override_vsn, Opts, []), meck:expect( ?MOD, download, fun (Dir, AppInfo, _, _) -> Git = rebar_app_info:source(AppInfo), filelib:ensure_dir(Dir), {git, Url, {_, Vsn}} = normalize_git(Git, Overrides, Default), App = app(Url), AppDeps = proplists:get_value({App,Vsn}, Deps, []), rebar_test_utils:CreateType( Dir, App, Vsn, [kernel, stdlib] ++ [element(1,D) || D <- AppDeps] ), rebar_test_utils:create_config(Dir, [{deps, AppDeps}]++Config), ok end). %%%%%%%%%%%%%%% %%% Helpers %%% %%%%%%%%%%%%%%% app(Path) -> filename:basename(Path, ".git"). normalize_git({git, Url}, Overrides, Default) -> Vsn = proplists:get_value(app(Url), Overrides, Default), {git, Url, {tag, Vsn}}; normalize_git({git, Url, Branch}, _, _) when is_list(Branch) -> {git, Url, {branch, Branch}}; normalize_git(Git, _, _) -> Git. rebar3-3.18.0/test/rebar_upgrade_SUITE.erl0000644000232200023220000007502414164317745020611 0ustar debalancedebalance-module(rebar_upgrade_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). all() -> [{group, git}, {group, pkg}, novsn_pkg, upgrade_no_args]. groups() -> [{all, [], [top_a, top_b, top_c, top_d1, top_d2, top_e, pair_a, pair_b, pair_ab, pair_c, pair_all, triplet_a, triplet_b, triplet_c, tree_a, tree_b, tree_c, tree_c2, tree_cj, tree_ac, tree_all, delete_d, promote, stable_lock, fwd_lock, compile_upgrade_parity, umbrella_config, profiles, profiles_exclusion, tree_migration]}, {git, [], [{group, all}]}, {pkg, [], [{group, all}]}]. init_per_suite(Config) -> application:start(meck), Config. end_per_suite(_Config) -> application:stop(meck). init_per_group(git, Config) -> [{deps_type, git} | Config]; init_per_group(pkg, Config) -> [{deps_type, pkg} | Config]; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. init_per_testcase(novsn_pkg, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0, "novsn_pkg_"), AppDir = ?config(apps, Config), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [fakeapp]}]), Deps = [{{<<"fakeapp">>, <<"1.0.0">>}, []}], UpDeps = [{{<<"fakeapp">>, <<"1.1.0">>}, []}], Upgrades = ["fakeapp"], [{rebarconfig, RebarConf}, {mock, fun() -> catch mock_pkg_resource:unmock(), mock_pkg_resource:mock([{pkgdeps, Deps}, {upgrade, []}]) end}, {mock_update, fun() -> catch mock_pkg_resource:unmock(), mock_pkg_resource:mock([{pkgdeps, UpDeps++Deps}, {upgrade, Upgrades}]) end}, {expected, {ok, [{dep, "fakeapp", "1.1.0"}, {lock, "fakeapp", "1.1.0"}]}} | Config]; init_per_testcase(upgrade_no_args, Config0) -> rebar_test_utils:init_rebar_state(Config0, "upgrade_no_args_"); init_per_testcase(Case, Config) -> DepsType = ?config(deps_type, Config), {Deps, UpDeps, ToUp, Expectations} = upgrades(Case), Expanded = rebar_test_utils:expand_deps(DepsType, Deps), UpExpanded = rebar_test_utils:expand_deps(DepsType, UpDeps), [{expected, normalize_unlocks(Expectations)}, {mock, fun() -> mock_deps(DepsType, Expanded, []) end}, {mock_update, fun() -> mock_deps(DepsType, Expanded, UpExpanded, ToUp) end} | setup_project(Case, Config, Expanded, UpExpanded)]. end_per_testcase(_, Config) -> meck:unload(), Config. setup_project(Case=umbrella_config, Config0, Deps, UpDeps) -> DepsType = ?config(deps_type, Config0), NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType), Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"), AppDir = filename:join([?config(apps, Config), "apps", NameRoot]), rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), TopConf = rebar_test_utils:create_config(AppDir, [{deps, []}]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]), [{rebarconfig, TopConf}, {rebarumbrella, RebarConf}, {next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config]; setup_project(Case, Config0, Deps, UpDeps) when Case == profiles; Case == profiles_exclusion -> DepsType = ?config(deps_type, Config0), NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType), Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"), AppDir = filename:join([?config(apps, Config), "apps", NameRoot]), rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]), [Top|ProfileDeps] = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [ {deps, [Top]}, {profiles, [{fake, [{deps, ProfileDeps}]}]} ]), [NextTop|NextPDeps] = rebar_test_utils:top_level_deps(UpDeps), NextConfig = [{deps, [NextTop]}, {profiles, [{fake, [{deps, NextPDeps}]}]}], [{rebarconfig, RebarConf}, {next_config, NextConfig} | Config]; setup_project(Case, Config0, Deps, UpDeps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( Config0, atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_" ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]), [{rebarconfig, RebarConf}, {next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config]. upgrades(top_a) -> %% Original tree {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Updated tree [{"A", "1.0.0", [{"B", [{"D", "3.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Modified apps, gobally ["A","B","D"], %% upgrade vs. new tree {"A", [{"A","1.0.0"}, "B", "C", {"D","3.0.0"}]}}; upgrades(top_b) -> %% Original tree {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Updated tree [{"A", "1.0.0", [{"B", [{"D", "3.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Modified apps, gobally ["A","B","D"], %% upgrade vs. new tree {"B", {error, {rebar_prv_upgrade, {transitive_dependency, <<"B">>}}}}}; upgrades(top_c) -> %% Original tree {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Updated tree [{"A", "1.0.0", [{"B", [{"D", "3.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Modified apps, gobally ["A","B","D"], %% upgrade vs. new tree {"C", {error, {rebar_prv_upgrade, {transitive_dependency, <<"C">>}}}}}; upgrades(top_d1) -> %% Original tree {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Updated tree [{"A", "1.0.0", [{"B", [{"D", "3.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Modified apps, gobally ["A","B","D"], %% upgrade vs. new tree {"D", {error, {rebar_prv_upgrade, {transitive_dependency, <<"D">>}}}}}; upgrades(top_d2) -> %% Original tree {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Updated tree [{"A", "1.0.0", [{"B", [{"D", "3.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Modified apps, gobally ["A","B","D"], %% upgrade vs. new tree {"D", {error, {rebar_prv_upgrade, {transitive_dependency, <<"D">>}}}}}; upgrades(top_e) -> %% Original tree {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Updated tree [{"A", "1.0.0", [{"B", [{"D", "3.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], %% Modified apps, gobally ["A","B","D"], %% upgrade vs. new tree {"E", {error, {rebar_prv_upgrade, {unknown_dependency, <<"E">>}}}}}; upgrades(pair_a) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], ["A","B","C","D"], {"A", [{"A","2.0.0"},{"C","2.0.0"},{"B","1.0.0"},{"D","1.0.0"}]}}; upgrades(pair_b) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], ["A","B","C","D"], {"B", [{"A","1.0.0"},{"C","1.0.0"},{"B","2.0.0"},{"D","2.0.0"}]}}; upgrades(pair_ab) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], ["A","B","C","D"], {"A,B", [{"A","2.0.0"},{"C","2.0.0"},{"B","2.0.0"},{"D","2.0.0"}]}}; upgrades(pair_c) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], ["A","B","C","D"], {"C", {error, {rebar_prv_upgrade, {transitive_dependency, <<"C">>}}}}}; upgrades(pair_all) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], ["A","B","C","D"], {"", [{"A","2.0.0"},{"C","2.0.0"},{"B","2.0.0"},{"D","2.0.0"}]}}; upgrades(triplet_a) -> {[{"A", "1.0.0", [{"D",[]}, {"E","3.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "0.0.0", [{"H","3.0.0",[]}, {"I",[]}]}], [{"A", "1.0.0", [{"D",[]}, {"E","2.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H","4.0.0",[]}, {"I",[]}]}], ["A","C","E","H"], {"A", [{"A","1.0.0"}, "D", {"E","2.0.0"}, {"B","1.0.0"}, {"F","1.0.0"}, "G", {"C","0.0.0"}, {"H","3.0.0"}, "I"]}}; upgrades(triplet_b) -> {[{"A", "1.0.0", [{"D",[]}, {"E","3.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "0.0.0", [{"H","3.0.0",[]}, {"I",[]}]}], [{"A", "2.0.0", [{"D",[]}, {"E","2.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H","4.0.0",[]}, {"I",[]}]}], ["A","C","E","H"], {"B", [{"A","1.0.0"}, "D", {"E","3.0.0"}, {"B","1.0.0"}, {"F","1.0.0"}, "G", {"C","0.0.0"}, {"H","3.0.0"}, "I"]}}; upgrades(triplet_c) -> {[{"A", "1.0.0", [{"D",[]}, {"E","3.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "0.0.0", [{"H","3.0.0",[]}, {"I",[]}]}], [{"A", "2.0.0", [{"D",[]}, {"E","2.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H","4.0.0",[]}, {"I",[]}]}], ["A","C","E","H"], {"C", [{"A","1.0.0"}, "D", {"E","3.0.0"}, {"B","1.0.0"}, {"F","1.0.0"}, "G", {"C","1.0.0"}, {"H","4.0.0"}, "I"]}}; upgrades(tree_a) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "2.0.0", [{"H",[]}]} ], ["C"], {"A", [{"A","1.0.0"}, "D", "J", "E", {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H", {"I","2.0.0"}]}}; upgrades(tree_b) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "2.0.0", [{"H",[]}]} ], ["C"], {"B", [{"A","1.0.0"}, "D", "J", "E", {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H", {"I","2.0.0"}]}}; upgrades(tree_c) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}]} ], ["C","I"], {"C", [{"A","1.0.0"}, "D", "J", "E", {"I","1.0.0"}, {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H"]}}; upgrades(tree_c2) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[{"K",[]}]}, {"I","2.0.0",[]}]} ], ["C", "H"], {"C", [{"A","1.0.0"}, "D", "J", "E", {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H", {"I", "2.0.0"}, "K"]}}; upgrades(tree_cj) -> {[{"A", "1.0.0", [{"D",[{"J", "1.0.0",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","1.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J", "2.0.0", []}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","1.0.0",[]}]} ], ["C","J"], {"C", [{"A","1.0.0"}, "D", {"J", "1.0.0"}, "E", {"I","1.0.0"}, {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H"]}}; upgrades(tree_ac) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}]} ], ["C","I"], {"C, A", [{"A","1.0.0"}, "D", "J", "E", {"I","1.0.0"}, {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H"]}}; upgrades(tree_all) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}]} ], ["C","I"], {"", [{"A","1.0.0"}, "D", "J", "E", {"I","1.0.0"}, {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H"]}}; upgrades(delete_d) -> {[{"A", "1.0.0", [{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}]} ], [{"A", "2.0.0", [{"B", []}, {"C", []}]} ], ["A","B", "C"], %% upgrade vs. new tree {"", [{"A","2.0.0"}, "B", "C"]}}; upgrades(promote) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]}, {"C", "3.0.0", []} ], ["A","B","C","D"], {"C", [{"A","1.0.0"},{"C","3.0.0"},{"B","1.0.0"},{"D","1.0.0"}]}}; upgrades(stable_lock) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], % lock after this [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], [], %% Run a regular lock and no app should be upgraded {"any", [{"A","1.0.0"},{"C","1.0.0"},{"B","1.0.0"},{"D","1.0.0"}]}}; upgrades(fwd_lock) -> {[{"A", "1.0.0", [{"C", "1.0.0", []}]}, {"B", "1.0.0", [{"D", "1.0.0", []}]} ], [{"A", "2.0.0", [{"C", "2.0.0", []}]}, {"B", "2.0.0", [{"D", "2.0.0", []}]} ], ["A","B","C","D"], %% For this one, we should build, rewrite the lock %% file to include the result post-upgrade, and then %% run a regular lock to see that the lock file is respected %% in deps. {"any", [{"A","2.0.0"},{"C","2.0.0"},{"B","2.0.0"},{"D","2.0.0"}]}}; upgrades(compile_upgrade_parity) -> {[{"A", "1.0.0", [{"D",[{"J",[]}]}, {"E",[{"I","1.0.0",[]}]}]}, {"B", "1.0.0", [{"F",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H",[]}, {"I","2.0.0",[]}]} ], [], [], {"", [{"A","1.0.0"}, "D", "J", "E", {"I","1.0.0"}, {"B","1.0.0"}, "F", "G", {"C","1.0.0"}, "H"]}}; upgrades(umbrella_config) -> {[{"A", "1.0.0", []}], [{"A", "2.0.0", []}], ["A"], {"A", [{"A","2.0.0"}]}}; upgrades(profiles) -> %% Ensure that we can unlock deps under a given profile; %% B and C should both be in a custom profile %% and must not be locked. {[{"A", "1.0.0", [{"D",[]}, {"E","3.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "0.0.0", [{"H","3.0.0",[]}, {"I",[]}]}], [{"A", "2.0.0", [{"D",[]}, {"E","2.0.0",[]}]}, {"B", "2.0.0", [{"F","2.0.0",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H","4.0.0",[]}, {"I",[]}]}], ["A","B","C","E","F","H"], {"C", [{"A","1.0.0"}, "D", {"E","3.0.0"}, {"B","2.0.0"}, {"F","2.0.0"}, "G", {"C","1.0.0"}, {"H","4.0.0"}, "I"]}}; upgrades(profiles_exclusion) -> %% Ensure that we can unlock deps under a given profile; %% B and C should both be in a custom profile %% and must not be locked. {[{"A", "1.0.0", [{"D",[]}, {"E","3.0.0",[]}]}, {"B", "1.0.0", [{"F","1.0.0",[]}, {"G",[]}]}, {"C", "0.0.0", [{"H","3.0.0",[]}, {"I",[]}]}], [{"A", "2.0.0", [{"D",[]}, {"E","2.0.0",[]}]}, {"B", "2.0.0", [{"F","2.0.0",[]}, {"G",[]}]}, {"C", "1.0.0", [{"H","4.0.0",[]}, {"I",[]}]}], ["A","B","C","E","F","H"], {"A", [{"A","1.0.0"}, "D", {"E","3.0.0"}, {"B","2.0.0"}, {"F","2.0.0"}, "G", {"C","1.0.0"}, {"H","4.0.0"}, "I"]}}; upgrades(tree_migration) -> {[{"B", "1.0.0", []}, {"C", "1.0.0", [{"D","1.0.0",[{"E", "1.0.0", []}]}]}], [{"B", "2.0.0", [{"E","1.0.0",[]}]}, {"C", "1.0.0", [{"D","1.0.0",[]}]}], ["B"], {"B", [{"A","1.0.0"}, "D", {"E","1.0.0"}, {"B","2.0.0"}]}}. %% TODO: add a test that verifies that unlocking files and then %% running the upgrade code is enough to properly upgrade things. mock_deps(git, Deps, Upgrades) -> catch mock_git_resource:unmock(), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]); mock_deps(pkg, Deps, Upgrades) -> catch mock_pkg_resource:unmock(), {_, PkgDeps} = rebar_test_utils:flat_deps(Deps), mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]). mock_deps(git, OldDeps, Deps, Upgrades) -> catch mock_git_resource:unmock(), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps++OldDeps), mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]); mock_deps(pkg, OldDeps, Deps, Upgrades) -> catch mock_pkg_resource:unmock(), {_, PkgDeps} = rebar_test_utils:flat_deps(Deps++OldDeps), mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]). normalize_unlocks({[], Locks}) -> {"--all", normalize_unlocks_expect(Locks)}; normalize_unlocks({App, Locks}) -> {iolist_to_binary(App), normalize_unlocks_expect(Locks)}; normalize_unlocks({App, Vsn, Locks}) -> {iolist_to_binary(App), iolist_to_binary(Vsn), normalize_unlocks_expect(Locks)}. normalize_unlocks_expect({error, Reason}) -> {error, Reason}; normalize_unlocks_expect([]) -> []; normalize_unlocks_expect([{App,Vsn} | Rest]) -> [{dep, App, Vsn}, {lock, App, Vsn} | normalize_unlocks_expect(Rest)]; normalize_unlocks_expect([App | Rest]) -> [{dep, App}, {lock, App} | normalize_unlocks_expect(Rest)]. top_a(Config) -> run(Config). top_b(Config) -> run(Config). top_c(Config) -> run(Config). top_d1(Config) -> run(Config). top_d2(Config) -> run(Config). top_e(Config) -> run(Config). pair_a(Config) -> run(Config). pair_b(Config) -> run(Config). pair_ab(Config) -> run(Config). pair_c(Config) -> run(Config). pair_all(Config) -> run(Config). triplet_a(Config) -> run(Config). triplet_b(Config) -> run(Config). triplet_c(Config) -> run(Config). tree_a(Config) -> run(Config). tree_b(Config) -> run(Config). tree_c(Config) -> run(Config). tree_c2(Config) -> run(Config). tree_cj(Config) -> run(Config). tree_ac(Config) -> run(Config). tree_all(Config) -> run(Config). promote(Config) -> run(Config). delete_d(Config) -> meck:new(rebar_log, [no_link, passthrough]), run(Config), Infos = [{Str, Args} || {_, {rebar_log, log, [info, Str, Args]}, _} <- meck:history(rebar_log)], meck:unload(rebar_log), ?assertNotEqual([], [1 || {"App ~ts is no longer needed and can be deleted.", [<<"D">>]} <- Infos]). stable_lock(Config) -> apply(?config(mock, Config), []), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}), {App, Unlocks} = ?config(expected, Config), ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]), Expectation = case Unlocks of {error, Term} -> {error, Term}; _ -> {ok, Unlocks} end, apply(?config(mock_update, Config), []), NewRebarConf = rebar_test_utils:create_config(?config(apps, Config), [{deps, ?config(next_top_deps, Config)}]), {ok, NewRebarConfig} = file:consult(NewRebarConf), rebar_test_utils:run_and_check( Config, NewRebarConfig, ["lock", App], Expectation ). fwd_lock(Config) -> apply(?config(mock, Config), []), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}), {App, Unlocks} = ?config(expected, Config), ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]), Expectation = case Unlocks of {error, Term} -> {error, Term}; _ -> {ok, Unlocks} end, rewrite_locks(Expectation, Config), apply(?config(mock_update, Config), []), NewRebarConf = rebar_test_utils:create_config(?config(apps, Config), [{deps, ?config(next_top_deps, Config)}]), {ok, NewRebarConfig} = file:consult(NewRebarConf), rebar_test_utils:run_and_check( Config, NewRebarConfig, ["lock", App], Expectation ). compile_upgrade_parity(Config) -> AppDir = ?config(apps, Config), apply(?config(mock, Config), []), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), %% compiling and upgrading should generate the same lockfiles when %% deps are identical Lockfile = filename:join([AppDir, "rebar.lock"]), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}), {ok, CompileLockData1} = file:read_file(Lockfile), rebar_test_utils:run_and_check(Config, RebarConfig, ["upgrade", "--all"], {ok, []}), {ok, UpgradeLockData} = file:read_file(Lockfile), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}), {ok, CompileLockData2} = file:read_file(Lockfile), ?assertEqual(CompileLockData1, CompileLockData2), ?assertEqual(CompileLockData1, UpgradeLockData). umbrella_config(Config) -> apply(?config(mock, Config), []), {ok, TopConfig} = file:consult(?config(rebarconfig, Config)), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}), {App, Unlocks} = ?config(expected, Config), ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]), Expectation = case Unlocks of {error, Term} -> {error, Term}; _ -> {ok, Unlocks} end, meck:new(rebar_prv_upgrade, [passthrough]), meck:expect(rebar_prv_upgrade, do, fun(S) -> apply(?config(mock_update, Config), []), meck:passthrough([S]) end), _NewRebarConf = rebar_test_utils:create_config(filename:dirname(?config(rebarumbrella, Config)), [{deps, ?config(next_top_deps, Config)}]), %% re-run from the top-level with the old config still in place; %% detection must happen when going for umbrella apps! rebar_test_utils:run_and_check( Config, TopConfig, ["upgrade", App], Expectation ), meck:unload(rebar_prv_upgrade). profiles(Config) -> apply(?config(mock, Config), []), {ok, TopConfig} = file:consult(?config(rebarconfig, Config)), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}), %% Install test deps along with them rebar_test_utils:run_and_check(Config, TopConfig, ["as","fake","lock"], {ok, []}), {App, Unlocks} = ?config(expected, Config), ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]), Expectation = case Unlocks of {error, Term} -> {error, Term}; _ -> {ok, [T || T <- Unlocks, element(1,T) == dep orelse lists:member(element(2,T), ["A","D","E"])]} end, meck:new(rebar_prv_app_discovery, [passthrough]), meck:expect(rebar_prv_app_discovery, do, fun(S) -> apply(?config(mock_update, Config), []), meck:passthrough([S]) end), NewRebarConf = rebar_test_utils:create_config(?config(apps, Config), ?config(next_config, Config)), {ok, NewRebarConfig} = file:consult(NewRebarConf), rebar_test_utils:run_and_check( Config, NewRebarConfig, ["as","fake","upgrade", App], Expectation ), meck:unload(rebar_prv_app_discovery). profiles_exclusion(Config) -> profiles(Config). tree_migration(Config) -> apply(?config(mock, Config), []), ConfigPath = ?config(rebarconfig, Config), {ok, RebarConfig} = file:consult(ConfigPath), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}), {App, _Unlocks} = ?config(expected, Config), meck:new(rebar_prv_upgrade, [passthrough]), meck:expect(rebar_prv_upgrade, do, fun(S) -> apply(?config(mock_update, Config), []), meck:passthrough([S]) end), NewRebarConf = rebar_test_utils:create_config(filename:dirname(ConfigPath), [{deps, ?config(next_top_deps, Config)}]), {ok, NewRebarConfig} = file:consult(NewRebarConf), {ok, NewState} = rebar_test_utils:run_and_check( Config, NewRebarConfig, ["upgrade", App], return ), meck:unload(rebar_prv_upgrade), %% Check that the internal state properly has E with a lock-level %% of 1. Locks = rebar_state:lock(NewState), [Locked] = [X || X <- Locks, rebar_app_info:name(X) =:= <<"E">>], ?assertEqual(1, rebar_app_info:dep_level(Locked)), %% Check that the lockfile on disk agrees AppDir = ?config(apps, Config), Lockfile = filename:join([AppDir, "rebar.lock"]), case file:consult(Lockfile) of {ok, [{_Vsn, Prop}|_]} -> % packages ?assertMatch({<<"E">>, _, 1}, lists:keyfind(<<"E">>, 1, Prop)); {ok, [Prop]} -> % git source ?assertMatch({<<"E">>, _, 1}, lists:keyfind(<<"E">>, 1, Prop)) end, ok. run(Config) -> apply(?config(mock, Config), []), ConfigPath = ?config(rebarconfig, Config), {ok, RebarConfig} = file:consult(ConfigPath), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}), {App, Unlocks} = ?config(expected, Config), ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]), Expectation = case Unlocks of {error, Term} -> {error, Term}; _ -> {ok, Unlocks} end, meck:new(rebar_prv_upgrade, [passthrough]), meck:expect(rebar_prv_upgrade, do, fun(S) -> apply(?config(mock_update, Config), []), meck:passthrough([S]) end), NewRebarConf = rebar_test_utils:create_config(filename:dirname(ConfigPath), [{deps, ?config(next_top_deps, Config)}]), {ok, NewRebarConfig} = file:consult(NewRebarConf), rebar_test_utils:run_and_check( Config, NewRebarConfig, ["upgrade", App], Expectation ), meck:unload(rebar_prv_upgrade). novsn_pkg(Config) -> apply(?config(mock, Config), []), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), %% Install dependencies before re-mocking for an upgrade rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}), Expectation = ?config(expected, Config), apply(?config(mock_update, Config), []), rebar_test_utils:run_and_check( Config, RebarConfig, ["upgrade", "--all"], Expectation ), ok. rewrite_locks({ok, Expectations}, Config) -> AppDir = ?config(apps, Config), LockFile = filename:join([AppDir, "rebar.lock"]), Locks = case ?config(deps_type, Config) of git -> {ok, [LockData]} = file:consult(LockFile), LockData; pkg -> {ok, [{_Vsn, LockData}|_]} = file:consult(LockFile), LockData end, ExpLocks = [{list_to_binary(Name), Vsn} || {lock, Name, Vsn} <- Expectations], NewLocks = lists:foldl( fun({App, {pkg, Name, _}, Lvl}, Acc) -> Vsn = list_to_binary(proplists:get_value(App,ExpLocks)), [{App, {pkg, Name, Vsn}, Lvl} | Acc] ; ({App, {git, URL, {ref, _}}, Lvl}, Acc) -> Vsn = proplists:get_value(App,ExpLocks), [{App, {git, URL, {ref, Vsn}}, Lvl} | Acc] end, [], Locks), ct:pal("rewriting locks from ~p to~n~p", [Locks, NewLocks]), file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])). upgrade_no_args(Config) -> try rebar_test_utils:run_and_check(Config, [], ["upgrade"], return) catch {error, {rebar_prv_upgrade, no_arg}} -> ok end, ok. rebar3-3.18.0/test/rebar_new_SUITE_data/0000755000232200023220000000000014164317745020230 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/0000755000232200023220000000000014164317745021464 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/0000755000232200023220000000000014164317745023462 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/0000755000232200023220000000000014164317745025377 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/README.md.dtl0000644000232200023220000000007414164317745027441 0ustar debalancedebalance{{name}} ===== {{desc}} Build ----- $ rebar3 compile rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/app.erl.dtl0000644000232200023220000000137614164317745027454 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc {{name}} public API %% @end %%%------------------------------------------------------------------- -module({{name}}_app). -behaviour(application). %% Application callbacks -export([start/2 ,stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> {{name}}_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/sup.erl.dtl0000644000232200023220000000177214164317745027503 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc {{name}} top level supervisor. %% @end %%%------------------------------------------------------------------- -module({{name}}_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/gitignore.dtl0000644000232200023220000000017514164317745030076 0ustar debalancedebalance.rebar3 _* .eunit *.o *.beam *.plt *.swp *.swo .erlang.cookie ebin log erl_crash.dump .rebar _rel _deps _plugins _tdeps logs rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/otp_app.app.src.dtl0000644000232200023220000000030314164317745031107 0ustar debalancedebalance{application, {{name}}, [{description, "{{desc}}"} ,{vsn, "0.1.0"} ,{registered, []} ,{mod, {'{{name}}_app', []}} ,{applications, [kernel ,stdlib ]} ,{env,[]} ,{modules, []} ]}. rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/bad_index.template0000644000232200023220000000107614164317745031055 0ustar debalancedebalance{description, "OTP Application"}. {variables, [ {name, "mylib", "Name of the OTP application"}, {desc, "An OTP application", "Short description of the app"} ]}. bad_term, {template, "app.erl.dtl", "{{name}}/src/{{name}}_app.erl"}. {template, "sup.erl.dtl", "{{name}}/src/{{name}}_sup.erl"}. {template, "otp_app.app.src.dtl", "{{name}}/src/{{name}}.app.src"}. {template, "rebar.config.dtl", "{{name}}/rebar.config"}. {template, "gitignore.dtl", "{{name}}/.gitignore"}. {template, "LICENSE.dtl", "{{name}}/LICENSE"}. {template, "README.md.dtl", "{{name}}/README.md"}. rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/rebar.config.dtl0000644000232200023220000000004514164317745030442 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}.rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/bad_index/LICENSE.dtl0000644000232200023220000000271514164317745027173 0ustar debalancedebalanceCopyright (c) {{copyright_year}}, {{author_name}} <{{author_email}}>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/0000755000232200023220000000000014164317745024242 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/README.md.dtl0000644000232200023220000000007414164317745026304 0ustar debalancedebalance{{name}} ===== {{desc}} Build ----- $ rebar3 compile rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/test_app.template0000644000232200023220000000106414164317745027617 0ustar debalancedebalance{description, "OTP Application"}. {variables, [ {name, "mylib", "Name of the OTP application"}, {desc, "An OTP application", "Short description of the app"} ]}. {template, "app.erl.dtl", "{{name}}/src/{{name}}_app.erl"}. {template, "sup.erl.dtl", "{{name}}/src/{{name}}_sup.erl"}. {template, "otp_app.app.src.dtl", "{{name}}/src/{{name}}.app.src"}. {template, "rebar.config.dtl", "{{name}}/rebar.config"}. {template, "gitignore.dtl", "{{name}}/.gitignore"}. {template, "LICENSE.dtl", "{{name}}/LICENSE"}. {template, "README.md.dtl", "{{name}}/README.md"}. rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/app.erl.dtl0000644000232200023220000000137614164317745026317 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc {{name}} public API %% @end %%%------------------------------------------------------------------- -module({{name}}_app). -behaviour(application). %% Application callbacks -export([start/2 ,stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> {{name}}_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/sup.erl.dtl0000644000232200023220000000177214164317745026346 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc {{name}} top level supervisor. %% @end %%%------------------------------------------------------------------- -module({{name}}_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/gitignore.dtl0000644000232200023220000000017514164317745026741 0ustar debalancedebalance.rebar3 _* .eunit *.o *.beam *.plt *.swp *.swo .erlang.cookie ebin log erl_crash.dump .rebar _rel _deps _plugins _tdeps logs rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/otp_app.app.src.dtl0000644000232200023220000000030314164317745027752 0ustar debalancedebalance{application, {{name}}, [{description, "{{desc}}"} ,{vsn, "0.1.0"} ,{registered, []} ,{mod, {'{{name}}_app', []}} ,{applications, [kernel ,stdlib ]} ,{env,[]} ,{modules, []} ]}. rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/rebar.config.dtl0000644000232200023220000000004514164317745027305 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}.rebar3-3.18.0/test/rebar_new_SUITE_data/.rebar3/templates/app/LICENSE.dtl0000644000232200023220000000271514164317745026036 0ustar debalancedebalanceCopyright (c) {{copyright_year}}, {{author_name}} <{{author_email}}>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/0000755000232200023220000000000014164317745022405 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/rebar.config0000644000232200023220000000007014164317745024664 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}. {plugins, [tpl]}. rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/0000755000232200023220000000000014164317745024534 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/0000755000232200023220000000000014164317745025333 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/priv/0000755000232200023220000000000014164317745026313 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/priv/module.erl.dtl0000644000232200023220000000002414164317745031062 0ustar debalancedebalance-module({{name}}). rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/priv/tpl.template0000644000232200023220000000023714164317745030651 0ustar debalancedebalance{description, "A basic template"}. {variables, [ {name, "mod", "Name of the module"} ]}. {dir, "test"}. {template, "module.erl.dtl", "src/{{name}}.erl"}. rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/rebar.config0000644000232200023220000000004514164317745027614 0ustar debalancedebalance{erl_opts, [debug_info]}. {deps, []}.rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/src/0000755000232200023220000000000014164317745026122 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/src/tpl_prv.erl0000644000232200023220000000225214164317745030315 0ustar debalancedebalance-module('tpl_prv'). -export([init/1, do/1, format_error/1]). -define(PROVIDER, 'tpl'). -define(DEPS, [app_discovery]). %% =================================================================== %% Public API %% =================================================================== -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> Provider = providers:create([ {name, ?PROVIDER}, % The 'user friendly' name of the task {module, ?MODULE}, % The module implementation of the task {bare, true}, % The task can be run by the user, always true {deps, ?DEPS}, % The list of dependencies {example, "rebar3 tpl"}, % How to use the plugin {opts, []}, % list of options understood by the plugin {short_desc, "A rebar plugin"}, {desc, "A rebar plugin"} ]), {ok, rebar_state:add_provider(State, Provider)}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> {ok, State}. -spec format_error(any()) -> iolist(). format_error(Reason) -> io_lib:format("~p", [Reason]). rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/src/tpl.erl0000644000232200023220000000024614164317745027427 0ustar debalancedebalance-module('tpl'). -export([init/1]). -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> {ok, State1} = 'tpl_prv':init(State), {ok, State1}. rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/_checkouts/tpl/src/tpl.app.src0000644000232200023220000000034614164317745030214 0ustar debalancedebalance{application, 'tpl', [{description, "A rebar plugin"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {contributors, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/src/0000755000232200023220000000000014164317745023174 5ustar debalancedebalancerebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/src/plugin_tpl.erl0000644000232200023220000000057214164317745026061 0ustar debalancedebalance-module('plugin_tpl'). %% API exports -export([]). %%==================================================================== %% API functions %%==================================================================== %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_new_SUITE_data/plugin_tpl/src/plugin_tpl.app.src0000644000232200023220000000035514164317745026644 0ustar debalancedebalance{application, 'plugin_tpl', [{description, "An OTP library"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {contributors, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_eunit_SUITE.erl0000644000232200023220000007057614164317745020315 0ustar debalancedebalance-module(rebar_eunit_SUITE). -export([all/0, groups/0]). -export([init_per_suite/1, end_per_suite/1]). -export([init_per_group/2, end_per_group/2]). -export([basic_app_compiles/1, basic_app_files/1]). -export([basic_app_exports/1, basic_app_testset/1]). -export([basic_app_eunit_macro/1]). -export([multi_app_compiles/1, multi_app_files/1]). -export([multi_app_exports/1, multi_app_testset/1]). -export([multi_app_eunit_macro/1]). -export([eunit_tests/1, eunit_opts/1, eunit_first_files/1]). -export([single_application_arg/1, multi_application_arg/1, missing_application_arg/1]). -export([single_module_arg/1, multi_module_arg/1, missing_module_arg/1]). -export([single_suite_arg/1, multi_suite_arg/1, missing_suite_arg/1]). -export([single_generator_arg/1, multi_generator_arg/1, missing_generator_arg/1]). -export([single_file_arg/1, multi_file_arg/1, missing_file_arg/1]). -export([single_dir_arg/1, multi_dir_arg/1, missing_dir_arg/1]). -export([multiple_arg_composition/1, multiple_arg_errors/1]). -export([misspecified_eunit_tests/1]). -export([misspecified_eunit_compile_opts/1]). -export([misspecified_eunit_first_files/1]). -export([alternate_test_regex/1]). -export([syscfg_app_opts/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). all() -> [{group, basic_app}, {group, multi_app}, {group, cmd_line_args}, misspecified_eunit_tests, misspecified_eunit_compile_opts, misspecified_eunit_first_files, alternate_test_regex, syscfg_app_opts]. groups() -> [{basic_app, [sequence], [basic_app_compiles, {group, basic_app_results}]}, {basic_app_results, [], [basic_app_files, basic_app_exports, basic_app_testset, basic_app_eunit_macro]}, {multi_app, [sequence], [multi_app_compiles, {group, multi_app_results}]}, {multi_app_results, [], [multi_app_files, multi_app_exports, multi_app_testset, multi_app_eunit_macro]}, {cmd_line_args, [], [eunit_tests, eunit_opts, eunit_first_files, single_application_arg, multi_application_arg, missing_application_arg, single_module_arg, multi_module_arg, missing_module_arg, single_suite_arg, multi_suite_arg, missing_suite_arg, single_generator_arg, multi_generator_arg, missing_generator_arg, single_file_arg, multi_file_arg, missing_file_arg, single_dir_arg, multi_dir_arg, missing_dir_arg, multiple_arg_composition, multiple_arg_errors]}]. %% this just unzips the example apps used by tests to the priv dir for later use init_per_suite(Config) -> PrivDir = ?config(priv_dir, Config), DataDir = ?config(data_dir, Config), ok = ec_file:copy(filename:join([DataDir, "basic_app.zip"]), filename:join([PrivDir, "basic_app.zip"])), {ok, _} = zip:extract(filename:join([PrivDir, "basic_app.zip"]), [{cwd, PrivDir}]), ok = ec_file:copy(filename:join([DataDir, "multi_app.zip"]), filename:join([PrivDir, "multi_app.zip"])), {ok, _} = zip:extract(filename:join([PrivDir, "multi_app.zip"]), [{cwd, PrivDir}]), ok = ec_file:copy(filename:join([DataDir, "syscfg_app.zip"]), filename:join([PrivDir, "syscfg_app.zip"])), {ok, _} = zip:extract(filename:join([PrivDir, "syscfg_app.zip"]), [{cwd, PrivDir}]), Config. end_per_suite(Config) -> Config. init_per_group(basic_app, Config) -> GroupState = rebar_test_utils:init_rebar_state(Config, "basic_app_"), AppDir = ?config(apps, GroupState), PrivDir = ?config(priv_dir, GroupState), AppDirs = ["src", "include", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), RebarConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}], {ok, State} = rebar_test_utils:run_and_check(GroupState, RebarConfig, ["as", "test", "lock"], return), [{result, State}|GroupState]; init_per_group(multi_app, Config) -> GroupState = rebar_test_utils:init_rebar_state(Config, "multi_app_"), AppDir = ?config(apps, GroupState), PrivDir = ?config(priv_dir, GroupState), AppDirs = ["apps", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "multi_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), RebarConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}], {ok, State} = rebar_test_utils:run_and_check(GroupState, RebarConfig, ["as", "test", "lock"], return), [{result, State}|GroupState]; init_per_group(cmd_line_args, Config) -> GroupState = rebar_test_utils:init_rebar_state(Config, "cmd_line_args_"), AppDir = ?config(apps, GroupState), PrivDir = ?config(priv_dir, GroupState), AppDirs = ["apps", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "multi_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), RebarConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}, %% test set not supported by cmd line args {eunit_tests, [{test, multi_app_bar, sanity_test}, {test, multi_app_baz, sanity_test}]}, {eunit_opts, [verbose]}, {eunit_first_files, [filename:join(["apps", "multi_app_bar", "test", "multi_app_bar_tests_helper.erl"]), filename:join(["apps", "multi_app_baz", "test", "multi_app_baz_tests_helper.erl"])]}], {ok, State} = rebar_test_utils:run_and_check(GroupState, RebarConfig, ["eunit"], return), [{result, State}|GroupState]; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. %% === tests for a single application at the root of a project === %% check that project compiles properly basic_app_compiles(Config) -> AppDir = ?config(apps, Config), State = ?config(result, Config), {ok, _} = rebar_prv_eunit:do(State), rebar_test_utils:check_results(AppDir, [{app, "basic_app"}], "*"). %% check that all files expected to be present are present basic_app_files(Config) -> AppDir = ?config(apps, Config), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "ebin", F])) end, ["basic_app.app", "basic_app.beam"]), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "test", F])) end, ["basic_app_tests.beam", "basic_app_tests_helper.beam"]). %% check that the correct tests are exported from modules for project %% note that this implies `TEST` is set correctly basic_app_exports(_Config) -> Tests = fun(Mod) -> begin Path = code:which(Mod), {ok, {Mod, [{exports, Ex}]}} = beam_lib:chunks(Path, [exports]), true = lists:member({sanity_test, 0}, Ex) end end, Helpers = fun(Mod) -> begin Path = code:which(Mod), {ok, {Mod, [{exports, Ex}]}} = beam_lib:chunks(Path, [exports]), true = lists:member({help, 0}, Ex) end end, lists:foreach(Tests, [basic_app, basic_app_tests]), lists:foreach(Helpers, [basic_app_tests_helper]). %% check that the correct tests are schedule to run for project basic_app_testset(Config) -> Result = ?config(result, Config), Set = {ok, [{application, basic_app}, {module, basic_app_tests_helper}]}, Set = rebar_prv_eunit:prepare_tests(Result). basic_app_eunit_macro(_Config) -> Macro = fun(Mod) -> begin Path = code:which(Mod), {ok, {Mod, [{compile_info, CompileInfo}]}} = beam_lib:chunks(Path, [compile_info]), Opts = proplists:get_value(options, CompileInfo, []), true = lists:member({d, 'EUNIT'}, Opts) end end, lists:foreach(Macro, [basic_app, basic_app_tests, basic_app_tests_helper]). %% === tests for multiple applications in the `apps' directory of a project === %% check that project compiles properly multi_app_compiles(Config) -> AppDir = ?config(apps, Config), State = ?config(result, Config), {ok, _} = rebar_prv_eunit:do(State), rebar_test_utils:check_results(AppDir, [{app, "multi_app_bar"}, {app, "multi_app_baz"}], "*"). %% check that all files expected to be present are present multi_app_files(Config) -> AppDir = ?config(apps, Config), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", F])) end, ["multi_app_bar.app", "multi_app_bar.beam"]), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", F])) end, ["multi_app_baz.app", "multi_app_baz.beam"]), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "test", F])) end, ["multi_app_bar_tests.beam", "multi_app_bar_tests_helper.beam"]), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "test", F])) end, ["multi_app_baz_tests.beam", "multi_app_baz_tests_helper.beam"]), lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "extras", "test", F])) end, ["multi_app_tests.beam", "multi_app_tests_helper.beam"]). %% check that the correct tests are exported from modules for project %% note that this implies `TEST` is set correctly multi_app_exports(_Config) -> Tests = fun(Mod) -> begin Ex = Mod:module_info(exports), true = lists:member({sanity_test, 0}, Ex) end end, Helpers = fun(Mod) -> begin Ex = Mod:module_info(exports), true = lists:member({help, 0}, Ex) end end, lists:foreach(Tests, [multi_app_bar, multi_app_bar_tests, multi_app_baz, multi_app_baz_tests, multi_app_tests]), lists:foreach(Helpers, [multi_app_bar_tests_helper, multi_app_baz_tests_helper, multi_app_tests_helper]). %% check that the correct tests are schedule to run for project multi_app_testset(Config) -> Result = ?config(result, Config), Set = {ok, [{application, multi_app_baz}, {application, multi_app_bar}, {module, multi_app_bar_tests_helper}, {module, multi_app_baz_tests_helper}, {module, multi_app_tests}, {module, multi_app_tests_helper}]}, Set = rebar_prv_eunit:prepare_tests(Result). multi_app_eunit_macro(_Config) -> Macro = fun(Mod) -> begin Path = code:which(Mod), {ok, {Mod, [{compile_info, CompileInfo}]}} = beam_lib:chunks(Path, [compile_info]), Opts = proplists:get_value(options, CompileInfo, []), true = lists:member({d, 'EUNIT'}, Opts) end end, lists:foreach(Macro, [multi_app_bar, multi_app_bar_tests, multi_app_baz, multi_app_baz_tests, multi_app_tests, multi_app_tests_helper, multi_app_bar_tests_helper, multi_app_baz_tests_helper]). %% === tests for command line arguments === %% no explicit test for cmd line args taking precedence over the rebar.config since %% almost every single test implies it %% check tests in the rebar.config are run if no cmd line opts are specified eunit_tests(Config) -> State = ?config(result, Config), Expect = {ok, [{test, multi_app_bar, sanity_test}, {test, multi_app_baz, sanity_test}]}, Expect = rebar_prv_eunit:prepare_tests(State). %% check eunit_opts from the rebar.config are respected eunit_opts(Config) -> State = ?config(result, Config), Apps = rebar_state:project_apps(State), lists:foreach(fun(App) -> [verbose] = rebar_app_info:get(App, eunit_opts) end, Apps). %% check eunit_first_files from the rebar.config are respected eunit_first_files(Config) -> State = ?config(result, Config), FirstFiles = [filename:join(["apps", "multi_app_bar", "test", "multi_app_bar_tests_helper.erl"]), filename:join(["apps", "multi_app_baz", "test", "multi_app_baz_tests_helper.erl"])], Apps = rebar_state:project_apps(State), lists:foreach(fun(App) -> FirstFiles = rebar_app_info:get(App, eunit_first_files) end, Apps). %% check that the --application cmd line opt generates the correct test set single_application_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{application, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State). multi_application_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar,multi_app_baz"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{application, multi_app_bar}, {application, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State). %% check that an invalid --application cmd line opt generates an error missing_application_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app"]), State = rebar_state:command_parsed_args(S, Args), Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Application `missing_app' not found in project."]}}}, Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)). %% check that the --module cmd line opt generates the correct test set single_module_arg(Config) -> AppDir = ?config(apps, Config), S = ?config(result, Config), %% necessary to fix paths Path = code:get_path(), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=multi_app_bar"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State), %% restore path code:set_path(Path). multi_module_arg(Config) -> AppDir = ?config(apps, Config), S = ?config(result, Config), %% necessary to fix paths Path = code:get_path(), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=multi_app_bar,multi_app_baz"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State), %% restore path code:set_path(Path). %% check that an invalid --module cmd line opt generates an error missing_module_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=missing_app"]), State = rebar_state:command_parsed_args(S, Args), T = rebar_prv_eunit:prepare_tests(State), Tests = rebar_prv_eunit:validate_tests(S, T), Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}}, Error = Tests. %% check that the --suite cmd line opt generates the correct test set single_suite_arg(Config) -> AppDir = ?config(apps, Config), S = ?config(result, Config), %% necessary to fix paths Path = code:get_path(), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State), %% restore path code:set_path(Path). multi_suite_arg(Config) -> AppDir = ?config(apps, Config), S = ?config(result, Config), %% necessary to fix paths Path = code:get_path(), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar,multi_app_baz"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State), %% restore path code:set_path(Path). %% check that an invalid --suite cmd line opt generates an error missing_suite_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=missing_app"]), State = rebar_state:command_parsed_args(S, Args), Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}}, Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)). %% check that the --generator cmd line opt generates the correct test set single_generator_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--generator=module_name:function_name"]), State = rebar_state:command_parsed_args(S, Args), {ok, [{generator, module_name, function_name}]} = rebar_prv_eunit:prepare_tests(State). multi_generator_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--generator=module1:func1;func2,module2:func1;func2"]), State = rebar_state:command_parsed_args(S, Args), Generators = [{generator, module1, func1}, {generator, module1, func2}, {generator, module2, func1}, {generator, module2, func2}], {ok, Generators} = rebar_prv_eunit:prepare_tests(State). %% check that an invalid --suite cmd line opt generates an error missing_generator_arg(Config) -> S = ?config(result, Config), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--generator=missing_module:func1"]), State = rebar_state:command_parsed_args(S, Args), Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_module' not found in project."]}}}, Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)). %% check that the --file cmd line opt generates the correct test set single_file_arg(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]), State = rebar_state:command_parsed_args(S, Args), {ok, [{file, Path}]} = rebar_prv_eunit:prepare_tests(State). multi_file_arg(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]), BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", "multi_app_baz.beam"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ BarPath ++ "," ++ BazPath]), State = rebar_state:command_parsed_args(S, Args), {ok, [{file, BarPath}, {file, BazPath}]} = rebar_prv_eunit:prepare_tests(State). %% check that an invalid --file cmd line opt generates an error missing_file_arg(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]), State = rebar_state:command_parsed_args(S, Args), Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["File `" ++ Path ++"' not found."]}}}, Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)). %% check that the --dir cmd line opt generates the correct test set single_dir_arg(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]), State = rebar_state:command_parsed_args(S, Args), {ok, [{dir, Path}]} = rebar_prv_eunit:prepare_tests(State). multi_dir_arg(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]), BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ BarPath ++ "," ++ BazPath]), State = rebar_state:command_parsed_args(S, Args), {ok, [{dir, BarPath}, {dir, BazPath}]} = rebar_prv_eunit:prepare_tests(State). %% check that an invalid --dir cmd line opt generates an error missing_dir_arg(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]), State = rebar_state:command_parsed_args(S, Args), Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Directory `" ++ Path ++"' not found."]}}}, Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)). %% check that multiple args are composed multiple_arg_composition(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), %% necessary to fix paths Path = code:get_path(), code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]), FilePath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]), DirPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar", "--module=multi_app_bar", "--suite=multi_app_bar", "--file=" ++ FilePath, "--dir=" ++ DirPath]), State = rebar_state:command_parsed_args(S, Args), Expect = [{application, multi_app_bar}, {dir, DirPath}, {file, FilePath}, {module, multi_app_bar}, {module, multi_app_bar}], {ok, Expect} = rebar_prv_eunit:prepare_tests(State), %% restore path code:set_path(Path). %% check that multiple errors are reported multiple_arg_errors(Config) -> S = ?config(result, Config), AppDir = ?config(apps, Config), FilePath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]), DirPath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]), {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app", "--module=missing_app", "--suite=missing_app", "--file=" ++ FilePath, "--dir=" ++ DirPath]), State = rebar_state:command_parsed_args(S, Args), T = rebar_prv_eunit:prepare_tests(State), Tests = rebar_prv_eunit:validate_tests(S, T), Expect = ["Application `missing_app' not found in project.", "Directory `" ++ DirPath ++ "' not found.", "File `" ++ FilePath ++ "' not found.", "Module `missing_app' not found in project.", "Module `missing_app' not found in project."], {error, {rebar_prv_eunit, {eunit_test_errors, Expect}}} = Tests. misspecified_eunit_tests(Config) -> State = rebar_test_utils:init_rebar_state(Config, "basic_app_"), AppDir = ?config(apps, State), PrivDir = ?config(priv_dir, State), AppDirs = ["src", "include", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), BaseConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}], RebarConfig = [{eunit_tests, {dir, "test"}}|BaseConfig], {error, {rebar_prv_eunit, Error}} = rebar_test_utils:run_and_check(State, RebarConfig, ["eunit"], return), {badconfig, {"Value `~p' of option `~p' must be a list", {{dir, "test"}, eunit_tests}}} = Error. misspecified_eunit_compile_opts(Config) -> State = rebar_test_utils:init_rebar_state(Config, "basic_app_"), AppDir = ?config(apps, State), PrivDir = ?config(priv_dir, State), AppDirs = ["src", "include", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), RebarConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, {d, eunit_compile_define}}], {error, {rebar_prv_eunit, Error}} = rebar_test_utils:run_and_check(State, RebarConfig, ["eunit"], return), {badconfig, {"Value `~p' of option `~p' must be a list", {{d, eunit_compile_define}, eunit_compile_opts}}} = Error. misspecified_eunit_first_files(Config) -> State = rebar_test_utils:init_rebar_state(Config, "basic_app_"), AppDir = ?config(apps, State), PrivDir = ?config(priv_dir, State), AppDirs = ["src", "include", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), BaseConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}], RebarConfig = [{eunit_first_files, some_file}|BaseConfig], {error, {rebar_prv_eunit, Error}} = rebar_test_utils:run_and_check(State, RebarConfig, ["eunit"], return), {badconfig, {"Value `~p' of option `~p' must be a list", {some_file, eunit_first_files}}} = Error. alternate_test_regex(Config) -> State = rebar_test_utils:init_rebar_state(Config, "alternate_test_regex_"), AppDir = ?config(apps, State), PrivDir = ?config(priv_dir, State), AppDirs = ["src", "include", "test"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), BaseConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}], RebarConfig = [{eunit_test_regex, "basic_app_tests.erl"}|BaseConfig], {ok, S} = rebar_test_utils:run_and_check(State, RebarConfig, ["as", "test", "lock"], return), Set = {ok, [{application, basic_app}, {module, basic_app_tests}]}, Set = rebar_prv_eunit:prepare_tests(S). %% check that sys_config files go through syscfg_app_opts(Config) -> State = rebar_test_utils:init_rebar_state(Config, "syscfg_"), AppDir = ?config(apps, State), PrivDir = ?config(priv_dir, State), AppDirs = ["src", "test", "config"], lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "syscfg_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), RebarConfig = [{eunit_opts, [ {sys_config, ["config/file1.config", "config/file2.config"]} ]}], Opts = ["--sys_config", "config/cmd1.config,config/cmd2.config"], {ok, _} = rebar_test_utils:run_and_check(State, RebarConfig, ["eunit" | Opts], return), ok. rebar3-3.18.0/test/rebar_unlock_SUITE.erl0000644000232200023220000000713014164317745020446 0ustar debalancedebalance-module(rebar_unlock_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). all() -> [pkgunlock, unlock, unlock_all, unlock_no_args]. init_per_testcase(pkgunlock, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0, "pkgunlock"), Lockfile = filename:join(?config(apps, Config), "rebar.lock"), ec_file:copy(filename:join(?config(data_dir, Config), "pkg.rebar.lock"), Lockfile), [{lockfile, Lockfile} | Config]; init_per_testcase(Case, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0, atom_to_list(Case)), Lockfile = filename:join(?config(apps, Config), "rebar.lock"), ec_file:copy(filename:join(?config(data_dir, Config), "rebar.lock"), Lockfile), [{lockfile, Lockfile} | Config]. end_per_testcase(_, Config) -> Config. pkgunlock(Config) -> Locks = read_locks(Config), Hashes = read_hashes(Config), rebar_test_utils:run_and_check(Config, [], ["unlock", "fakeapp"], {ok, []}), Locks = read_locks(Config), Hashes = read_hashes(Config), rebar_test_utils:run_and_check(Config, [], ["unlock", "bbmustache"], {ok, []}), ?assertEqual(Locks -- ["bbmustache"], read_locks(Config)), ?assertEqual(Hashes -- ["bbmustache"], read_hashes(Config)), rebar_test_utils:run_and_check(Config, [], ["unlock", "cf,certifi"], {ok, []}), ?assertEqual(Locks -- ["bbmustache","cf","certifi"], read_locks(Config)), ?assertEqual(Hashes -- ["bbmustache","cf","certifi"], read_hashes(Config)), rebar_test_utils:run_and_check(Config, [], ["unlock", rebar_string:join(Locks,",")], {ok, []}), ?assertEqual({error, enoent}, read_locks(Config)), ?assertEqual({error, enoent}, read_hashes(Config)), ok. unlock(Config) -> Locks = read_locks(Config), rebar_test_utils:run_and_check(Config, [], ["unlock", "fakeapp"], {ok, []}), Locks = read_locks(Config), {ok, State} = rebar_test_utils:run_and_check(Config, [], ["unlock", "uuid"], return), ?assertEqual(Locks -- ["uuid"], read_locks(Config)), ?assert(false =:= lists:keyfind(<<"uuid">>, 1, rebar_state:get(State, {locks, default}))), ?assert(false =/= lists:keyfind(<<"itc">>, 1, rebar_state:get(State, {locks, default}))), rebar_test_utils:run_and_check(Config, [], ["unlock", "gproc,itc"], {ok, []}), ?assertEqual(Locks -- ["uuid","gproc","itc"], read_locks(Config)), rebar_test_utils:run_and_check(Config, [], ["unlock", rebar_string:join(Locks,",")], {ok, []}), ?assertEqual({error, enoent}, read_locks(Config)), ok. unlock_all(Config) -> [_|_] = read_locks(Config), {ok, State} = rebar_test_utils:run_and_check(Config, [], ["unlock", "--all"], return), ?assertEqual({error, enoent}, read_locks(Config)), ?assertEqual([], rebar_state:get(State, {locks, default})), ok. unlock_no_args(Config) -> try rebar_test_utils:run_and_check(Config, [], ["unlock"], return) catch {error, {rebar_prv_unlock, no_arg}} -> ok end, ok. read_locks(Config) -> case file:consult(?config(lockfile, Config)) of {ok, _} -> Locks = rebar_config:consult_lock_file(?config(lockfile, Config)), [binary_to_list(element(1,Lock)) || Lock <- Locks]; Other -> Other end. read_hashes(Config) -> case file:consult(?config(lockfile, Config)) of {ok, [{_Vsn, _Locks},Props|_]} -> Hashes = proplists:get_value(pkg_hash, Props, []), [binary_to_list(element(1,Hash)) || Hash <- Hashes]; {ok, [{_Vsn, _Locks}]} -> []; Other -> Other end. rebar3-3.18.0/test/rebar_localfs_resource.erl0000644000232200023220000000213314164317745021532 0ustar debalancedebalance%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% %% @doc A localfs custom resource (for testing purposes only) %% implementing the deprecated rebar_resource instead of v2 %% %% ``` %% {deps, [ %% %% Application files are copied from "/path/to/app_name" %% {app_name, {localfs, "/path/to/app_name", undefined}} %% ]}. %% ''' -module(rebar_localfs_resource). -behaviour(rebar_resource). -export([init/1 ,lock/2 ,download/3 ,needs_update/2 ,make_vsn/1]). -include_lib("eunit/include/eunit.hrl"). -spec init(rebar_state:t()) -> {ok, term()}. init(_State) -> {ok, #{}}. lock(AppDir, {localfs, Path, _Ref}) -> lock(AppDir, {localfs, Path}); lock(_AppDir, {localfs, Path}) -> {localfs, Path, undefined}. needs_update(_AppDir, _Resource) -> false. download(AppDir, {localfs, Path, _Ref}, State) -> download(AppDir, {localfs, Path}, State); download(AppDir, {localfs, Path}, _State) -> ok = rebar_file_utils:cp_r(filelib:wildcard(Path ++ "/*"), AppDir), {ok, undefined}. make_vsn(_AppDir) -> {plain, "undefined"}. rebar3-3.18.0/test/rebar_dialyzer_SUITE.erl0000644000232200023220000004163714164317745021010 0ustar debalancedebalance-module(rebar_dialyzer_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2, init_per_testcase/2, all/0, groups/0, empty_base_plt/1, empty_app_plt/1, empty_app_succ_typings/1, update_base_plt/1, update_app_plt/1, build_release_plt/1, plt_apps_option/1, exclude_and_extra/1, cli_args/1, single_app_succ_typing/1, extra_src_dirs/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_group(empty, Config) -> [{base_plt_apps, []} | Config]; init_per_group(_Group, Config) -> [{base_plt_apps, [erts]} | Config]. end_per_group(_Group, _Config) -> ok. init_per_testcase(Testcase, Config) -> PrivDir = ?config(priv_dir, Config), Prefix = ec_cnv:to_list(Testcase), BasePrefix = Prefix ++ "_base", Opts = [{plt_prefix, Prefix}, {plt_location, PrivDir}, {base_plt_prefix, BasePrefix}, {base_plt_location, PrivDir}, {base_plt_apps, ?config(base_plt_apps, Config)}], Suffix = "_" ++ rebar_utils:otp_release() ++ "_plt", [{plt, filename:join(PrivDir, Prefix ++ Suffix)}, {base_plt, filename:join(PrivDir, BasePrefix ++ Suffix)}, {rebar_config, [{dialyzer, Opts}]} | rebar_test_utils:init_rebar_state(Config)]. all() -> [{group, empty}, {group, build_and_check}, {group, update}]. groups() -> [{empty, [empty_base_plt, empty_app_plt, empty_app_succ_typings]}, {build_and_check, [cli_args, single_app_succ_typing, build_release_plt, plt_apps_option, exclude_and_extra, extra_src_dirs]}, {update, [update_base_plt, update_app_plt]}]. empty_base_plt(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), BasePlt = ?config(base_plt, Config), Plt = ?config(plt, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, BasePltFiles} = plt_files(BasePlt), ?assertEqual([], BasePltFiles), ErtsFiles = erts_files(), {ok, PltFiles} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles), ok. empty_app_plt(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), BasePlt = ?config(base_plt, Config), Plt = ?config(plt, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, []), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, BasePltFiles} = plt_files(BasePlt), ?assertEqual([], BasePltFiles), {ok, PltFiles} = plt_files(Plt), ?assertEqual([], PltFiles), ok. empty_app_succ_typings(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_empty_app(AppDir, Name, Vsn, []), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), ok. update_base_plt(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), BasePlt = ?config(base_plt, Config), Plt = ?config(plt, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), ErtsFiles = erts_files(), {ok, BasePltFiles} = plt_files(BasePlt), ?assertEqual(ErtsFiles, BasePltFiles), alter_plt(BasePlt), ok = file:delete(Plt), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, BasePltFiles2} = plt_files(BasePlt), ?assertEqual(ErtsFiles, BasePltFiles2), {ok, PltFiles} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles), add_missing_file(BasePlt), ok = file:delete(Plt), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, BasePltFiles3} = plt_files(BasePlt), ?assertEqual(ErtsFiles, BasePltFiles3). update_app_plt(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), Plt = ?config(plt, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), ErtsFiles = erts_files(), {ok, PltFiles} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles), alter_plt(Plt), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, PltFiles2} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles2), ok = file:delete(Plt), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, PltFiles3} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles3), add_missing_file(Plt), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name}]}), {ok, PltFiles4} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles4). build_release_plt(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), BasePlt = ?config(base_plt, Config), Plt = ?config(plt, Config), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [erts]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [erts, ec_cnv:to_atom(Name1)]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name1}, {app, Name2}]}), ErtsFiles = erts_files(), {ok, BasePltFiles} = plt_files(BasePlt), ?assertEqual(ErtsFiles, BasePltFiles), {ok, PltFiles} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles). plt_apps_option(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), Plt = ?config(plt, Config), State = ?config(state, Config), %% Create applications Name1 = rebar_test_utils:create_random_name("app1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"deps",Name1]), Name1, Vsn1, []), App1 = ec_cnv:to_atom(Name1), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"deps",Name2]), Name2, Vsn2, [App1]), % App2 depends on App1 App2 = ec_cnv:to_atom(Name2), Name3 = rebar_test_utils:create_random_name("app3_"), % the project application Vsn3 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name3, Vsn3, [App2]), % App3 depends on App2 %% Dependencies settings State1 = rebar_state:add_resource(State, {localfs, rebar_localfs_resource}), Config1 = [{state, State1} | Config], RebarConfig1 = merge_config( [{deps, [ {App1, {localfs, filename:join([AppDir,"deps",Name1])}}, {App2, {localfs, filename:join([AppDir,"deps",Name2])}} ]}], RebarConfig), %% Dialyzer: plt_apps = top_level_deps (default) rebar_test_utils:run_and_check(Config1, RebarConfig1, ["dialyzer"], {ok, [{app, Name3}]}), %% NOTE: `erts` is included in `base_plt_apps` {ok, PltFiles1} = plt_files(Plt), ?assertEqual([App2, erts], get_apps_from_beam_files(PltFiles1)), %% Dialyzer: plt_apps = all_deps RebarConfig2 = merge_config([{dialyzer, [{plt_apps, all_deps}]}], RebarConfig1), rebar_test_utils:run_and_check(Config1, RebarConfig2, ["dialyzer"], {ok, [{app, Name3}]}), {ok, PltFiles2} = plt_files(Plt), ?assertEqual([App1, App2, erts], get_apps_from_beam_files(PltFiles2)). exclude_and_extra(Config) -> AppDir = ?config(apps, Config), RebarConfig = ?config(rebar_config, Config), BasePlt = ?config(base_plt, Config), Plt = ?config(plt, Config), {value, {dialyzer, Opts}, Rest} = lists:keytake(dialyzer, 1, RebarConfig), % Remove erts => [] % Add erlang+zlib => [erlang, zlib], % Add erl_prim_loader+init => [erl_prim_loader, init, erlang, zlib] % Remove zlib+init => [erl_prim_loader, erlang] Opts2 = [{exclude_apps, [erts]}, {base_plt_mods, [erlang, zlib]}, {plt_extra_mods, [erl_prim_loader, init]}, {exclude_mods, [zlib, init]} | Opts], RebarConfig2 = [{dialyzer, Opts2} | Rest], Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [erts]), rebar_test_utils:run_and_check(Config, RebarConfig2, ["dialyzer"], {ok, [{app, Name}]}), Erlang = code:where_is_file("erlang.beam"), {ok, BasePltFiles} = plt_files(BasePlt), ?assertEqual([Erlang], BasePltFiles), Pair = lists:sort([Erlang, code:where_is_file("erl_prim_loader.beam")]), {ok, PltFiles} = plt_files(Plt), ?assertEqual(Pair, PltFiles). cli_args(Config) -> AppDir = ?config(apps, Config), [{dialyzer, Opts}] = ?config(rebar_config, Config), BasePlt = ?config(base_plt, Config), Plt = ?config(plt, Config), {value, {_, Prefix}, Opts1} = lists:keytake(plt_prefix, 1, Opts), {value, {_, BasePrefix}, Opts2} = lists:keytake(base_plt_prefix, 1, Opts1), {value, {_, Location}, Opts3} = lists:keytake(plt_location, 1, Opts2), {value, {_, BasePltLocation}, Opts4} = lists:keytake(base_plt_location, 1, Opts3), RebarConfig = [{dialyzer, Opts4}], Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [erts]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [erts, ec_cnv:to_atom(Name1)]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer", "--plt-location=" ++ Location, "--base-plt-location=" ++ BasePltLocation, "--plt-prefix=" ++ Prefix, "--base-plt-prefix=" ++ BasePrefix, "--statistics"], {ok, [{app, Name1}, {app, Name2}]}), ErtsFiles = erts_files(), {ok, BasePltFiles} = plt_files(BasePlt), ?assertEqual(ErtsFiles, BasePltFiles), {ok, PltFiles} = plt_files(Plt), ?assertEqual(ErtsFiles, PltFiles). single_app_succ_typing(Config) -> AppDir = ?config(apps, Config), State = ?config(state, Config), Plt = ?config(plt, Config), RebarConfig = ?config(rebar_config, Config), %% test workflow: %% (a) build PLT containing all project apps and dependencies (no success typing yet)! %% (b) perform success-typing for all apps (warnings expected) %% (c) perform success-typing for app with and without warnings Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), %% contains warnings in tests rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, []), %% second app, depending on first, should not produce warnings App1 = ec_cnv:to_atom(Name), %%% second app depends on first Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [App1]), % App2 depends on App1 App2 = ec_cnv:to_atom(Name2), %% start with building all apps into PLT RebarConfig2 = merge_config([{dialyzer, [{plt_apps, all_apps}]}], RebarConfig), {ok, _} = rebar3:run(rebar_state:new(State, RebarConfig2, AppDir), ["dialyzer", "--succ-typings=false"]), %% verify all project apps are in PLT {ok, PltFiles} = plt_files(Plt), ?assertEqual([App1, App2, erts], get_apps_from_beam_files(PltFiles)), %% warnings when apps are not specified Command0 = ["as", "test", "dialyzer"], % there are few warnings for generated test (see rebar_test_utils:erl_eunit_suite_file/1) {error, {rebar_prv_dialyzer, {dialyzer_warnings, _}}} = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), Command0), %% warnings from App Command1 = ["as", "test", "dialyzer", "--app=" ++ Name], % there are few warnings for generated test (see rebar_test_utils:erl_eunit_suite_file/1) {error, {rebar_prv_dialyzer, {dialyzer_warnings, _}}} = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), Command1), %% no warnings from App2 Command2 = ["as", "test", "dialyzer", "--app=" ++ Name2], {ok, _} = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), Command2). extra_src_dirs(Config) -> AppDir = ?config(apps, Config), State = ?config(state, Config), RebarConfig = ?config(rebar_config, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, []), % `test` directory is already in `extra_src_dirs` when run test profile Command = ["as", "test", "dialyzer"], % there are few warnings for generated test (see rebar_test_utils:erl_eunit_suite_file/1) {error, {rebar_prv_dialyzer, {dialyzer_warnings, _}}} = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), Command). %% Helpers erts_files() -> ErtsDir = code:lib_dir(erts, ebin), ErtsBeams = filelib:wildcard("*.beam", ErtsDir), ErtsFiles = lists:map(fun(Beam) -> filename:join(ErtsDir, Beam) end, ErtsBeams), lists:sort(ErtsFiles). plt_files(Plt) -> case dialyzer:plt_info(Plt) of {ok, Info} -> Files = proplists:get_value(files, Info), {ok, lists:sort(Files)}; Other -> Other end. alter_plt(Plt) -> {ok, Files} = plt_files(Plt), _ = dialyzer:run([{analysis_type, plt_remove}, {init_plt, Plt}, {files, [hd(Files)]}]), _ = dialyzer:run([{analysis_type, plt_add}, {init_plt, Plt}, {files, [code:which(dialyzer)]}]), ok. add_missing_file(Plt) -> Source = code:which(dialyzer), Dest = filename:join(filename:dirname(Plt), "dialyzer.beam"), {ok, _} = file:copy(Source, Dest), _ = try dialyzer:run([{analysis_type, plt_add}, {init_plt, Plt}, {files, [Dest]}]) after ok = file:delete(Dest) end, ok. -spec merge_config(Config, Config) -> Config when Config :: [{term(), term()}]. merge_config(NewConfig, OldConfig) -> dict:to_list( rebar_opts:merge_opts(dict:from_list(NewConfig), dict:from_list(OldConfig))). -spec get_apps_from_beam_files(string()) -> [atom()]. get_apps_from_beam_files(BeamFiles) -> lists:usort( [begin AppNameVsn = filename:basename(filename:dirname(filename:dirname(File))), [AppName | _] = rebar_string:lexemes(AppNameVsn ++ "-", "-"), ec_cnv:to_atom(AppName) end || File <- BeamFiles]). rebar3-3.18.0/test/rebar_localfs_resource_v2.erl0000644000232200023220000000243714164317745022150 0ustar debalancedebalance%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% %% @doc A localfs custom resource (for testing purposes only) %% %% ``` %% {deps, [ %% %% Application files are copied from "/path/to/app_name" %% {app_name, {localfs, "/path/to/app_name", undefined}} %% ]}. %% ''' -module(rebar_localfs_resource_v2). -behaviour(rebar_resource_v2). -export([init/2 ,lock/2 ,download/4 ,needs_update/2 ,make_vsn/2]). -include_lib("eunit/include/eunit.hrl"). -spec init(atom(), rebar_state:t()) -> {ok, term()}. init(Type, _State) -> Resource = rebar_resource_v2:new(Type, ?MODULE, #{}), {ok, Resource}. lock(AppInfo, _) -> case rebar_app_info:source(AppInfo) of {localfs, Path, _Ref} -> {localfs, Path, undefined}; {localfs, Path} -> {localfs, Path, undefined} end. needs_update(_AppInfo, _) -> false. download(TmpDir, AppInfo, State, _) -> download_(TmpDir, rebar_app_info:source(AppInfo), State). download_(TmpDir, {localfs, Path, _Ref}, State) -> download_(TmpDir, {localfs, Path}, State); download_(TmpDir, {localfs, Path}, _State) -> ok = rebar_file_utils:cp_r(filelib:wildcard(Path ++ "/*"), TmpDir), {ok, undefined}. make_vsn(_AppInfo, _) -> {plain, "undefined"}. rebar3-3.18.0/test/rebar_namespace_SUITE.erl0000644000232200023220000001122714164317745021111 0ustar debalancedebalance-module(rebar_namespace_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [implicit_compile, default_compile, do_compile, as_default_compile, as_do_compile, notfound, do_notfound, default_notfound, ns_notfound, ns_found, as_ns_invalid, do_ns_chain, do_ns_chain2, do_ns_noarg, do_ns_badcmd]. init_per_testcase(Case, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"++atom_to_list(Case)), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), [{name, Name} | Config]. end_per_testcase(_, Config) -> Config. implicit_compile(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}). default_compile(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check(Config, [], ["default","compile"], {ok, [{app, Name}]}). do_compile(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check(Config, [], ["do", "compile"], {ok, [{app, Name}]}). as_default_compile(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check(Config, [], ["as", "prod", "default", "compile"], {ok, [{app, Name}]}). as_do_compile(Config) -> Name = ?config(name, Config), rebar_test_utils:run_and_check(Config, [], ["as", "prod", "do", "compile"], {ok, [{app, Name}]}). notfound(Config) -> Command = ["fakecommand"], rebar_test_utils:run_and_check( Config, [], Command, {error, io_lib:format("Command ~p not found", [fakecommand])} ). do_notfound(Config) -> Command = ["do", "fakecommand"], rebar_test_utils:run_and_check( Config, [], Command, {error, io_lib:format("Command ~p not found", [fakecommand])} ). default_notfound(Config) -> Command = ["default", "fakecommand"], rebar_test_utils:run_and_check( Config, [], Command, {error, io_lib:format("Command ~p not found", [fakecommand])} ). ns_notfound(Config) -> Command = ["ns", "fakecommand"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {error, io_lib:format("Command ~p not found in namespace ~p", [fakecommand, ns])} ). ns_found(Config) -> Command = ["ns", "fake_provider"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {ok, []} ). as_ns_invalid(Config) -> %% The as namespace is not valid Command = ["as", "profile", "as", "task"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {error, "Namespace 'as' is forbidden"} ). do_ns_chain(Config) -> %% `do` is also able to resolve namespaces on %% commands not found Command = ["do", "deps,", "ns", "fake_provider,", "deps"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {ok, []} ). do_ns_chain2(Config) -> %% `do` is also able to resolve namespaces on %% commands not found Command = ["do", "ns", "fake_provider,", "deps,", "ns", "fake_provider"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {ok, []} ). do_ns_noarg(Config) -> %% `do` is also able to resolve namespaces on %% commands not found Command = ["do", "ns"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {error, io_lib:format("Command ~p not found", [ns])} ). do_ns_badcmd(Config) -> %% `do` is also able to resolve namespaces on %% commands not found Command = ["do", "ns", "badcmd"], rebar_test_utils:run_and_check( add_fake_ns_provider(Config), [], Command, {error, io_lib:format("Command ~p not found in namespace ~p", [badcmd, ns])} ). %%% Helpers %%% add_fake_ns_provider(Config) -> State = ?config(state, Config), State1 = rebar_state:add_provider( State, providers:create( [{name, fake_provider}, {module, ?MODULE}, {namespace, ns}, {deps, []}, {opts, []}] ) ), [{state, State1} | Config]. %% callback for the test suite. do(State) -> {ok, State}. rebar3-3.18.0/test/rebar_escriptize_SUITE.erl0000644000232200023220000000617014164317745021337 0ustar debalancedebalance-module(rebar_escriptize_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, all/0, escriptize_with_name/1, escriptize_with_bad_name/1, escriptize_with_bad_dep/1, build_and_clean_app/1, escriptize_with_ebin_subdir/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). all() -> [ build_and_clean_app, escriptize_with_name, escriptize_with_bad_name, escriptize_with_bad_dep, escriptize_with_ebin_subdir ]. %% Test escriptize builds and runs the app's escript build_and_clean_app(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["escriptize"], {ok, [{app, Name, valid}]}). escriptize_with_name(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [{escript_main_app, Name}], ["escriptize"], {ok, [{app, Name, valid}]}). escriptize_with_bad_name(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [{escript_main_app, boogers}], ["escriptize"], {error,{rebar_prv_escriptize, {bad_name, boogers}}}). escriptize_with_bad_dep(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib, boogers]), rebar_test_utils:run_and_check(Config, [{escript_main_app, Name}], ["escriptize"], {error,{rebar_prv_escriptize, {bad_app, boogers}}}). escriptize_with_ebin_subdir(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), filelib:ensure_dir(filename:join([AppDir, "ebin", "subdir", "subdirfile"])), %% To work, this test must run from the AppDir itself. To avoid breaking %% other tests, be careful with cwd Cwd = file:get_cwd(), try file:set_cwd(AppDir), {ok, _} = rebar3:run(rebar_state:new(?config(state,Config), [], AppDir), ["escriptize"]) after file:set_cwd(Cwd) % reset always end, ok. rebar3-3.18.0/test/rebar_xref_SUITE.erl0000644000232200023220000002756214164317745020132 0ustar debalancedebalance%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et -module(rebar_xref_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, all/0, xref_test/1, xref_ignore_test/1, xref_dep_hook/1, xref_undef_behaviour/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). %% =================================================================== %% common_test callbacks %% =================================================================== suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(xref_dep_hook, Config) -> Src = filename:join([?config(data_dir, Config), "recursive"]), Dst = filename:join([?config(priv_dir, Config), "recursive"]), ok = rebar_file_utils:cp_r([Src], Dst), GlobalDir = filename:join([?config(priv_dir, Config), "cache"]), State = rebar_state:new([{base_dir, filename:join([Dst, "_build"])} ,{global_rebar_dir, GlobalDir} ,{root_dir, Dst}]), [{apps, Dst}, {state, State} | Config]; init_per_testcase(Case, Config) -> UpdConfig = rebar_test_utils:init_rebar_state(Config), AppDir = ?config(apps, UpdConfig), file:set_cwd(AppDir), Name = rebar_test_utils:create_random_name("xrefapp_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_empty_app(AppDir, Name, Vsn, [kernel, stdlib]), AppModules = [behaviour1, behaviour2, mymod, othermod, ignoremod, ignoremod2], [write_src_file(AppDir, Name, Module, ignore_xref(Case)) || Module <- AppModules], IgnoreMod = list_to_atom(Name ++ "_" ++ "ignoremod"), RebarConfig = [{erl_opts, [debug_info]}, {xref_ignores, [IgnoreMod]}, {xref_checks, [deprecated_function_calls,deprecated_functions, undefined_function_calls,undefined_functions, exports_not_used,locals_not_used]}], [{app_name, Name}, {rebar_config, RebarConfig} | UpdConfig]. end_per_testcase(_, _Config) -> ok. all() -> [xref_test, xref_ignore_test, xref_dep_hook, xref_undef_behaviour]. %% =================================================================== %% Test cases %% =================================================================== xref_test(Config) -> AppDir = ?config(apps, Config), State = ?config(state, Config), Name = ?config(app_name, Config), RebarConfig = ?config(rebar_config, Config), Result = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), ["xref"]), verify_results(xref_test, Name, Result). xref_ignore_test(Config) -> AppDir = ?config(apps, Config), State = ?config(state, Config), Name = ?config(app_name, Config), RebarConfig = ?config(rebar_config, Config), Result = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), ["xref"]), verify_results(xref_ignore_test, Name, Result). xref_dep_hook(Config) -> rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, []}). xref_undef_behaviour(Config) -> AppDir = ?config(apps, Config), State = ?config(state, Config), Name = ?config(app_name, Config), RebarConfig = ?config(rebar_config, Config), %% delete one of the behaviours, which should create new warnings delete_src_file(AppDir, Name, behaviour1), %% just ensure this does not crash Result = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), ["xref"]), verify_results(xref_undef_behaviour, Name, Result). %% =================================================================== %% Helper functions %% =================================================================== ignore_xref(xref_ignore_test) -> true; ignore_xref(_) -> false. verify_results(TestCase, AppName, Results) -> {error, {rebar_prv_xref, {xref_issues, XrefResults, QueryResults}}} = Results, verify_test_results(TestCase, AppName, XrefResults, QueryResults). verify_test_results(xref_test, AppName, XrefResults, _QueryResults) -> AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod"], [Behaviour1Mod, Behaviour2Mod, MyMod, OtherMod, SomeMod] = [list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules], UndefFuns = proplists:get_value(undefined_functions, XrefResults), UndefFunCalls = proplists:get_value(undefined_function_calls, XrefResults), LocalsNotUsed = proplists:get_value(locals_not_used, XrefResults), ExportsNotUsed = proplists:get_value(exports_not_used, XrefResults), DeprecatedFuns = proplists:get_value(deprecated_functions, XrefResults), DeprecatedFunCalls = proplists:get_value(deprecated_function_calls, XrefResults), ?assert(lists:member({SomeMod, notavailable, 1}, UndefFuns)), ?assert(lists:member({{OtherMod, somefunc, 0}, {SomeMod, notavailable, 1}}, UndefFunCalls)), ?assert(lists:member({MyMod, fdeprecated, 0}, DeprecatedFuns)), ?assert(lists:member({{OtherMod, somefunc, 0}, {MyMod, fdeprecated, 0}}, DeprecatedFunCalls)), ?assert(lists:member({MyMod, localfunc2, 0}, LocalsNotUsed)), ?assert(lists:member({Behaviour1Mod, behaviour_info, 1}, ExportsNotUsed)), ?assert(lists:member({Behaviour2Mod, behaviour_info, 1}, ExportsNotUsed)), ?assert(lists:member({MyMod, other2, 1}, ExportsNotUsed)), ?assert(lists:member({OtherMod, somefunc, 0}, ExportsNotUsed)), ?assertNot(lists:member({MyMod, bh1_a, 1}, ExportsNotUsed)), ?assertNot(lists:member({MyMod, bh1_b, 1}, ExportsNotUsed)), ?assertNot(lists:member({MyMod, bh2_a, 1}, ExportsNotUsed)), ?assertNot(lists:member({MyMod, bh2_b, 1}, ExportsNotUsed)), ok; verify_test_results(xref_undef_behaviour, AppName, XrefResults, _QueryResults) -> AppModules = ["behaviour2", "mymod", "othermod", "somemod"], [Behaviour2Mod, MyMod, OtherMod, SomeMod] = [list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules], UndefFuns = proplists:get_value(undefined_functions, XrefResults), UndefFunCalls = proplists:get_value(undefined_function_calls, XrefResults), LocalsNotUsed = proplists:get_value(locals_not_used, XrefResults), ExportsNotUsed = proplists:get_value(exports_not_used, XrefResults), DeprecatedFuns = proplists:get_value(deprecated_functions, XrefResults), DeprecatedFunCalls = proplists:get_value(deprecated_function_calls, XrefResults), ?assert(lists:member({SomeMod, notavailable, 1}, UndefFuns)), ?assert(lists:member({{OtherMod, somefunc, 0}, {SomeMod, notavailable, 1}}, UndefFunCalls)), ?assert(lists:member({MyMod, fdeprecated, 0}, DeprecatedFuns)), ?assert(lists:member({{OtherMod, somefunc, 0}, {MyMod, fdeprecated, 0}}, DeprecatedFunCalls)), ?assert(lists:member({MyMod, localfunc2, 0}, LocalsNotUsed)), ?assert(lists:member({Behaviour2Mod, behaviour_info, 1}, ExportsNotUsed)), ?assert(lists:member({MyMod, other2, 1}, ExportsNotUsed)), ?assert(lists:member({OtherMod, somefunc, 0}, ExportsNotUsed)), ?assert(lists:member({MyMod, bh1_a, 1}, ExportsNotUsed)), ?assert(lists:member({MyMod, bh1_b, 1}, ExportsNotUsed)), ?assertNot(lists:member({MyMod, bh2_a, 1}, ExportsNotUsed)), ?assertNot(lists:member({MyMod, bh2_b, 1}, ExportsNotUsed)), ok; verify_test_results(xref_ignore_test, AppName, XrefResults, _QueryResults) -> AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod", "ignoremod", "ignoremod2"], [_Behaviour1Mod, _Behaviour2Mod, _MyMod, _OtherMod, SomeMod, IgnoreMod, IgnoreMod2] = [list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules], UndefFuns = proplists:get_value(undefined_functions, XrefResults), ?assertNot(lists:keymember(undefined_function_calls, 1, XrefResults)), ?assertNot(lists:keymember(locals_not_used, 1, XrefResults)), ?assertNot(lists:keymember(exports_not_used, 1, XrefResults)), ?assertNot(lists:keymember(deprecated_functions, 1, XrefResults)), ?assertNot(lists:keymember(deprecated_function_calls, 1, XrefResults)), ?assertNot(lists:member({IgnoreMod, notavailable, 1}, UndefFuns)), ?assertNot(lists:member({IgnoreMod2, notavailable, 1}, UndefFuns)), ?assert(lists:member({SomeMod, notavailable, 1}, UndefFuns)), ok. write_src_file(Dir, AppName, Module, IgnoreXref) -> Erl = filename:join([Dir, "src", module_name(AppName, Module)]), ok = filelib:ensure_dir(Erl), ok = ec_file:write(Erl, get_module_body(Module, AppName, IgnoreXref)). delete_src_file(Dir, AppName, Module) -> Erl = filename:join([Dir, "src", module_name(AppName, Module)]), ok = file:delete(Erl). module_name(AppName, Module) -> lists:flatten([AppName, "_", atom_to_list(Module), ".erl"]). get_module_body(behaviour1, AppName, IgnoreXref) -> ["-module(", AppName, "_behaviour1).\n", "-export([behaviour_info/1]).\n", ["-ignore_xref([ignoremod,{behaviour_info,1}]).\n" || X <- [IgnoreXref], X =:= true], "behaviour_info(callbacks) -> [{bh1_a,1},{bh1_b,1}];\n", "behaviour_info(_Other) -> undefined.\n"]; get_module_body(behaviour2, AppName, IgnoreXref) -> ["-module(", AppName, "_behaviour2).\n", "-export([behaviour_info/1]).\n", ["-ignore_xref({behaviour_info,1}).\n" || X <- [IgnoreXref], X =:= true], "behaviour_info(callbacks) -> [{bh2_a,1},{bh2_b,1}];\n", "behaviour_info(_Other) -> undefined.\n"]; get_module_body(mymod, AppName, IgnoreXref) -> ["-module(", AppName, "_mymod).\n", "-export([bh1_a/1,bh1_b/1,bh2_a/1,bh2_b/1," "other1/1,other2/1,fdeprecated/0]).\n", ["-ignore_xref([{other2,1},{localfunc2,0},{fdeprecated,0}]).\n" || X <- [IgnoreXref], X =:= true], "-behaviour(", AppName, "_behaviour1).\n", % 2 behaviours "-behavior(", AppName, "_behaviour2).\n", "-deprecated({fdeprecated,0}).\n", % deprecated function "bh1_a(A) -> localfunc1(bh1_a, A).\n", % behaviour functions "bh1_b(A) -> localfunc1(bh1_b, A).\n", "bh2_a(A) -> localfunc1(bh2_a, A).\n", "bh2_b(A) -> localfunc1(bh2_b, A).\n", "other1(A) -> localfunc1(other1, A).\n", % regular exported functions "other2(A) -> localfunc1(other2, A).\n", "localfunc1(A, B) -> {A, B}.\n", % used local "localfunc2() -> ok.\n", % unused local "fdeprecated() -> ok.\n" % deprecated function ]; get_module_body(ignoremod, AppName, IgnoreXref) -> ["-module(", AppName, "_ignoremod).\n", "-export([]).\n", [["-ignore_xref(", AppName, "_ignoremod).\n"] || X <- [IgnoreXref], X =:= true], "localfunc1(A, B) -> {A, B}.\n", % used local "localfunc2() -> ok.\n", % unused local "fdeprecated() -> ok.\n" % deprecated function "undef_call() -> non_existent_mod:func().\n" % undef function call ]; get_module_body(ignoremod2, AppName, IgnoreXref) -> ["-module(", AppName, "_ignoremod2).\n", "-export([]).\n", [["-ignore_xref(", AppName, "_ignoremod2).\n"] || X <- [IgnoreXref], X =:= true], "localfunc1(A, B) -> {A, B}.\n", % used local "localfunc2() -> ok.\n", % unused local "fdeprecated() -> ok.\n" % deprecated function "undef_call() -> non_existent_mod:func().\n" % undef function call ]; get_module_body(othermod, AppName, IgnoreXref) -> ["-module(", AppName, "_othermod).\n", "-export([somefunc/0]).\n", [["-ignore_xref([{", AppName, "_somemod,notavailable,1},{somefunc,0}]).\n", "-ignore_xref({", AppName, "_mymod,fdeprecated,0}).\n"] || X <- [IgnoreXref], X =:= true], "somefunc() ->\n", " ", AppName, "_mymod:other1(arg),\n", " ", AppName, "_somemod:notavailable(arg),\n", " ", AppName, "_mymod:fdeprecated(),\n", " ", AppName, "_ignoremod:notavailable().\n"]. rebar3-3.18.0/test/rebar_dir_SUITE.erl0000644000232200023220000004053514164317745017737 0ustar debalancedebalance-module(rebar_dir_SUITE). -export([all/0, init_per_testcase/2, end_per_testcase/2]). -export([default_src_dirs/1, default_extra_src_dirs/1, default_all_src_dirs/1]). -export([src_dirs/1, alt_src_dir_nested/1, src_dirs_with_opts/1, extra_src_dirs/1, all_src_dirs/1]). -export([src_dir_opts/1, recursive/1]). -export([top_src_dirs/1]). -export([profile_src_dirs/1, profile_extra_src_dirs/1, profile_all_src_dirs/1]). -export([profile_src_dir_opts/1]). -export([retarget_path/1, alt_base_dir_abs/1, alt_base_dir_env_variable_abs/1, alt_base_dir_rel/1]). -export([global_cache_dir/1, default_global_cache_dir/1, overwrite_default_global_cache_dir/1]). -export([default_global_config/1, overwrite_default_global_config/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). all() -> [default_src_dirs, default_extra_src_dirs, default_all_src_dirs, src_dirs, alt_src_dir_nested, extra_src_dirs, all_src_dirs, src_dir_opts, recursive, profile_src_dirs, profile_extra_src_dirs, profile_all_src_dirs, profile_src_dir_opts, top_src_dirs, retarget_path, alt_base_dir_abs, alt_base_dir_env_variable_abs, alt_base_dir_rel, global_cache_dir, default_global_cache_dir, overwrite_default_global_cache_dir, default_global_config, overwrite_default_global_config]. init_per_testcase(default_global_cache_dir, Config) -> [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, _State} | Config] = rebar_test_utils:init_rebar_state(Config), NewState = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, NewState} | Config]; init_per_testcase(overwrite_default_global_cache_dir, Config) -> os:putenv("REBAR_CACHE_DIR", ?config(priv_dir, Config)), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, _State} | Config] = rebar_test_utils:init_rebar_state(Config), NewState = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, NewState} | Config]; init_per_testcase(default_global_config, Config) -> [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, _State} | Config] = rebar_test_utils:init_rebar_state(Config), NewState = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, NewState} | Config]; init_per_testcase(overwrite_default_global_config, Config) -> ConfDir = filename:join([?config(priv_dir, Config), "custom"]), ok = file:make_dir(ConfDir), os:putenv("REBAR_GLOBAL_CONFIG_DIR", ConfDir), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, _State} | Config] = rebar_test_utils:init_rebar_state(Config), NewState = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, NewState} | Config]; init_per_testcase(_, Config) -> C = rebar_test_utils:init_rebar_state(Config), AppDir = ?config(apps, C), Name1 = rebar_test_utils:create_random_name("app1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [kernel, stdlib]), [{app_one, Name1}, {app_two, Name2}] ++ C. end_per_testcase(_, _Config) -> ok. default_src_dirs(Config) -> {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), [] = rebar_dir:src_dirs(rebar_state:opts(State)), ["src"] = rebar_dir:src_dirs(rebar_state:opts(State), ["src"]). default_extra_src_dirs(Config) -> {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), [] = rebar_dir:extra_src_dirs(rebar_state:opts(State)), ["src"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), ["src"]). default_all_src_dirs(Config) -> {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), [] = rebar_dir:all_src_dirs(rebar_state:opts(State)), ["src", "test"] = rebar_dir:all_src_dirs(rebar_state:opts(State), ["src"], ["test"]). src_dirs(Config) -> RebarConfig = [{erl_opts, [{src_dirs, ["foo", "./bar", "bar", "bar/", "./bar/", "baz", "./", ".", "../", "..", "./../", "../.", ".././../"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), [".", "..", "../..", "bar", "baz", "foo"] = rebar_dir:src_dirs(rebar_state:opts(State)). alt_src_dir_nested(Config) -> RebarConfig = [{src_dirs, ["src", "alt/nested"]}], AppsDir = ?config(apps, Config), Name1 = ?config(app_one, Config), ModDir = filename:join([AppsDir, "apps", Name1, "alt", "nested"]), Mod = "-module(altmod). -export([main/0]). main() -> ok.", ec_file:mkdir_path(ModDir), ok = file:write_file(filename:join([ModDir, "altmod.erl"]), Mod), Ebin = filename:join([AppsDir, "_build", "default", "lib", Name1, "ebin", "altmod.beam"]), {ok, State} = rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{file, Ebin}]} ), ["alt/nested", "src"] = rebar_dir:src_dirs(rebar_state:opts(State)). src_dirs_with_opts(Config) -> RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar", "baz"]}, {src_dirs, [{"foo",[{recursive,false}]}, "qux"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State)). extra_src_dirs(Config) -> RebarConfig = [{erl_opts, [{extra_src_dirs, ["foo", "bar", "baz"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo"] = rebar_dir:extra_src_dirs(rebar_state:opts(State)). all_src_dirs(Config) -> RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}, {extra_src_dirs, ["baz", "qux"]}, {src_dirs, [{"foo", [{recursive,false}]}]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo", "qux"] = rebar_dir:all_src_dirs(rebar_state:opts(State)). src_dir_opts(Config) -> RebarConfig = [{erl_opts, [{src_dirs, [{"foo",[{recursive,true}]}, "bar"]}, {extra_src_dirs, ["baz", {"foo", [{recursive,false}]}]}, {src_dirs, [{"foo", [{recursive,false}]}]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), [{recursive,true}] = rebar_dir:src_dir_opts(rebar_state:opts(State), "foo"), [] = rebar_dir:src_dir_opts(rebar_state:opts(State), "bar"), [] = rebar_dir:src_dir_opts(rebar_state:opts(State), "nonexisting"). recursive(Config) -> RebarConfig1 = [{erl_opts, [{src_dirs, ["foo", "bar"]}, {extra_src_dirs, ["baz", {"foo", [{recursive,true}]}]}, {src_dirs, [{"foo", [{recursive,false}]}]}]}], {ok, State1} = rebar_test_utils:run_and_check(Config, RebarConfig1, ["compile"], return), false = rebar_dir:recursive(rebar_state:opts(State1), "foo"), true = rebar_dir:recursive(rebar_state:opts(State1), "bar"), RebarConfig2 = [{erlc_compiler,[{recursive,false}]}, {erl_opts,[{src_dirs,["foo",{"bar",[{recursive,true}]}]}]}], {ok, State2} = rebar_test_utils:run_and_check(Config, RebarConfig2, ["compile"], return), false = rebar_dir:recursive(rebar_state:opts(State2), "foo"), true = rebar_dir:recursive(rebar_state:opts(State2), "bar"), ok. top_src_dirs(Config) -> %% We can get the same result out of specifying src_dirs from the config root, %% not just the erl_opts RebarConfig = [{src_dirs, ["foo", "./bar", "bar", "bar/", "./bar/", "baz", "./", ".", "../", "..", "./../", "../.", ".././../"]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), [".", "..", "../..", "bar", "baz", "foo"] = rebar_dir:src_dirs(rebar_state:opts(State)). profile_src_dirs(Config) -> RebarConfig = [ {erl_opts, [{src_dirs, ["foo", "bar"]}]}, {profiles, [ {more, [{erl_opts, [{src_dirs, ["baz", "qux"]}]}]} ]} ], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), R = lists:sort(["foo", "bar", "baz", "qux"]), R = rebar_dir:src_dirs(rebar_state:opts(State)). profile_extra_src_dirs(Config) -> RebarConfig = [ {erl_opts, [{extra_src_dirs, ["foo", "bar"]}]}, {profiles, [ {more, [{erl_opts, [{extra_src_dirs, ["baz", "qux"]}]}]} ]} ], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), R = lists:sort(["foo", "bar", "baz", "qux"]), R = rebar_dir:extra_src_dirs(rebar_state:opts(State)). profile_all_src_dirs(Config) -> RebarConfig = [ {erl_opts, [{src_dirs, ["foo"]}, {extra_src_dirs, ["bar"]}]}, {profiles, [ {more, [{erl_opts, [{src_dirs, ["baz"]}, {extra_src_dirs, ["qux"]}]}]} ]} ], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), R = lists:sort(["foo", "bar", "baz", "qux"]), R = rebar_dir:all_src_dirs(rebar_state:opts(State)). profile_src_dir_opts(Config) -> RebarConfig = [ {erl_opts, [{src_dirs, ["foo"]}, {extra_src_dirs, [{"bar",[recursive]}]}]}, {profiles, [ {more, [{erl_opts, [{src_dirs, [{"bar",[{recursive,false}]}]}, {extra_src_dirs, ["qux"]}]}]} ]} ], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return), [{recursive,false}] = rebar_dir:src_dir_opts(rebar_state:opts(State),"bar"), {ok, State1} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), [{recursive,true}] = rebar_dir:src_dir_opts(rebar_state:opts(State1),"bar"). retarget_path(Config) -> {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), BaseDir = rebar_dir:base_dir(State), Name1 = ?config(app_one, Config), Name2 = ?config(app_two, Config), ?assertEqual(filename:join([BaseDir, "lib", Name1, "test"]), rebar_dir:retarget_path(State, filename:join([rebar_dir:root_dir(State), "apps", Name1, "test"]))), ?assertEqual(filename:join([BaseDir, "lib", Name2, "test"]), rebar_dir:retarget_path(State, filename:join([rebar_dir:root_dir(State), "apps", Name2, "test"]))), ?assertEqual(filename:join([BaseDir, "lib", Name1, "more_test"]), rebar_dir:retarget_path(State, filename:join([rebar_dir:root_dir(State), "apps", Name1, "more_test"]))), ?assertEqual(filename:join([BaseDir, "test"]), rebar_dir:retarget_path(State, filename:join([rebar_dir:root_dir(State), "test"]))), ?assertEqual(filename:join([BaseDir, "some_other_dir"]), rebar_dir:retarget_path(State, filename:join([rebar_dir:root_dir(State), "some_other_dir"]))), ?assertEqual("/somewhere/outside/the/project", rebar_dir:retarget_path(State, "/somewhere/outside/the/project")). alt_base_dir_abs(Config) -> AltName = lists:flatten(io_lib:format("~p", [os:timestamp()])), AltBaseDir = filename:join(?config(priv_dir, Config), AltName), RebarConfig = [{base_dir, AltBaseDir}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), BaseDir = rebar_dir:base_dir(State), ?assertEqual(filename:join(AltBaseDir, "default"), BaseDir), Name1 = ?config(app_one, Config), Name2 = ?config(app_two, Config), ?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name1, "ebin"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name1, "ebin", Name1++".app"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name1, "ebin", Name1++".beam"]))), ?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name2, "ebin"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".app"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".beam"]))). alt_base_dir_env_variable_abs(Config) -> AltName = lists:flatten(io_lib:format("~p", [os:timestamp()])), AltBaseDir = filename:join(?config(priv_dir, Config), AltName), RebarConfig = [], true = os:putenv("REBAR_BASE_DIR", AltBaseDir), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), true = os:unsetenv("REBAR_BASE_DIR"), BaseDir = rebar_dir:base_dir(State), ?assertEqual(filename:join(AltBaseDir, "default"), BaseDir), Name1 = ?config(app_one, Config), Name2 = ?config(app_two, Config), ?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name1, "ebin"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name1, "ebin", Name1++".app"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name1, "ebin", Name1++".beam"]))), ?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name2, "ebin"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".app"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".beam"]))). alt_base_dir_rel(Config) -> AltName = lists:flatten(io_lib:format("~p", [os:timestamp()])), AltBaseDir = filename:join("..", AltName), RebarConfig = [{base_dir, AltBaseDir}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), BaseDir = rebar_dir:base_dir(State), Name1 = ?config(app_one, Config), Name2 = ?config(app_two, Config), ?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name1, "ebin"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name1, "ebin", Name1++".app"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name1, "ebin", Name1++".beam"]))), ?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name2, "ebin"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".app"]))), ?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".beam"]))). global_cache_dir(Config) -> RebarConfig = [{erl_opts, []}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), DataDir = ?config(priv_dir, Config), Expected = filename:join([DataDir, "cache"]), ?assertEqual(Expected, rebar_dir:global_cache_dir(rebar_state:opts(State))). default_global_cache_dir(Config) -> RebarConfig = [{erl_opts, []}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), Expected = filename:join([rebar_dir:home_dir(), ".cache", "rebar3"]), ?assertEqual(Expected, rebar_dir:global_cache_dir(rebar_state:opts(State))). overwrite_default_global_cache_dir(Config) -> RebarConfig = [{erl_opts, []}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), Expected = ?config(priv_dir, Config), ?assertEqual(Expected, rebar_dir:global_cache_dir(rebar_state:opts(State))). default_global_config(Config) -> RebarConfig = [{erl_opts, []}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ConfDir = ?config(priv_dir, Config), Expected = filename:join([ConfDir, ".config", "rebar3", "rebar.config"]), ?assertEqual(Expected, rebar_dir:global_config(State)). overwrite_default_global_config(Config) -> RebarConfig = [{erl_opts, []}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), Expected = filename:join([os:getenv("REBAR_GLOBAL_CONFIG_DIR"), ".config", "rebar3", "rebar.config"]), rebar_dir:global_config(State), ?assertEqual(Expected, rebar_dir:global_config(State)). rebar3-3.18.0/test/rebar_opts_parser_SUITE.erl0000644000232200023220000000351414164317745021516 0ustar debalancedebalance-module(rebar_opts_parser_SUITE). -export([all/0, init_per_testcase/2]). -export([bad_arg_to_flag/1, missing_arg_to_flag/1]). -include_lib("common_test/include/ct.hrl"). all() -> [bad_arg_to_flag, missing_arg_to_flag]. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config, "opts_parser_"). bad_arg_to_flag(Config) -> ok = meck:new(getopt), ok = meck:expect(getopt, parse, fun(_, _) -> {error, {invalid_option_arg, {foo, "null"}}} end), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("bad_arg_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), {error, Error} = rebar_test_utils:run_and_check(Config, [], ["compile", "--foo=null"], return), true = meck:validate(getopt), ok = meck:unload(getopt), "Invalid argument null to option foo" = lists:flatten(Error). missing_arg_to_flag(Config) -> ok = meck:new(getopt), ok = meck:expect(getopt, parse, fun(_, _) -> {error, {missing_option_arg, foo}} end), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("missing_arg_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), {error, Error} = rebar_test_utils:run_and_check(Config, [], ["compile", "--foo"], return), true = meck:validate(getopt), ok = meck:unload(getopt), "Missing argument to option foo" = lists:flatten(Error).rebar3-3.18.0/test/rebar_src_dirs_SUITE.erl0000644000232200023220000003202414164317745020763 0ustar debalancedebalance-module(rebar_src_dirs_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, all/0, src_dirs_at_root/1, extra_src_dirs_at_root/1, src_dirs_in_erl_opts/1, extra_src_dirs_in_erl_opts/1, src_dirs_at_root_and_in_erl_opts/1, dupe_src_dirs_at_root_and_in_erl_opts/1, extra_src_dirs_at_root_and_in_erl_opts/1, build_basic_app/1, build_multi_apps/1, src_dir_takes_precedence_over_extra/1, src_dir_checkout_dep/1, app_src_info/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). end_per_testcase(_, _Config) -> ok. all() -> [src_dirs_at_root, extra_src_dirs_at_root, src_dirs_in_erl_opts, extra_src_dirs_in_erl_opts, src_dirs_at_root_and_in_erl_opts, dupe_src_dirs_at_root_and_in_erl_opts, extra_src_dirs_at_root_and_in_erl_opts, build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra, src_dir_checkout_dep, app_src_info]. src_dirs_at_root(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{src_dirs, ["foo", "bar", "baz"]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo"] = rebar_dir:src_dirs(rebar_state:opts(State), []). extra_src_dirs_at_root(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{extra_src_dirs, ["foo", "bar", "baz"]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), []). src_dirs_in_erl_opts(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar", "baz"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo"] = rebar_dir:src_dirs(rebar_state:opts(State), []). extra_src_dirs_in_erl_opts(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{extra_src_dirs, ["foo", "bar", "baz"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), []). src_dirs_at_root_and_in_erl_opts(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("src_dirs_root_erlopts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}], %% move the .app.src file to one of the subdirs, out of src/ filelib:ensure_dir(filename:join([AppDir, "qux", "fake"])), rebar_file_utils:mv(filename:join([AppDir, "src", Name ++ ".app.src"]), filename:join([AppDir, "qux", Name ++ ".app.src"])), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State), []), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), ok. dupe_src_dirs_at_root_and_in_erl_opts(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("dupe_src_dirs_root_erlopts_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}], %% move the .app.src file to one of the subdirs, out of src/ filelib:ensure_dir(filename:join([AppDir, "qux", "fake"])), filelib:ensure_dir(filename:join([AppDir, "foo", "fake"])), Src1 = filename:join([AppDir, "qux", Name ++ ".app.src"]), Src2 = filename:join([AppDir, "foo", Name ++ ".app.src"]), rebar_file_utils:mv(filename:join([AppDir, "src", Name ++ ".app.src"]), Src1), %% Then copy it over to create a conflict with dupes file:copy(Src1, Src2), {error, {rebar_prv_app_discovery, {multiple_app_files, [Src2, Src1]}}} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ok. extra_src_dirs_at_root_and_in_erl_opts(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{extra_src_dirs, ["foo", "bar"]}]}, {extra_src_dirs, ["baz", "qux"]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), ["bar", "baz", "foo", "qux"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), []). build_basic_app(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Extra = filename:join([AppDir, "extra", "extra.erl"]), ok = filelib:ensure_dir(Extra), Src = io_lib:format("-module(extra).~n-export([x/0]).~nx() -> ok.", []), ok = ec_file:write(Extra, Src), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), %% check that `extra.erl` was compiled to the `extra` dir ExtraOut = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]), true = filelib:is_file(filename:join([ExtraOut, "extra.beam"])), %% check that `extra.erl` is not in the `modules` key of the app {ok, App} = file:consult(filename:join([AppDir, "_build", "default", "lib", Name, "ebin", Name ++ ".app"])), [{application, _, KVs}] = App, Mods = proplists:get_value(modules, KVs), false = lists:member(extra, Mods). build_multi_apps(Config) -> AppDir = ?config(apps, Config), Name1 = rebar_test_utils:create_random_name("app1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [kernel, stdlib]), Extra1 = filename:join([AppDir, "apps", Name1, "extra", "extra1.erl"]), ok = filelib:ensure_dir(Extra1), Src1 = io_lib:format("-module(extra1).~n-export([x/0]).~nx() -> ok.", []), ok = ec_file:write(Extra1, Src1), Extra2 = filename:join([AppDir, "apps", Name2, "extra", "extra2.erl"]), ok = filelib:ensure_dir(Extra2), Src2 = io_lib:format("-module(extra2).~n-export([x/0]).~nx() -> ok.", []), ok = ec_file:write(Extra2, Src2), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}]} ), %% check that `extraX.erl` was compiled to the `ebin` dir ExtraOut1 = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]), true = filelib:is_file(filename:join([ExtraOut1, "extra1.beam"])), ExtraOut2 = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]), true = filelib:is_file(filename:join([ExtraOut2, "extra2.beam"])), %% check that `extraX.erl` is not in the `modules` key of the app {ok, App1} = file:consult(filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", Name1 ++ ".app"])), [{application, _, KVs1}] = App1, Mods1 = proplists:get_value(modules, KVs1), false = lists:member(extra1, Mods1), {ok, App2} = file:consult(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin", Name2 ++ ".app"])), [{application, _, KVs2}] = App2, Mods2 = proplists:get_value(modules, KVs2), false = lists:member(extra2, Mods2). src_dir_takes_precedence_over_extra(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Extra = filename:join([AppDir, "extra", "extra.erl"]), ok = filelib:ensure_dir(Extra), Src = io_lib:format("-module(extra).~n-export([x/0]).~nx() -> ok.", []), ok = ec_file:write(Extra, Src), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}, {extra_src_dirs, ["extra"]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), %% check that `extra.erl` was compiled to the `extra` dir ExtraOut = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]), true = filelib:is_file(filename:join([ExtraOut, "extra.beam"])), %% check that `extra.erl` is in the `modules` key of the app {ok, App} = file:consult(filename:join([AppDir, "_build", "default", "lib", Name, "ebin", Name ++ ".app"])), [{application, _, KVs}] = App, Mods = proplists:get_value(modules, KVs), true = lists:member(extra, Mods). src_dir_checkout_dep(Config) -> AppDir = ?config(apps, Config), AppName = rebar_test_utils:create_random_name("src_dir_checkout_app"), DepName = rebar_test_utils:create_random_name("src_dir_checkout_dep"), AtomDep = list_to_atom(DepName), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, AppName, Vsn, [kernel, stdlib]), RebarConfig = [{deps, [AtomDep]}], DepDir = filename:join([?config(checkouts, Config), DepName]), ct:pal("checkouts dir: ~p", [DepDir]), rebar_test_utils:create_app(DepDir, DepName, Vsn, [kernel, stdlib]), %% move the .app.src file to one of the subdirs, out of src/ rebar_file_utils:mv(filename:join([DepDir, "src"]), filename:join([DepDir, "qux"])), DepRebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}], file:write_file(filename:join([DepDir, "rebar.config"]), io_lib:format("~p.~n~p.~n", DepRebarConfig)), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{checkout, DepName}, {app, AppName}]} ), ok. app_src_info(Config) -> PrivDir = ?config(priv_dir, Config), AppName1 = rebar_test_utils:create_random_name("app_src_info"), AppDir1 = filename:join(PrivDir, AppName1), {ok, Info1} = rebar_app_info:new(AppName1, "1.0.0", AppDir1), AppSrc1 = filename:join([AppDir1, "src", AppName1 ++ ".app.src"]), ok = filelib:ensure_dir(AppSrc1), ok = file:write_file(AppSrc1, "[]."), ?assertEqual(AppSrc1, rebar_app_info:app_file_src(Info1)), AppName2 = rebar_test_utils:create_random_name("app_src_info"), AppDir2 = filename:join(PrivDir, AppName2), {ok, Info2Tmp} = rebar_app_info:new(AppName2, "1.0.0", AppDir2), Info2 = rebar_app_info:set(Info2Tmp, src_dirs, ["foo", "bar", "baz"]), AppSrc2 = filename:join([AppDir2, "bar", AppName2 ++ ".app.src"]), ok = filelib:ensure_dir(AppSrc2), ok = file:write_file(AppSrc2, "[]."), ?assertEqual(AppSrc2, rebar_app_info:app_file_src(Info2)), ok. rebar3-3.18.0/test/rebar_deps_SUITE.erl0000644000232200023220000006037614164317745020121 0ustar debalancedebalance-module(rebar_deps_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [sub_app_deps, newly_added_dep, newly_added_after_empty_lock, no_deps_empty_lock, http_proxy_settings, https_proxy_settings, http_os_proxy_settings, https_os_proxy_settings, semver_matching_lt, semver_matching_lte, semver_matching_gt, valid_version, top_override, {group, git}, {group, pkg}, deps_cmd_needs_update_called ]. groups() -> [{all, [], [flat, pick_highest_left, pick_highest_right, pick_smallest1, pick_smallest2, circular1, circular2, circular_skip]}, {git, [], [{group, all}]}, {pkg, [], [{group, all}]}]. init_per_suite(Config) -> application:start(meck), Config. end_per_suite(_Config) -> application:stop(meck). init_per_group(git, Config) -> [{deps_type, git} | Config]; init_per_group(pkg, Config) -> [{deps_type, pkg} | Config]; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. init_per_testcase(valid_version, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(semver_matching_lt, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(semver_matching_lte, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(semver_matching_gt, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(newly_added_after_empty_lock, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(no_deps_empty_lock, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(newly_added_dep, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(sub_app_deps, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(top_override, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(http_proxy_settings, Config) -> %% Create private rebar.config Priv = ?config(priv_dir, Config), GlobalDir = filename:join(Priv, "global"), GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), %% Insert proxy variables into config rebar_test_utils:create_config(GlobalConfigDir, [{http_proxy, "http://localhost:1234"} ]), rebar_test_utils:init_rebar_state(Config); init_per_testcase(https_proxy_settings, Config) -> SupportsHttpsProxy = case erlang:system_info(otp_release) of "R16"++_ -> true; "R"++_ -> false; _ -> true % 17 and up don't have a "R" in the version end, if not SupportsHttpsProxy -> {skip, https_proxy_unsupported_before_R16}; SupportsHttpsProxy -> %% Create private rebar.config Priv = ?config(priv_dir, Config), GlobalDir = filename:join(Priv, "global"), GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), %% Insert proxy variables into config rebar_test_utils:create_config(GlobalConfigDir, [{https_proxy, "http://localhost:1234"} ]), %% Add a bad value by default to show config overtakes default os:putenv("https_proxy", "unparseable-garbage"), rebar_test_utils:init_rebar_state(Config) end; init_per_testcase(http_os_proxy_settings, Config) -> %% Create private rebar.config Priv = ?config(priv_dir, Config), GlobalDir = filename:join(Priv, "global"), GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), %% Insert proxy variables into os env, but not config os:putenv("http_proxy", "http://localhost:1234"), rebar_test_utils:create_config(GlobalConfigDir, []), rebar_test_utils:init_rebar_state(Config); init_per_testcase(https_os_proxy_settings, Config) -> SupportsHttpsProxy = case erlang:system_info(otp_release) of "R16"++_ -> true; "R"++_ -> false; _ -> true % 17 and up don't have a "R" in the version end, if not SupportsHttpsProxy -> {skip, https_proxy_unsupported_before_R16}; SupportsHttpsProxy -> %% Create private rebar.config Priv = ?config(priv_dir, Config), GlobalDir = filename:join(Priv, "global"), GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), %% Insert proxy variables into os env, not in config os:putenv("https_proxy", "http://localhost:1234"), rebar_test_utils:create_config(GlobalConfigDir, []), rebar_test_utils:init_rebar_state(Config) end; init_per_testcase(deps_cmd_needs_update_called, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(Case, Config) -> {Deps, Warnings, Expect} = deps(Case), Expected = case Expect of {ok, List} -> {ok, format_expected_deps(List)}; {error, Reason} -> {error, Reason} end, DepsType = ?config(deps_type, Config), mock_warnings(), [{expect, Expected}, {warnings, Warnings} | setup_project(Case, Config, rebar_test_utils:expand_deps(DepsType, Deps))]. end_per_testcase(https_proxy_settings, Config) -> os:putenv("https_proxy", ""), meck:unload(rebar_dir), Config; end_per_testcase(http_proxy_settings, Config) -> meck:unload(rebar_dir), Config; end_per_testcase(http_os_proxy_settings, Config) -> os:putenv("http_proxy", ""), meck:unload(rebar_dir), Config; end_per_testcase(https_os_proxy_settings, Config) -> os:putenv("https_proxy", ""), meck:unload(rebar_dir), Config; end_per_testcase(_, Config) -> meck:unload(), Config. format_expected_deps(Deps) -> [case Dep of {N,V} -> {dep, N, V}; N -> {dep, N} end || Dep <- Deps]. %% format: %% {Spec, %% [Warning], %% {ok, Result} | {error, Reason}} %% %% Spec is a list of levelled dependencies of two possible forms: %% - {"Name", Spec} %% - {"Name", "Vsn", Spec} %% %% Warnings are going to match on mocked ?WARN(...) %% calls to be evaluated. An empty list means we do not care about %% warnings, not that no warnings will be printed. This means %% the list of warning isn't interpreted to be exhaustive, and more %% warnings may be generated than are listed. deps(flat) -> {[{"B", []}, {"C", []}], [], {ok, ["B", "C"]}}; deps(pick_highest_left) -> {[{"B", [{"C", "2.0.0", []}]}, {"C", "1.0.0", []}], [{"C","2.0.0"}], {ok, ["B", {"C", "1.0.0"}]}}; deps(pick_highest_right) -> {[{"B", "1.0.0", []}, {"C", [{"B", "2.0.0", []}]}], [{"B","2.0.0"}], {ok, [{"B","1.0.0"}, "C"]}}; deps(pick_smallest1) -> {[{"B", [{"D", "1.0.0", []}]}, {"C", [{"D", "2.0.0", []}]}], [{"D","2.0.0"}], %% we pick D1 because B < C {ok, ["B","C",{"D","1.0.0"}]}}; deps(pick_smallest2) -> {[{"C", [{"D", "2.0.0", []}]}, {"B", [{"D", "1.0.0", []}]}], [{"D","2.0.0"}], %% we pick D1 because B < C {ok, ["B","C",{"D","1.0.0"}]}}; deps(circular1) -> {[{"B", [{"A", []}]}, % A is the top-level app {"C", []}], [], {error, {rebar_prv_install_deps, {cycles, [[<<"A">>,<<"B">>]]}}}}; deps(circular2) -> {[{"B", [{"C", [{"B", []}]}]}, {"C", []}], [], {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}}; deps(circular_skip) -> %% Never spot the circular dep due to being to low in the deps tree %% in source deps {[{"B", [{"C", "2.0.0", [{"B", []}]}]}, {"C", "1.0.0", [{"D",[]}]}], [{"C","2.0.0"}], {ok, ["B", {"C","1.0.0"}, "D"]}}. setup_project(Case, Config0, Deps) -> DepsType = ?config(deps_type, Config0), %% spread packages across 3 repos randomly Repos = [<<"test-repo-1">>, <<"test-repo-2">>, <<"hexpm">>], Config = rebar_test_utils:init_rebar_state( [{repos, Repos} | Config0], atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_" ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]), {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {repos, Repos}]), [{rebarconfig, RebarConf} | Config]. mock_warnings() -> %% just let it do its thing, we check warnings through %% the call log. meck:new(rebar_log, [no_link, passthrough]). mock_rebar_fetch() -> meck:new(rebar_fetch, [no_link, passthrough]). %%% TESTS %%% flat(Config) -> run(Config). pick_highest_left(Config) -> run(Config). pick_highest_right(Config) -> run(Config). pick_smallest1(Config) -> run(Config). pick_smallest2(Config) -> run(Config). circular1(Config) -> run(Config). circular2(Config) -> run(Config). circular_skip(Config) -> run(Config). %% Test that a top-level application overtakes dependencies, and %% works even if said deps do not exist. top_override(Config) -> AppDir = ?config(apps, Config), ct:pal("dir: ~p", [AppDir]), Name1 = rebar_test_utils:create_random_name("sub_app1_"), Name2 = rebar_test_utils:create_random_name("sub_app2_"), SubAppsDir1 = filename:join([AppDir, "apps", Name1]), SubAppsDir2 = filename:join([AppDir, "apps", Name2]), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(SubAppsDir1, Name1, Vsn, [kernel, stdlib]), rebar_test_utils:create_app(SubAppsDir2, Name2, Vsn, [kernel, stdlib]), rebar_test_utils:create_config( SubAppsDir1, [{deps, [list_to_atom(Name2)]}] ), rebar_test_utils:create_config( SubAppsDir2, [{deps, [{list_to_atom(Name1), {git, "https://example.org", {branch, "master"}}}]}] ), rebar_test_utils:run_and_check( Config, [], ["compile"], {ok, [{app, Name1}, {app,Name2}]} ). %% Test that the deps of project apps that have their own rebar.config %% are included, but that top level rebar.config deps take precedence sub_app_deps(Config) -> AppDir = ?config(apps, Config), Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", []} ,{"b", "2.0.0", []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), SubAppsDir = filename:join([AppDir, "apps", Name]), SubDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "2.0.0", []}])), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(SubAppsDir, [{deps, SubDeps}]), TopDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}, {dep, "a"}, {dep, "b", "1.0.0"}]}). %% Newly added dependency after locking newly_added_dep(Config) -> AppDir = ?config(apps, Config), Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", [{"c", "1.0.0", []}]} ,{"c", "2.0.0", []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("app_"), Vsn = rebar_test_utils:create_random_vsn(), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}, {dep, "b", "1.0.0"}, {dep, "c", "1.0.0"}]}), %% Add a and c to top level TopDeps2 = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"c", "2.0.0", []} ,{"b", "1.0.0", []}])), {ok, RebarConfig2} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps2}])), LockFile = filename:join(AppDir, "rebar.lock"), RebarConfig3 = rebar_config:merge_locks(RebarConfig2, rebar_config:consult_lock_file(LockFile)), %% a should now be installed and c should not change rebar_test_utils:run_and_check( Config, RebarConfig3, ["compile"], {ok, [{app, Name}, {dep, "a"}, {dep, "b", "1.0.0"}, {dep, "c", "1.0.0"}]}). newly_added_after_empty_lock(Config) -> AppDir = ?config(apps, Config), Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("app_"), Vsn = rebar_test_utils:create_random_vsn(), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [])), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, []}), %% Add a and c to top level TopDeps2 = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}])), {ok, RebarConfig2} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps2}])), LockFile = filename:join(AppDir, "rebar.lock"), RebarConfig3 = rebar_config:merge_locks(RebarConfig2, rebar_config:consult_lock_file(LockFile)), %% a should now be installed and c should not change rebar_test_utils:run_and_check( Config, RebarConfig3, ["compile"], {ok, [{app, Name}, {dep, "a", "1.0.0"}]}). no_deps_empty_lock(Config) -> AppDir = ?config(apps, Config), Deps = rebar_test_utils:expand_deps(git, []), mock_git_resource:mock([{deps, Deps}]), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, Deps}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, []}), LockFile = filename:join(AppDir, "rebar.lock"), %% the lock file should exist {ok,_} = file:read_file_info(LockFile), %% and just in case, it should be empty ?assertEqual([], rebar_config:consult_lock_file(LockFile)), %% which means that merging that lock file with the current config %% returns the same config ?assertEqual(RebarConfig, rebar_config:merge_locks(RebarConfig, rebar_config:consult_lock_file(LockFile))). http_proxy_settings(_Config) -> %% Load config rebar_utils:set_httpc_options(), rebar3:init_config(), %% Assert variable is right ?assertEqual({ok,{{"localhost", 1234}, []}}, httpc:get_option(proxy, rebar)). https_proxy_settings(_Config) -> %% Load config rebar_utils:set_httpc_options(), rebar3:init_config(), %% Assert variable is right ?assertEqual({ok,{{"localhost", 1234}, []}}, httpc:get_option(https_proxy, rebar)). http_os_proxy_settings(_Config) -> %% Load config rebar_utils:set_httpc_options(), rebar3:init_config(), %% Assert variable is right ?assertEqual({ok,{{"localhost", 1234}, []}}, httpc:get_option(proxy, rebar)). https_os_proxy_settings(_Config) -> %% Load config rebar_utils:set_httpc_options(), rebar3:init_config(), %% Assert variable is right ?assertEqual({ok,{{"localhost", 1234}, []}}, httpc:get_option(https_proxy, rebar)). semver_matching_lt(_Config) -> MaxVsn = <<"0.2.0">>, Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>, <<"0.2.1">>], ?assertEqual({ok, <<"0.1.9">>}, rebar_packages:cmpl_(undefined, MaxVsn, Vsns, fun ec_semver:lt/2)). semver_matching_lte(_Config) -> MaxVsn = <<"0.2.0">>, Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>, <<"0.2.1">>], ?assertEqual({ok, <<"0.2.0">>}, rebar_packages:cmpl_(undefined, MaxVsn, Vsns, fun ec_semver:lte/2)). semver_matching_gt(_Config) -> MaxVsn = <<"0.2.0">>, Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>, <<"0.2.1">>], ?assertEqual({ok, <<"0.2.1">>}, rebar_packages:cmp_(undefined, MaxVsn, Vsns, fun ec_semver:gt/2)). semver_matching_gte(_Config) -> MaxVsn = <<"0.2.0">>, Vsns = [<<"0.1.7">>, <<"0.1.9">>, <<"0.1.8">>, <<"0.2.0">>], ?assertEqual({ok, <<"0.2.0">>}, rebar_packages:cmp_(undefined, MaxVsn, Vsns, fun ec_semver:gt/2)). valid_version(_Config) -> ?assert(rebar_packages:valid_vsn(<<"0.1">>)), ?assert(rebar_packages:valid_vsn(<<"0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<" 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<" 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"<0.1">>)), ?assert(rebar_packages:valid_vsn(<<"<0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"< 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"< 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<">0.1">>)), ?assert(rebar_packages:valid_vsn(<<">0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"> 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"> 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"<=0.1">>)), ?assert(rebar_packages:valid_vsn(<<"<=0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"<= 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"<= 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<">=0.1">>)), ?assert(rebar_packages:valid_vsn(<<">=0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<">= 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<">= 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"==0.1">>)), ?assert(rebar_packages:valid_vsn(<<"==0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"== 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"== 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"~>0.1">>)), ?assert(rebar_packages:valid_vsn(<<"~>0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"~> 0.1.0">>)), ?assert(rebar_packages:valid_vsn(<<"~> 0.1.0">>)), ?assertNot(rebar_packages:valid_vsn(<<"> 0.1.0 and < 0.2.0">>)), ok. run(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["install_deps"], ?config(expect, Config) ), check_warnings(warning_calls(), ?config(warnings, Config), ?config(deps_type, Config)). deps_cmd_needs_update_called(Config) -> mock_rebar_fetch(), AppDir = ?config(apps, Config), Deps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", [{"c", "1.0.0", []}]} ,{"c", "2.0.0", []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("app_"), Vsn = rebar_test_utils:create_random_vsn(), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])), rebar_test_utils:run_and_check(Config, RebarConfig, ["deps"], {ok, []}), [<<"b">>] = rebar_fetch_needs_update_calls_sorted(), %% Add c to top level TopDeps2 = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"c", "2.0.0", []} ,{"b", "1.0.0", []}])), {ok, RebarConfig2} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps2}])), rebar_test_utils:run_and_check(Config, RebarConfig2, ["deps"], {ok, []}), %% Only top level deps are checked for updates [<<"b">>, <<"b">>, <<"c">>] = rebar_fetch_needs_update_calls_sorted(), %% Lock deps rebar_test_utils:run_and_check(Config, RebarConfig2, ["lock"], {ok, []}), NeedsUpdate1 = rebar_fetch_needs_update_calls_sorted(), %% Switch c for a as top level deps TopDeps3 = rebar_test_utils:top_level_deps(rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", []}])), {ok, RebarConfig3} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps3}])), LockFile = filename:join(AppDir, "rebar.lock"), RebarConfig4 = rebar_config:merge_locks(RebarConfig3, rebar_config:consult_lock_file(LockFile)), rebar_test_utils:run_and_check(Config, RebarConfig4, ["deps"], {ok, []}), NeedsUpdate2 = lists:subtract(rebar_fetch_needs_update_calls_sorted(), NeedsUpdate1), %% B and C from lock file + install_deps and A, B and C from 'deps' [<<"a">>, <<"b">>, <<"b">>, <<"c">>, <<"c">>] = NeedsUpdate2. rebar_fetch_needs_update_calls_sorted() -> History = meck:history(rebar_fetch), DepsNames = [rebar_app_info:name(Dep) || {_, {rebar_fetch, needs_update, [Dep, _]}, _} <- History], lists:sort(DepsNames). warning_calls() -> History = meck:history(rebar_log), [{Str, Args} || {_, {rebar_log, log, [warn, Str, Args]}, _} <- History]. check_warnings(_, [], _) -> ok; check_warnings(Warns, [{Name, Vsn} | Rest], Type) -> ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]), ?assert(in_warnings(Type, Warns, Name, Vsn)), check_warnings(Warns, Rest, Type). in_warnings(git, Warns, NameRaw, VsnRaw) -> Name = iolist_to_binary(NameRaw), Vsn = iolist_to_binary([$",VsnRaw,$"]), 1 =< length([1 || {_, [[AppName, $\s,$(,$f,$r,$o,$m,$\s,[${,["git",$,, _URL, $,,[${,["tag",$,, AppVsn], $}]],$}],$)]]} <- Warns, iolist_to_binary(AppName) =:= Name, iolist_to_binary(AppVsn) =:= Vsn]); in_warnings(pkg, Warns, NameRaw, VsnRaw) -> Name = iolist_to_binary(NameRaw), Vsn = iolist_to_binary(VsnRaw), 1 =< length([1 || {_, [[AppName, $\s,$v, AppVsn]]} <- Warns, iolist_to_binary(AppName) =:= Name, iolist_to_binary(AppVsn) =:= Vsn]). rebar3-3.18.0/test/rebar_edoc_SUITE_data/0000755000232200023220000000000014164317745020351 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/0000755000232200023220000000000014164317745021077 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/0000755000232200023220000000000014164317745022042 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar2/0000755000232200023220000000000014164317745023476 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar2/src/0000755000232200023220000000000014164317745024265 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar2/src/bad_bar2_app.erl0000644000232200023220000000136214164317745027267 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar2 public API %% @end %%%------------------------------------------------------------------- -module(bad_bar2_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> bad_bar2_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar2/src/bad_bar2.app.src0000644000232200023220000000041214164317745027206 0ustar debalancedebalance{application, bad_bar2, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { bad_bar2_app, []}}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar2/src/bad_bar2.erl0000644000232200023220000000045214164317745026426 0ustar debalancedebalance%% @doc one docline is fine %% @doc a second docline causes a failure %% @doc if not, then a & causes a bad ref error. -module(bad_bar2). -export([bar2/0]). -export_type([barer2/0]). -type barer2() :: string(). % @doc Bar2 bars the bar2. -spec bar2() -> barer2(). bar2() -> "Barer2". rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar2/src/bad_bar2_sup.erl0000644000232200023220000000176614164317745027326 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar2 top level supervisor. %% @end %%%------------------------------------------------------------------- -module(bad_bar2_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar1/0000755000232200023220000000000014164317745023475 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar1/src/0000755000232200023220000000000014164317745024264 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar1/src/bad_bar1_app.erl0000644000232200023220000000136214164317745027265 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar1 public API %% @end %%%------------------------------------------------------------------- -module(bad_bar1_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> bad_bar1_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar1/src/bad_bar1_sup.erl0000644000232200023220000000176614164317745027324 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar1 top level supervisor. %% @end %%%------------------------------------------------------------------- -module(bad_bar1_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar1/src/bad_bar1.app.src0000644000232200023220000000041214164317745027204 0ustar debalancedebalance{application, bad_bar1, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { bad_bar1_app, []}}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_bar1/src/bad_bar1.erl0000644000232200023220000000025714164317745026427 0ustar debalancedebalance-module(bad_bar1). -export([bar1/0]). -export_type([barer1/0]). -type barer1() :: string(). % @doc Bar1 bars the bar. -spec bar1() -> barer1(). bar1() -> "Barer1". rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_foo/0000755000232200023220000000000014164317745023433 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_foo/src/0000755000232200023220000000000014164317745024222 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_foo/src/bad_foo_sup.erl0000644000232200023220000000176414164317745027216 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc foo top level supervisor. %% @end %%%------------------------------------------------------------------- -module(bad_foo_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_foo/src/bad_foo_app.erl0000644000232200023220000000135714164317745027165 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc foo public API %% @end %%%------------------------------------------------------------------- -module(bad_foo_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> bad_foo_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_foo/src/bad_foo.app.src0000644000232200023220000000044414164317745027105 0ustar debalancedebalance{application, bad_foo, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { bad_foo_app, []}}, {applications, [kernel, stdlib, bad_bar1, bad_bar2 ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/bad/apps/bad_foo/src/bad_foo.erl0000644000232200023220000000060514164317745026320 0ustar debalancedebalance-module(bad_foo). -export([foo/0, bar1/0, bar2/0]). -export_type([fooer/0]). -type fooer() :: string(). % @doc Foo function returns fooer. -spec foo() -> fooer(). foo() -> "fooer". % @doc Bar1 function returns barer1. -spec bar1() -> bar1:barer1(). bar1() -> bar1:bar1(). % @doc Bar2 functions returns barer2. -spec bar2() -> bar2:barer2(). bar2() -> bar2:bar2(). rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/0000755000232200023220000000000014164317745021134 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/0000755000232200023220000000000014164317745022077 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar2/0000755000232200023220000000000014164317745022725 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar2/src/0000755000232200023220000000000014164317745023514 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar2/src/bar2.app.src0000644000232200023220000000040214164317745025626 0ustar debalancedebalance{application, bar2, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { bar2_app, []}}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar2/src/bar2.erl0000644000232200023220000000025214164317745025045 0ustar debalancedebalance-module(bar2). -export([bar2/0]). -export_type([barer2/0]). -type barer2() :: string(). % @doc Bar2 bars the bar2. -spec bar2() -> barer2(). bar2() -> "Barer2".rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar2/src/bar2_app.erl0000644000232200023220000000135214164317745025707 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar2 public API %% @end %%%------------------------------------------------------------------- -module(bar2_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> bar2_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar2/src/bar2_sup.erl0000644000232200023220000000176214164317745025743 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar2 top level supervisor. %% @end %%%------------------------------------------------------------------- -module(bar2_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/0000755000232200023220000000000014164317745022662 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/rebar.config0000644000232200023220000000005414164317745025143 0ustar debalancedebalance{edoc_opts, [{title, "foo_custom_title"}]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/src/0000755000232200023220000000000014164317745023451 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/src/foo.erl0000644000232200023220000000057714164317745024751 0ustar debalancedebalance-module(foo). -export([foo/0, bar1/0, bar2/0]). -export_type([fooer/0]). -type fooer() :: string(). % @doc Foo function returns fooer. -spec foo() -> fooer(). foo() -> "fooer". % @doc Bar1 function returns barer1. -spec bar1() -> bar1:barer1(). bar1() -> bar1:bar1(). % @doc Bar2 functions returns barer2. -spec bar2() -> bar2:barer2(). bar2() -> bar2:bar2().rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/src/foo.app.src0000644000232200023220000000042014164317745025520 0ustar debalancedebalance{application, foo, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { foo_app, []}}, {applications, [kernel, stdlib, bar1, bar2 ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/src/foo_sup.erl0000644000232200023220000000176014164317745025633 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc foo top level supervisor. %% @end %%%------------------------------------------------------------------- -module(foo_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/foo/src/foo_app.erl0000644000232200023220000000134714164317745025605 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc foo public API %% @end %%%------------------------------------------------------------------- -module(foo_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> foo_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar1/0000755000232200023220000000000014164317745022724 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar1/src/0000755000232200023220000000000014164317745023513 5ustar debalancedebalancerebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar1/src/bar1.app.src0000644000232200023220000000040214164317745025624 0ustar debalancedebalance{application, bar1, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { bar1_app, []}}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar1/src/bar1_app.erl0000644000232200023220000000135214164317745025705 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar1 public API %% @end %%%------------------------------------------------------------------- -module(bar1_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> bar1_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar1/src/bar1.erl0000644000232200023220000000025114164317745025042 0ustar debalancedebalance-module(bar1). -export([bar1/0]). -export_type([barer1/0]). -type barer1() :: string(). % @doc Bar1 bars the bar. -spec bar1() -> barer1(). bar1() -> "Barer1".rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/apps/bar1/src/bar1_sup.erl0000644000232200023220000000176214164317745025741 0ustar debalancedebalance%%%------------------------------------------------------------------- %% @doc bar1 top level supervisor. %% @end %%%------------------------------------------------------------------- -module(bar1_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== rebar3-3.18.0/test/rebar_edoc_SUITE_data/foo/rebar.config0000644000232200023220000000007714164317745023422 0ustar debalancedebalance{edoc_opts, [{title, "forced wrong title to be overridden"}]}. rebar3-3.18.0/test/rebar_pkg_SUITE_data/0000755000232200023220000000000014164317745020220 5ustar debalancedebalancerebar3-3.18.0/test/rebar_pkg_SUITE_data/badpkg-1.0.0.tar0000644000232200023220000002400014164317745022606 0ustar debalancedebalanceCHECKSUM0000664000175000017500000000010113346507563012143 0ustar tristantristanB14E3718B33F8124E98004433193509EC6660F6CA03302657CAB8785751D77A0 contents.tar.gz0000664000175000017500000000260412524662766014020 0ustar tristantristaneSUXmo6gCI᪶;0fbIr (YRr"ߑWf`puآx<ǓH͢<O&쬣NkAivnylZtҩ5e)W?%J1[_iX31߷ nIvsUz+lM§g<&нNx2a}IlvdۭI]ρ,+1(>vi ~d.]&-b)9%(^ru'.*!s%C)*g*HT>[DuR\T$8 )W*P^$ب 8*IS 9k+zR'W>9[˄C]ע! yuid4ȸ>Z``,Ы;PK"E*Z'5.Q *D96J77ؙG7l \rT%z)׹G$MBȡC#k}Fc2nhɀ @z!q؈8,_w#xkkcuĆ퇬?qltXBh%uC|%\k7C=jC&i?|l8ti`L Xl_'80GvLIӑvi& d$pys@K|?I@d`1*)c7 ጹ!8d{BVG C5B=Z+p5k> S @0c ]POZX@1U,1GNzELsc6L"=d`L}VP^';_gfWm+* fci3Z<Rphcpr}EMe5W=qqiNoB;-W9OM*Az*n)_B S?W^mNwiyZsղĎV?ƭ` Z6n,?kE¾A,{u[s_nKVp§"'9VQyg% KVHs%t[{T[ź}jFʞb,'N]ρUD>[4!4ٮ2+DQF5j0(metadata.config0000664000175000017500000000007113346500423013757 0ustar tristantristan{<<"app">>, <<"badpkg">>}. {<<"version">>, <<"1.0.0">>}. VERSION0000664000175000017500000000000113346501171012052 0ustar tristantristan3rebar3-3.18.0/test/rebar_pkg_SUITE_data/goodpkg-1.0.0.tar0000644000232200023220000002400014164317745023010 0ustar debalancedebalanceCHECKSUM0000664000175000017500000000010113346501013012123 0ustar tristantristan12726BDE1F65583A0817A7E8AADCA73F03FD8CB06F01E6CD29117C4A0DA0AFCF contents.tar.gz0000664000175000017500000000260412524662766014020 0ustar tristantristaneSUXmo6gCI᪶;0fbIr (YRr"ߑWf`puآx<ǓH͢<O&쬣NkAivnylZtҩ5e)W?%J1[_iX31߷ nIvsUz+lM§g<&нNx2a}IlvdۭI]ρ,+1(>vi ~d.]&-b)9%(^ru'.*!s%C)*g*HT>[DuR\T$8 )W*P^$ب 8*IS 9k+zR'W>9[˄C]ע! yuid4ȸ>Z``,Ы;PK"E*Z'5.Q *D96J77ؙG7l \rT%z)׹G$MBȡC#k}Fc2nhɀ @z!q؈8,_w#xkkcuĆ퇬?qltXBh%uC|%\k7C=jC&i?|l8ti`L Xl_'80GvLIӑvi& d$pys@K|?I@d`1*)c7 ጹ!8d{BVG C5B=Z+p5k> S @0c ]POZX@1U,1GNzELsc6L"=d`L}VP^';_gfWm+* fci3Z<Rphcpr}EMe5W=qqiNoB;-W9OM*Az*n)_B S?W^mNwiyZsղĎV?ƭ` Z6n,?kE¾A,{u[s_nKVp§"'9VQyg% KVHs%t[{T[ź}jFʞb,'N]ρUD>[4!4ٮ2+DQF5j0(metadata.config0000664000175000017500000000007213346500302013754 0ustar tristantristan{<<"app">>, <<"goodpkg">>}. {<<"version">>, <<"1.0.0">>}. VERSION0000664000175000017500000000000112524717303012055 0ustar tristantristan3rebar3-3.18.0/test/rebar_pkg_SUITE_data/badindexchk-1.0.0.tar0000644000232200023220000002400014164317745023622 0ustar debalancedebalanceCHECKSUM0000664000175000017500000000010113346506232012133 0ustar tristantristan7B2CBED315C89F3126B5BF553DD7FF0FB5FE94B064888DD1B095CE8BF4B6A16A contents.tar.gz0000664000175000017500000000260412524662766014020 0ustar tristantristaneSUXmo6gCI᪶;0fbIr (YRr"ߑWf`puآx<ǓH͢<O&쬣NkAivnylZtҩ5e)W?%J1[_iX31߷ nIvsUz+lM§g<&нNx2a}IlvdۭI]ρ,+1(>vi ~d.]&-b)9%(^ru'.*!s%C)*g*HT>[DuR\T$8 )W*P^$ب 8*IS 9k+zR'W>9[˄C]ע! yuid4ȸ>Z``,Ы;PK"E*Z'5.Q *D96J77ؙG7l \rT%z)׹G$MBȡC#k}Fc2nhɀ @z!q؈8,_w#xkkcuĆ퇬?qltXBh%uC|%\k7C=jC&i?|l8ti`L Xl_'80GvLIӑvi& d$pys@K|?I@d`1*)c7 ጹ!8d{BVG C5B=Z+p5k> S @0c ]POZX@1U,1GNzELsc6L"=d`L}VP^';_gfWm+* fci3Z<Rphcpr}EMe5W=qqiNoB;-W9OM*Az*n)_B S?W^mNwiyZsղĎV?ƭ` Z6n,?kE¾A,{u[s_nKVp§"'9VQyg% KVHs%t[{T[ź}jFʞb,'N]ρUD>[4!4ٮ2+DQF5j0(metadata.config0000664000175000017500000000007613346500001013754 0ustar tristantristan{<<"app">>, <<"badindexchk">>}. {<<"version">>, <<"1.0.0">>}. VERSION0000664000175000017500000000000112524717303012055 0ustar tristantristan3rebar3-3.18.0/test/rebar_file_utils_SUITE.erl0000644000232200023220000003434514164317745021322 0ustar debalancedebalance-module(rebar_file_utils_SUITE). -export([all/0, groups/0, init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2, raw_tmpdir/1, empty_tmpdir/1, simple_tmpdir/1, multi_tmpdir/1, reset_nonexistent_dir/1, reset_empty_dir/1, reset_dir/1, path_from_ancestor/1, canonical_path/1, absolute_path/1, normalized_path/1, resolve_link/1, split_dirname/1, mv_warning_is_ignored/1, mv_dir/1, mv_file_same/1, mv_file_diff/1, mv_file_dir_same/1, mv_file_dir_diff/1, mv_no_clobber/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). -define(TMPDIR, "/test"). all() -> [{group, tmpdir}, {group, reset_dir}, {group, mv}, path_from_ancestor, canonical_path, absolute_path, normalized_path, resolve_link, split_dirname, mv_warning_is_ignored]. groups() -> [{tmpdir, [], [raw_tmpdir, empty_tmpdir, simple_tmpdir, multi_tmpdir]}, {reset_dir, [], [reset_nonexistent_dir, reset_empty_dir, reset_dir]}, {mv, [], [mv_dir, mv_file_same, mv_file_diff, mv_file_dir_same, mv_file_dir_diff, mv_no_clobber]}]. init_per_group(reset_dir, Config) -> TmpDir = rebar_file_utils:system_tmpdir(["rebar_file_utils_SUITE", "resettable"]), [{tmpdir, TmpDir} | Config]; init_per_group(tmpdir, Config) -> PreviousTmpDir = os:getenv("TMPDIR"), os:putenv("TMPDIR", ?TMPDIR), [{previous_tmp, PreviousTmpDir} | Config]; init_per_group(_, Config) -> Config. end_per_group(tmpdir, Config) -> case ?config(previous_tmp, Config) of false -> os:unsetenv("TMPDIR"); Val -> os:putenv("TMPDIR", Val) end, Config; end_per_group(_, Config) -> Config. init_per_testcase(Test, Config) -> case os:type() of {win32, _} -> case lists:member(Test, [resolve_link, mv_warning_is_ignored]) of true -> {skip, "broken in windows"}; false -> Config end; _ -> Config end. end_per_testcase(_Test, Config) -> Config. raw_tmpdir(_Config) -> case rebar_file_utils:system_tmpdir() of ?TMPDIR -> ok; "./tmp" -> ok end. empty_tmpdir(_Config) -> case rebar_file_utils:system_tmpdir([]) of ?TMPDIR -> ok; "./tmp" -> ok end. simple_tmpdir(_Config) -> case rebar_file_utils:system_tmpdir(["test"]) of ?TMPDIR ++ "/test" -> ok; "./tmp/test" -> ok end. multi_tmpdir(_Config) -> case rebar_file_utils:system_tmpdir(["a", "b", "c"]) of ?TMPDIR ++ "/a/b/c" -> ok; "./tmp/a/b/c" -> ok end. reset_nonexistent_dir(Config) -> TmpDir = ?config(tmpdir, Config), _ = ec_file:remove(TmpDir, [recursive]), ?assertNot(filelib:is_dir(TmpDir)), ok = rebar_file_utils:reset_dir(TmpDir), ?assert(filelib:is_dir(TmpDir)), {ok, []} = rebar_utils:list_dir(TmpDir). reset_empty_dir(Config) -> TmpDir = ?config(tmpdir, Config), _ = ec_file:remove(TmpDir, [recursive]), _ = filelib:ensure_dir(filename:join([TmpDir, "dummy.beam"])), ?assert(filelib:is_dir(TmpDir)), ok = rebar_file_utils:reset_dir(TmpDir), ?assert(filelib:is_dir(TmpDir)), {ok, []} = rebar_utils:list_dir(TmpDir). reset_dir(Config) -> TmpDir = ?config(tmpdir, Config), _ = ec_file:remove(TmpDir, [recursive]), _ = filelib:ensure_dir(filename:join([TmpDir, "dummy.beam"])), ?assert(filelib:is_dir(TmpDir)), lists:foreach(fun(Name) -> file:write_file(filename:join([TmpDir, Name]), <<>>) end, ["a", "b", "c"]), lists:foreach(fun(File) -> ?assert(filelib:is_file(filename:join([TmpDir, File]))) end, ["a", "b", "c"]), ok = rebar_file_utils:reset_dir(TmpDir), ?assert(filelib:is_dir(TmpDir)), {ok, []} = rebar_utils:list_dir(TmpDir). path_from_ancestor(_Config) -> ?assertEqual({ok, "foo/bar/baz"}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/")), ?assertEqual({ok, "bar/baz"}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/foo")), ?assertEqual({ok, "bar"}, rebar_file_utils:path_from_ancestor("foo/bar", "foo")), ?assertEqual({ok, "bar"}, rebar_file_utils:path_from_ancestor("foo/bar/", "foo/")), ?assertEqual({error, badparent}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/qux")), ?assertEqual({error, badparent}, rebar_file_utils:path_from_ancestor("/foo/bar/baz", "/foo/bar/baz/qux")). canonical_path(_Config) -> %% We find the root so that the name works both on unix-likes and %% with Windows. Root = case os:type() of {win32, _} -> filename:nativename(filename:absname("/")); % C:\, with proper drive _ -> "/" end, ?assertEqual(filename:nativename(Root), rebar_file_utils:canonical_path("/")), ?assertEqual(filename:nativename(Root), rebar_file_utils:canonical_path("/../../..")), ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/bar/..")), ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/../foo")), ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/.")), ?assertEqual(Root ++ "foo", rebar_file_utils:canonical_path("/foo/./.")), ?assertEqual(filename:nativename(Root ++ "foo/bar"), rebar_file_utils:canonical_path("/foo/./bar")). absolute_path(_Config) -> %% We find the root so that the name works both on unix-likes and %% with Windows. Starting on OTP-22, filename:join/1 drops the drive letter, %% and split/1 and absname both normalize c:\\ to c:/ -- going onwards, we %% start normalizing the same way as well to prevent issues. Root = case os:type() of {win32, _} -> filename:absname(filename:nativename("/")); % C:\, with proper drive _ -> "/" end, ?assertEqual(filename:absname(Root), rebar_file_utils:absolute_path("/")), ?assertEqual(Root ++ "foo", rebar_file_utils:absolute_path("/foo")), % casoscon ../ o ./ {ok, Cwd} = file:get_cwd(), ?assertEqual(Cwd, rebar_file_utils:absolute_path("./")), ?assertEqual(Cwd ++ "/foo", rebar_file_utils:absolute_path("./foo")), ?assertEqual(Cwd ++ "/foo/bar", rebar_file_utils:absolute_path("foo/bar")). normalized_path(_Config) -> %% We find the root so that the name works both on unix-likes and %% with Windows. Starting on OTP-22, filename:join/1 drops the drive letter, %% and split/1 and absname both normalize c:\\ to c:/ -- going onwards, we %% start normalizing the same way as well to prevent issues. Root = case os:type() of {win32, _} -> filename:absname(filename:nativename("/")); % c:/, with proper drive _ -> "/" end, ?assertEqual(Root, rebar_file_utils:normalized_path("/")), ?assertEqual("../..", rebar_file_utils:normalized_path("/../../..")), ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/bar/..")), ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/../foo")), ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/.")), ?assertEqual(Root ++ "foo", rebar_file_utils:normalized_path("/foo/./.")), ?assertEqual(Root ++ "foo/bar", rebar_file_utils:normalized_path("/foo/./bar")). resolve_link(_Config) -> TmpDir = rebar_file_utils:system_tmpdir( ["rebar_file_utils_SUITE", "resolve_link"]), Link = filename:join(TmpDir, "link"), Target = filename:join(TmpDir, "link-target"), ec_file:remove(TmpDir, [recursive]), ok = filelib:ensure_dir(Target), ok = file:write_file(Target, <<>>), ok = file:make_symlink(Target, Link), ?assertEqual(Target, rebar_file_utils:resolve_link(Link)). split_dirname(_Config) -> ?assertEqual({".", ""}, rebar_file_utils:split_dirname("")), ?assertEqual({"/", ""}, rebar_file_utils:split_dirname("/")), ?assertEqual({"/", "foo"}, rebar_file_utils:split_dirname("/foo")), ?assertEqual({".", "foo"}, rebar_file_utils:split_dirname("foo")), ?assertEqual({"/foo", "bar"}, rebar_file_utils:split_dirname("/foo/bar")), ?assertEqual({"foo", "bar"}, rebar_file_utils:split_dirname("foo/bar")). mv_warning_is_ignored(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, sh, fun("mv ding dong", _) -> {ok, "Warning"} end), ok = rebar_file_utils:mv("ding", "dong"), meck:unload(rebar_utils). %%% Ensure Windows & Unix operations to move files mv_dir(Config) -> %% Move a directory to another one location PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_dir), SrcDir = filename:join(BaseDir, "src/"), ec_file:mkdir_p(SrcDir), ?assert(filelib:is_dir(SrcDir)), %% empty dir movement DstDir1 = filename:join(BaseDir, "dst1/"), ?assertNot(filelib:is_dir(DstDir1)), ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir1)), ?assert(filelib:is_dir(DstDir1)), %% move files from dir to empty dir F1 = filename:join(SrcDir, "file1"), F2 = filename:join(SrcDir, "subdir/file2"), filelib:ensure_dir(F2), file:write_file(F1, "hello"), file:write_file(F2, "world"), DstDir2 = filename:join(BaseDir, "dst2/"), D2F1 = filename:join(DstDir2, "file1"), D2F2 = filename:join(DstDir2, "subdir/file2"), ?assertNot(filelib:is_dir(DstDir2)), ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir2)), ?assert(filelib:is_file(D2F1)), ?assert(filelib:is_file(D2F2)), %% move files from dir to existing dir moves it to %% a subdir filelib:ensure_dir(F2), file:write_file(F1, "hello"), file:write_file(F2, "world"), DstDir3 = filename:join(BaseDir, "dst3/"), D3F1 = filename:join(DstDir3, "src/file1"), D3F2 = filename:join(DstDir3, "src/subdir/file2"), ec_file:mkdir_p(DstDir3), ?assert(filelib:is_dir(DstDir3)), ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir3)), ?assertNot(filelib:is_file(F1)), ?assertNot(filelib:is_file(F2)), ?assert(filelib:is_file(D3F1)), ?assert(filelib:is_file(D3F2)), ?assertNot(filelib:is_dir(SrcDir)), ok. mv_file_same(Config) -> %% Move a file from a directory to the other without renaming PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_same), SrcDir = filename:join(BaseDir, "src/"), ec_file:mkdir_p(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), ec_file:mkdir_p(DstDir), Dst = filename:join(DstDir, "file"), ?assertEqual(ok, rebar_file_utils:mv(F, Dst)), ?assert(filelib:is_file(Dst)), ?assertNot(filelib:is_file(F)), ok. mv_file_diff(Config) -> %% Move a file from a directory to another one while renaming %% into a pre-existing file PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_diff), SrcDir = filename:join(BaseDir, "src/"), ec_file:mkdir_p(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), ec_file:mkdir_p(DstDir), Dst = filename:join(DstDir, "file-rename"), file:write_file(Dst, "not-the-right-content"), ?assert(filelib:is_file(Dst)), ?assertEqual(ok, rebar_file_utils:mv(F, Dst)), ?assert(filelib:is_file(Dst)), ?assertEqual({ok, <<"hello">>}, file:read_file(Dst)), ?assertNot(filelib:is_file(F)), ok. mv_file_dir_same(Config) -> %% Move a file to a directory without renaming PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_dir_same), SrcDir = filename:join(BaseDir, "src/"), ec_file:mkdir_p(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), ec_file:mkdir_p(DstDir), Dst = filename:join(DstDir, "file"), ?assert(filelib:is_dir(DstDir)), ?assertEqual(ok, rebar_file_utils:mv(F, DstDir)), ?assert(filelib:is_file(Dst)), ?assertNot(filelib:is_file(F)), ok. mv_file_dir_diff(Config) -> %% Move a file to a directory while renaming PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_dir_diff), SrcDir = filename:join(BaseDir, "src/"), ec_file:mkdir_p(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), ec_file:mkdir_p(DstDir), Dst = filename:join(DstDir, "file-rename"), ?assert(filelib:is_dir(DstDir)), ?assertNot(filelib:is_file(Dst)), ?assertEqual(ok, rebar_file_utils:mv(F, Dst)), ?assert(filelib:is_file(Dst)), ?assertNot(filelib:is_file(F)), ok. mv_no_clobber(Config) -> %% Moving a file while renaming does not clobber other files PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_no_clobber), SrcDir = filename:join(BaseDir, "src/"), ec_file:mkdir_p(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), FBad = filename:join(SrcDir, "file-alt"), file:write_file(FBad, "wrong-data"), DstDir = filename:join(BaseDir, "dst/"), ec_file:mkdir_p(DstDir), Dst = filename:join(DstDir, "file-alt"), DstBad = filename:join(DstDir, "file"), file:write_file(DstBad, "wrong-data"), ?assert(filelib:is_file(F)), ?assert(filelib:is_file(FBad)), ?assert(filelib:is_dir(DstDir)), ?assertNot(filelib:is_file(Dst)), ?assert(filelib:is_file(DstBad)), ?assertEqual(ok, rebar_file_utils:mv(F, Dst)), ?assert(filelib:is_file(Dst)), ?assertNot(filelib:is_file(F)), ?assert(filelib:is_file(DstBad)), ?assert(filelib:is_file(FBad)), ?assertEqual({ok, <<"hello">>}, file:read_file(Dst)), ?assertEqual({ok, <<"wrong-data">>}, file:read_file(FBad)), ?assertEqual({ok, <<"wrong-data">>}, file:read_file(DstBad)), ok. mk_base_dir(BasePath, Name) -> {_,_,Micro} = os:timestamp(), Index = integer_to_list(Micro), Path = filename:join(BasePath, atom_to_list(Name) ++ Index), ec_file:mkdir_p(Path), Path. rebar3-3.18.0/test/rebar_edoc_SUITE.erl0000644000232200023220000001227314164317745020071 0ustar debalancedebalance-module(rebar_edoc_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). all() -> [multiapp, multiapp_macros, error_survival]. init_per_testcase(multiapp, Config) -> application:load(rebar), DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("multiapp"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), ec_file:copy(filename:join([DataDir, "foo"]), AppsDir, [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {state, State}, {name, Name} | Config]; init_per_testcase(multiapp_macros, Config) -> application:load(rebar), DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("multiapp_macros"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), ec_file:copy(filename:join([DataDir, "foo"]), AppsDir, [recursive]), ok = ec_file:remove(filename:join([AppsDir, "apps", "foo"]), [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {state, State}, {name, Name} | Config]; init_per_testcase(error_survival, Config) -> application:load(rebar), DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("error_survival"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), ec_file:copy(filename:join([DataDir, "bad"]), AppsDir, [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {state, State}, {name, Name} | Config]. end_per_testcase(_, Config) -> Config. multiapp(Config) -> %% With an empty config (no `dir'), links are being processed RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["edoc"], {ok, []}), %% validate that all doc entries are generated and links work AppsDir = ?config(apps, Config), ct:pal("AppsDir: ~s", [AppsDir]), ?assert(file_content_matches( filename:join([AppsDir, "apps", "bar1", "doc", "bar1.html"]), "barer1")), ?assert(file_content_matches( filename:join([AppsDir, "apps", "bar2", "doc", "bar2.html"]), "barer2")), %% Links are in place for types ?assert(file_content_matches( filename:join([AppsDir, "apps", "foo", "doc", "foo.html"]), "barer1")), ?assert(file_content_matches( filename:join([AppsDir, "apps", "foo", "doc", "foo.html"]), "apps/bar1/doc/bar1.html")), %% Options such from rebar.config in the app themselves are %% respected ?assert(file_content_matches( filename:join([AppsDir, "apps", "foo", "doc", "overview-summary.html"]), "foo_custom_title" )), ok. multiapp_macros(Config) -> RebarConfig = [{edoc_opts, [ preprocess, {macros, [{m1, x1}, {m2, x2}]}, {def, [{d1, "1"}, {d2, "1"}]} ]}], AppConfig = {edoc_opts, [ {preprocess, true}, {macros, [{m2, f2}, {m3, f3}]}, {def, [{d2, "2"}, {d3, "2"}]} ]}, DebugModule = " -module(debug). -ifndef(m1). -define(m1,z1). -endif. -ifndef(m2). -define(m2,z2). -endif. -ifndef(m3). -define(m3,z3). -endif. -export([?m1 /0, ?m2 /0, ?m3 /0]). %% @doc %% d1:{@d1} %% d2:{@d2} %% d3:{@d3} %% @end ?m1 () -> ok. ?m2 () -> ok. ?m3 () -> ok. ", AppsDir = ?config(apps, Config), ct:pal("AppsDir: ~s", [AppsDir]), ok = file:write_file(filename:join([AppsDir, "apps", "bar1", "rebar.config"]), io_lib:format("~p.~n", [AppConfig])), ok = file:write_file(filename:join([AppsDir, "apps", "bar1", "src", "debug.erl"]), DebugModule), rebar_test_utils:run_and_check(Config, RebarConfig, ["edoc"], {ok, []}), DocFile = filename:join([AppsDir, "apps", "bar1", "doc", "debug.html"]), ?assert(file_content_matches(DocFile, "d1:1")), % config layered ?assert(file_content_matches(DocFile, "d2:2")), ?assert(file_content_matches(DocFile, "d3:2")), ?assert(file_content_matches(DocFile, "x1/0")), % elided in config drop ?assert(file_content_matches(DocFile, "f2/0")), ?assert(file_content_matches(DocFile, "f3/0")), ok. error_survival(Config) -> RebarConfig = [], rebar_test_utils:run_and_check( Config, RebarConfig, ["edoc"], {error,{rebar_prv_edoc,{app_failed,"bad_bar2"}}} ), ok. file_content_matches(Path, Regex) -> case file:read_file(Path) of {ok, Bin} -> nomatch =/= re:run(Bin, Regex); {error, Reason} -> Reason end. rebar3-3.18.0/test/rebar_templater_SUITE.erl0000644000232200023220000000377314164317745021161 0ustar debalancedebalance%% coding:utf-8 -module(rebar_templater_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [ consult_template_latin1_test, consult_template_utf8_test ]. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(Case, Config) when Case =:= consult_template_latin1_test; Case =:= consult_template_utf8_test -> %% Generate UCS string containing all printable characters of latin-1 area. Description = lists:seq(16#A1, 16#AC) ++ lists:seq(16#AE, 16#FE), Expected = [{description, Description}], SampleTemplate = "{description, \"" ++ Description ++ "\"}.\n", Path = generate_sample_template_file(Case, SampleTemplate, Config), [{template_file_path, Path}, {expected, Expected} | Config]; init_per_testcase(_Case, Config) -> Config. end_per_testcase(_Case, _Config) -> ok. generate_sample_template_file(Case, Content, Config) -> CaseName = atom_to_list(Case), {Encoding, EncodingName} = case string:str(CaseName, "latin1") of 0 -> {utf8, "utf-8"}; _ -> {latin1, "latin-1"} end, PrivDir = ?config(priv_dir, Config), Path = filename:join([PrivDir, CaseName ++ ".template"]), {ok, FH} = file:open(Path, [write, {encoding, Encoding}]), try io:format(FH, "%% coding:~s~n~s", [EncodingName, Content]) after file:close(FH) end, Path. consult_template_test_common(Config) -> Expected = ?config(expected, Config), Path = ?config(template_file_path, Config), Result = rebar_templater:consult_template([], file, Path), ?assertEqual(Expected, Result), ok. consult_template_latin1_test() -> [{doc, "parse test for latin1 template file"}]. consult_template_latin1_test(Config) -> consult_template_test_common(Config). consult_template_utf8_test() -> [{doc, "parse test for utf8 template file"}]. consult_template_utf8_test(Config) -> consult_template_test_common(Config). rebar3-3.18.0/test/rebar_test_utils.erl0000644000232200023220000005771614164317745020420 0ustar debalancedebalance-module(rebar_test_utils). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -export([init_rebar_state/1, init_rebar_state/2, run_and_check/3, run_and_check/4, check_results/3, check_results/4]). -export([expand_deps/2, flat_deps/1, top_level_deps/1]). -export([create_app/4, create_plugin/4, create_eunit_app/4, create_empty_app/4, create_config/2, create_config/3, package_app/4]). -export([create_random_name/1, create_random_vsn/0, write_src_file/2, random_element/1]). %%%%%%%%%%%%%% %%% Public %%% %%%%%%%%%%%%%% %% @doc {@see init_rebar_state/2} init_rebar_state(Config) -> init_rebar_state(Config, "apps_dir1_"). %% @doc Takes a common test config and a name (string) and sets up %% a basic OTP app directory with a pre-configured rebar state to %% run tests with. init_rebar_state(Config, Name) -> application:load(rebar), DataDir = ?config(priv_dir, Config), AppsDir = filename:join([DataDir, create_random_name(Name)]), CheckoutsDir = filename:join([AppsDir, "_checkouts"]), ok = ec_file:mkdir_p(AppsDir), ok = ec_file:mkdir_p(CheckoutsDir), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), GlobalDir = filename:join([DataDir, "cache"]), Repos = proplists:get_value(repos, Config, []), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} ,{global_rebar_dir, GlobalDir} ,{hex, [{repos, [#{name => R} || R <- Repos]}]} ,{root_dir, AppsDir}]), [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, State} | Config]. %% @doc Takes common test config, a rebar config ([] if empty), a command to %% run ("install_deps", "compile", etc.), and a list of expected applications %% and/or dependencies to be present, and verifies whether they are all in %% place. %% %% The expectation list takes elements of the form: %% - `{app, Name :: string()}': checks that the app is properly built. %% - `{dep, Name :: string()}': checks that the dependency has been fetched. %% Ignores the build status of the dependency. %% - `{dep, Name :: string(), Vsn :: string()}': checks that the dependency %% has been fetched, and that a given version has been chosen. Useful to %% test for conflict resolution. Also ignores the build status of the %% dependency. %% %% This function assumes `init_rebar_state/1-2' has run before, in order to %% fetch the `apps' and `state' values from the CT config. run_and_check(Config, RebarConfig, Command, Expect) -> %% Assumes init_rebar_state has run first AppDir = ?config(apps, Config), State = ?config(state, Config), try Res = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), Command), case Expect of {error, Reason} -> ?assertEqual({error, Reason}, Res); {ok, Expected} -> {ok, _} = Res, check_results(AppDir, Expected, "*"), Res; {ok, Expected, ProfileRun} -> {ok, _} = Res, check_results(AppDir, Expected, ProfileRun), Res; return -> Res end catch rebar_abort when Expect =:= rebar_abort -> rebar_abort end. run_and_check(Config, Command, Expect) -> %% Assumes init_rebar_state has run first AppDir = ?config(apps, Config), {ok, Cwd} = file:get_cwd(), try ok = file:set_cwd(AppDir), Res = rebar3:run(Command), case Expect of {error, Reason} -> ?assertEqual({error, Reason}, Res); {ok, Expected} -> {ok, _} = Res, check_results(AppDir, Expected, "*"), Res; {ok, Expected, ProfileRun} -> {ok, _} = Res, check_results(AppDir, Expected, ProfileRun), Res; return -> Res end catch rebar_abort when Expect =:= rebar_abort -> rebar_abort after ok = file:set_cwd(Cwd) end. %% @doc Creates a dummy application including: %% - src/.erl %% - src/.app.src %% And returns a `rebar_app_info' object. create_app(AppDir, Name, Vsn, Deps) -> write_src_file(AppDir, Name ++ ".erl"), write_src_file(AppDir, "not_a_real_src_" ++ Name ++ ".erl"), write_app_src_file(AppDir, Name, Vsn, Deps), rebar_app_info:new(Name, Vsn, AppDir, Deps). %% @doc Creates a dummy plugin including: %% - src/.erl %% - src/.app.src %% And returns a `rebar_app_info' object. create_plugin(AppDir, Name, Vsn, Deps) -> write_plugin_file(AppDir, Name ++ ".erl"), write_src_file(AppDir, "not_a_real_src_" ++ Name ++ ".erl"), write_app_src_file(AppDir, Name, Vsn, Deps), rebar_app_info:new(Name, Vsn, AppDir, Deps). %% @doc Creates a dummy application including: %% - src/.erl %% - src/.app.src %% - test/_tests.erl %% And returns a `rebar_app_info' object. create_eunit_app(AppDir, Name, Vsn, Deps) -> write_eunitized_src_file(AppDir, Name), write_eunit_suite_file(AppDir, Name), write_app_src_file(AppDir, Name, Vsn, Deps), rebar_app_info:new(Name, Vsn, AppDir, Deps). %% @doc Creates a dummy application including: %% - ebin/.app %% And returns a `rebar_app_info' object. create_empty_app(AppDir, Name, Vsn, Deps) -> write_app_file(AppDir, Name, Vsn, Deps), rebar_app_info:new(Name, Vsn, AppDir, Deps). %% @doc Creates a rebar.config file. The function accepts a list of terms, %% each of which will be dumped as a consult file. For example, the list %% `[a, b, c]' will return the consult file `a. b. c.'. create_config(AppDir, Contents) -> ConfFilename = filename:join([AppDir, "rebar.config"]), create_config(AppDir, ConfFilename, Contents). create_config(_AppDir, ConfFilename, Contents) -> ok = filelib:ensure_dir(ConfFilename), Config = lists:flatten([io_lib:fwrite("~p.~n", [Term]) || Term <- Contents]), ok = ec_file:write(ConfFilename, Config), ConfFilename. %% @doc Util to create a random variation of a given name. create_random_name(Name) -> Name ++ erlang:integer_to_list(rand:uniform(1000000)). %% @doc Util to create a random variation of a given version. create_random_vsn() -> lists:flatten([erlang:integer_to_list(rand:uniform(100)), ".", erlang:integer_to_list(rand:uniform(100)), ".", erlang:integer_to_list(rand:uniform(100))]). expand_deps(_, []) -> []; expand_deps(git_subdir, [{Name, Deps} | Rest]) -> Dep = {Name, {git_subdir, "https://example.org/user/"++Name++".git", {branch, "master"}, filename:join("appsubdir", Name)}}, [{Dep, expand_deps(git_subdir, Deps)} | expand_deps(git_subdir, Rest)]; expand_deps(git_subdir, [{Name, Vsn, Deps} | Rest]) -> Dep = {Name, Vsn, {git_subdir, "https://example.org/user/"++Name++".git", {tag, Vsn}, filename:join("appsubdir", Name)}}, [{Dep, expand_deps(git_subdir, Deps)} | expand_deps(git_subdir, Rest)]; expand_deps(git, [{Name, Deps} | Rest]) -> Dep = {Name, ".*", {git, "https://example.org/user/"++Name++".git", "master"}}, [{Dep, expand_deps(git, Deps)} | expand_deps(git, Rest)]; expand_deps(git, [{Name, Vsn, Deps} | Rest]) -> Dep = {Name, Vsn, {git, "https://example.org/user/"++Name++".git", {tag, Vsn}}}, [{Dep, expand_deps(git, Deps)} | expand_deps(git, Rest)]; expand_deps(pkg, [{Name, Deps} | Rest]) -> Dep = {pkg, Name, "0.0.0", undefined, undefined}, [{Dep, expand_deps(pkg, Deps)} | expand_deps(pkg, Rest)]; expand_deps(pkg, [{Name, Vsn, Deps} | Rest]) -> Dep = {pkg, Name, Vsn, undefined, undefined}, [{Dep, expand_deps(pkg, Deps)} | expand_deps(pkg, Rest)]; expand_deps(mixed, [{Name, Deps} | Rest]) -> Dep = if hd(Name) >= $a, hd(Name) =< $z -> {pkg, rebar_string:uppercase(Name), "0.0.0", undefined, undefined} ; hd(Name) >= $A, hd(Name) =< $Z -> {Name, ".*", {git, "https://example.org/user/"++Name++".git", "master"}} end, [{Dep, expand_deps(mixed, Deps)} | expand_deps(mixed, Rest)]; expand_deps(mixed, [{Name, Vsn, Deps} | Rest]) -> Dep = if hd(Name) >= $a, hd(Name) =< $z -> {pkg, rebar_string:uppercase(Name), Vsn, undefined, undefined} ; hd(Name) >= $A, hd(Name) =< $Z -> {Name, Vsn, {git, "https://example.org/user/"++Name++".git", {tag, Vsn}}} end, [{Dep, expand_deps(mixed, Deps)} | expand_deps(mixed, Rest)]. %% Source deps can depend on both source and package dependencies; %% package deps can only depend on package deps. %% For things to work we have to go down the dep tree and find all %% lineages of pkg deps and return them, whereas the source deps %% can be left as is. flat_deps(Deps) -> flat_deps(Deps, [], []). flat_deps([], Src, Pkg) -> {Src, Pkg}; flat_deps([{{pkg, Name, Vsn, undefined, undefined}, PkgDeps} | Rest], Src, Pkg) -> Current = {{iolist_to_binary(Name), iolist_to_binary(Vsn)}, top_level_deps(PkgDeps)}, {[], FlatPkgDeps} = flat_deps(PkgDeps), flat_deps(Rest, Src, Pkg ++ [Current | FlatPkgDeps]); flat_deps([{{Name,_Vsn,Ref}, Deps} | Rest], Src, Pkg) -> Current = {{Name,vsn_from_ref(Ref)}, top_level_deps(Deps)}, {FlatDeps, FlatPkgDeps} = flat_deps(Deps), flat_deps(Rest, Src ++ [Current | FlatDeps], Pkg ++ FlatPkgDeps); flat_deps([{{Name,Ref}, Deps} | Rest], Src, Pkg) -> Current = {{Name,vsn_from_ref(Ref)}, top_level_deps(Deps)}, {FlatDeps, FlatPkgDeps} = flat_deps(Deps), flat_deps(Rest, Src ++ [Current | FlatDeps], Pkg ++ FlatPkgDeps). vsn_from_ref({git, _, {_, Vsn}}) -> Vsn; vsn_from_ref({git, _, Vsn}) -> Vsn; vsn_from_ref({git_subdir, _, {_, Vsn}, _}) -> Vsn; vsn_from_ref({git_subdir, _, Vsn, _}) -> Vsn. top_level_deps([]) -> []; top_level_deps([{{pkg, Name, Vsn, undefined, undefined}, _} | Deps]) -> [{list_to_atom(Name), Vsn} | top_level_deps(Deps)]; top_level_deps([{{Name, Vsn, Ref}, _} | Deps]) -> [{list_to_atom(Name), Vsn, Ref} | top_level_deps(Deps)]. %%%%%%%%%%%%%%% %%% Helpers %%% %%%%%%%%%%%%%%% check_results(AppDir, Expected, ProfileRun) -> State = rebar_state:new(), check_results(AppDir, Expected, ProfileRun, State). check_results(AppDir, Expected, ProfileRun, State) -> BuildDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "lib", "*"])), BuildSubDirs = [D || D <- filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "lib", "*", "*", "*"])), filelib:is_dir(D)], PluginDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "plugins", "*"])), GlobalPluginDirs = filelib:wildcard(filename:join([AppDir, "global", "plugins", "*"])), CheckoutsDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "checkouts", "*"])), LockFile = filename:join([AppDir, "rebar.lock"]), Locks = lists:flatten(rebar_config:consult_lock_file(LockFile)), InvalidApps = rebar_app_discover:find_apps(BuildDirs, invalid, State), ValidApps = rebar_app_discover:find_apps(BuildDirs, valid, State), InvalidDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- InvalidApps], ValidDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- ValidApps], Deps = rebar_app_discover:find_apps(BuildDirs, all, State), SubDeps = rebar_app_discover:find_apps(BuildSubDirs, all, State), DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps], SubDirDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- SubDeps], Checkouts = rebar_app_discover:find_apps(CheckoutsDirs, all, State), CheckoutsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Checkouts], Plugins = rebar_app_discover:find_apps(PluginDirs, all, State), PluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Plugins], GlobalPlugins = rebar_app_discover:find_apps(GlobalPluginDirs, all, State), GlobalPluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- GlobalPlugins], lists:foreach( fun({app, Name}) -> ct:pal("App Name: ~p", [Name]), case lists:keyfind(Name, 1, DepsNames) of false -> error({app_not_found, Name}); {Name, _App} -> ok end ; ({app, Name, invalid}) -> ct:pal("Invalid Name: ~p", [Name]), case lists:keyfind(Name, 1, InvalidDepsNames) of false -> error({app_not_found, Name}); {Name, _App} -> ok end ; ({app, Name, valid}) -> ct:pal("Valid Name: ~p", [Name]), case lists:keyfind(Name, 1, ValidDepsNames) of false -> error({app_not_found, Name}); {Name, _App} -> ok end ; ({dep_not_exist, Name}) -> ct:pal("Dep Not Exist Name: ~p", [Name]), case lists:keyfind(Name, 1, DepsNames) of false -> ok; {Name, _App} -> error({app_found, Name}) end ; ({app_not_exist, Name}) -> ct:pal("App Not Exist Name: ~p", [Name]), case lists:keyfind(Name, 1, DepsNames) of false -> ok; {Name, _App} -> error({app_found, Name}) end ; ({checkout, Name}) -> ct:pal("Checkout Name: ~p", [Name]), ?assertNotEqual(false, lists:keyfind(Name, 1, CheckoutsNames)) ; ({dep, Name}) -> ct:pal("Dep Name: ~p", [Name]), ?assertNotEqual(false, lists:keyfind(Name, 1, DepsNames)) ; ({dep, Name, Vsn}) -> ct:pal("Dep Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(Name, 1, DepsNames) of false -> error({dep_not_found, Name}); {Name, App} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(rebar_app_info:original_vsn(App))) end ; ({subdir_dep, Name}) -> ct:pal("Subdir Dep Name: ~p", [Name]), ?assertNotEqual(false, lists:keyfind(Name, 1, SubDirDepsNames)) ; ({subdir_dep, Name, Vsn}) -> ct:pal("Subdir Dep Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(Name, 1, SubDirDepsNames) of false -> error({dep_not_found, Name}); {Name, App} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(rebar_app_info:original_vsn(App))) end ; ({plugin, Name}) -> ct:pal("Plugin Name: ~p", [Name]), ?assertNotEqual(false, lists:keyfind(Name, 1, PluginsNames)) ; ({plugin, Name, Vsn}) -> ct:pal("Plugin Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(Name, 1, PluginsNames) of false -> error({plugin_not_found, Name}); {Name, App} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(rebar_app_info:original_vsn(App))) end ; ({global_plugin, Name}) -> ct:pal("Global Plugin Name: ~p", [Name]), ?assertNotEqual(false, lists:keyfind(Name, 1, GlobalPluginsNames)) ; ({global_plugin, Name, Vsn}) -> ct:pal("Global Plugin Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(Name, 1, GlobalPluginsNames) of false -> error({global_plugin_not_found, Name}); {Name, App} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(rebar_app_info:original_vsn(App))) end ; ({lock, Name}) -> ct:pal("Lock Name: ~p", [Name]), ?assertNotEqual(false, lists:keyfind(iolist_to_binary(Name), 1, Locks)) ; ({lock, Name, Vsn}) -> ct:pal("Lock Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(iolist_to_binary(Name), 1, Locks) of false -> error({lock_not_found, Name}); {_LockName, {pkg, _, LockVsn, _InnerHash, OuterHash}, _} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(LockVsn)), ?assertNotEqual(undefined, OuterHash); {_LockName, {_, _, {ref, LockVsn}}, _} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(LockVsn)) end ; ({lock, pkg, Name, Vsn}) -> ct:pal("Pkg Lock Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(iolist_to_binary(Name), 1, Locks) of false -> error({lock_not_found, Name}); {_LockName, {pkg, _, LockVsn, _InnerHash, OuterHash}, _} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(LockVsn)), ?assertNotEqual(undefined, OuterHash); {_LockName, {_, _, {ref, LockVsn}}, _} -> error({source_lock, {Name, LockVsn}}) end ; ({lock, src, Name, Vsn}) -> ct:pal("Src Lock Name: ~p, Vsn: ~p", [Name, Vsn]), case lists:keyfind(iolist_to_binary(Name), 1, Locks) of false -> error({lock_not_found, Name}); {_LockName, {pkg, _, LockVsn, _}, _} -> error({pkg_lock, {Name, LockVsn}}); {_LockName, {_, _, {ref, LockVsn}}, _} -> ?assertEqual(iolist_to_binary(Vsn), iolist_to_binary(LockVsn)) end ; ({release, Name, Vsn, ExpectedDevMode}) -> ct:pal("Release: ~p-~ts", [Name, Vsn]), {ok, Cwd} = file:get_cwd(), try file:set_cwd(AppDir), [ReleaseDir] = filelib:wildcard(filename:join([AppDir, "_build", "*", "rel"])), LibDir = filename:join([ReleaseDir, Name, "lib"]), {ok, RelLibs} = rebar_utils:list_dir(LibDir), IsSymLinkFun = fun(X) -> ec_file:is_symlink(filename:join(LibDir, X)) end, DevMode = lists:all(IsSymLinkFun, RelLibs), ?assertEqual(ExpectedDevMode, DevMode), ?assert(ec_file:exists(filename:join([ReleaseDir, Name, "releases", Vsn]))), %% throws not_found if it doesn't exist ok catch _ -> ct:fail(release_not_found) after file:set_cwd(Cwd) end ; ({tar, Name, Vsn}) -> ct:pal("Tarball: ~ts-~ts", [Name, Vsn]), Tarball = filename:join([AppDir, "_build", "rel", Name, Name++"-"++Vsn++".tar.gz"]), ?assertNotEqual([], filelib:is_file(Tarball)) ; ({file, Filename}) -> ct:pal("Filename: ~ts", [Filename]), ?assert(filelib:is_file(Filename)) ; ({dir, Dirname}) -> ct:pal("Directory: ~ts", [Dirname]), ?assert(filelib:is_dir(Dirname)) end, Expected). write_plugin_file(Dir, Name) -> Erl = filename:join([Dir, "src", Name]), ok = filelib:ensure_dir(Erl), ok = ec_file:write(Erl, plugin_src_file(Name)). write_src_file(Dir, Name) -> Erl = filename:join([Dir, "src", Name]), ok = filelib:ensure_dir(Erl), ok = ec_file:write(Erl, erl_src_file(Name)). write_eunitized_src_file(Dir, Name) -> Erl = filename:join([Dir, "src", "not_a_real_src_" ++ Name ++ ".erl"]), ok = filelib:ensure_dir(Erl), ok = ec_file:write(Erl, erl_eunitized_src_file("not_a_real_src_" ++ Name ++ ".erl")). write_eunit_suite_file(Dir, Name) -> Erl = filename:join([Dir, "test", "not_a_real_src_" ++ Name ++ "_tests.erl"]), ok = filelib:ensure_dir(Erl), ok = ec_file:write(Erl, erl_eunit_suite_file("not_a_real_src_" ++ Name ++ ".erl")). write_app_file(Dir, Name, Version, Deps) -> Filename = filename:join([Dir, "ebin", Name ++ ".app"]), ok = filelib:ensure_dir(Filename), ok = ec_file:write_term(Filename, get_app_metadata(ec_cnv:to_list(Name), Version, Deps)). write_app_src_file(Dir, Name, Version, Deps) -> Filename = filename:join([Dir, "src", Name ++ ".app.src"]), ok = filelib:ensure_dir(Filename), ok = ec_file:write_term(Filename, get_app_metadata(ec_cnv:to_list(Name), Version, Deps)). erl_src_file(Name) -> io_lib:format("-module('~s').\n" "-export([main/0]).\n" "main() -> ok.\n", [filename:basename(Name, ".erl")]). plugin_src_file(Name) -> io_lib:format("-module('~s').\n" "-export([init/1, do/1]).\n" "init(State) -> \n" "Provider = providers:create([\n" "{name, '~s'},\n" "{module, '~s'}\n" "]),\n" "{ok, rebar_state:add_provider(State, Provider)}.\n" "do(State) -> {ok, State}.\n", [filename:basename(Name, ".erl"), filename:basename(Name, ".erl"), filename:basename(Name, ".erl")]). erl_eunitized_src_file(Name) -> io_lib:format("-module('~s').\n" "-export([main/0]).\n" "main() -> ok.\n" "-ifdef(TEST).\n" "-include_lib(\"eunit/include/eunit.hrl\").\n" "some_test_() -> ?_assertEqual(ok, main()).\n" "-endif.\n", [filename:basename(Name, ".erl")]). erl_eunit_suite_file(Name) -> BaseName = filename:basename(Name, ".erl"), io_lib:format("-module('~s_tests').\n" "-compile(export_all).\n" "-ifndef(some_define).\n" "-define(some_define, false).\n" "-endif.\n" "-ifdef(TEST).\n" "-include_lib(\"eunit/include/eunit.hrl\").\n" "some_test_() -> ?_assertEqual(ok, ~s:main()).\n" "define_test_() -> ?_assertEqual(true, ?some_define).\n" "-endif.\n", [BaseName, BaseName]). get_app_metadata(Name, Vsn, Deps) -> {application, erlang:list_to_atom(Name), [{description, ""}, {vsn, Vsn}, {modules, []}, {included_applications, []}, {registered, []}, {applications, Deps}]}. package_app(AppDir, DestDir, PkgName, PkgVsn) -> AppSrc = filename:join(AppDir, "src"), {ok, Fs} = rebar_utils:list_dir(AppSrc), Files = lists:zip([filename:join("src", F) || F <- Fs], [filename:join(AppSrc,F) || F <- Fs]), Metadata = #{<<"app">> => list_to_binary(PkgName), <<"version">> => list_to_binary(PkgVsn)}, {ok, #{tarball := Tarball, outer_checksum := <>}} = r3_hex_tarball:create(Metadata, Files), Name = PkgName++"-"++PkgVsn++".tar", Archive = filename:join(DestDir, Name), file:write_file(Archive, Tarball), <> = crypto:hash(md5, Tarball), Checksum1 = list_to_binary( rebar_string:uppercase( lists:flatten(io_lib:format("~64.16.0b", [Checksum])))), {Checksum1, E}. random_element(Repos) -> Index = rand:uniform(length(Repos)), lists:nth(Index, Repos). rebar3-3.18.0/test/rebar_pkg_alias_SUITE.erl0000644000232200023220000003046014164317745021107 0ustar debalancedebalance-module(rebar_pkg_alias_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). -include("rebar.hrl"). all() -> [same_alias, diff_alias, diff_alias_vsn, transitive_alias%% , %% transitive_hash_mismatch ]. %% {uuid, {pkg, uuid}} = uuid %% {uuid, {pkg, alias}} = uuid on disk %% another run should yield the same lock file without error init_per_suite(Config) -> Config. %% mock_config(?MODULE, Config). end_per_suite(Config) -> Config. %% unmock_config(Config). init_per_testcase(same_alias, Config0) -> mock_config(?MODULE, Config0), Config = rebar_test_utils:init_rebar_state(Config0,"same_alias_"), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, {pkg, fakelib}}]}]), [{rebarconfig, RebarConf} | Config]; init_per_testcase(diff_alias, Config0) -> mock_config(?MODULE, Config0), Config = rebar_test_utils:init_rebar_state(Config0,"diff_alias_"), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, {pkg, goodpkg}}]}]), [{rebarconfig, RebarConf} | Config]; init_per_testcase(diff_alias_vsn, Config0) -> mock_config(?MODULE, Config0), Config = rebar_test_utils:init_rebar_state(Config0,"diff_alias_vsn_"), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, "1.0.0", {pkg, goodpkg}}]}]), [{rebarconfig, RebarConf} | Config]; init_per_testcase(transitive_alias, Config0) -> mock_config(?MODULE, Config0), Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{topdep, "1.0.0", {pkg, topdep}}]}]), [{rebarconfig, RebarConf} | Config]; init_per_testcase(transitive_hash_mismatch, Config0) -> mock_config(?MODULE, Config0), Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{topdep, "1.0.0", {pkg, topdep}}]}]), [{rebarconfig, RebarConf} | Config]. end_per_testcase(_, Config) -> unmock_config(Config), Config. same_alias(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{lock, "fakelib"}, {dep, "fakelib"}]} ). diff_alias(Config) -> %% even though the dep is 'fakelib' aliased as 'goodpkg' all %% internal records use 'fakelib' as a value. Just make sure %% the lock actually maintains the proper source as 'goodpkg' AppDir = ?config(apps, Config), Lockfile = filename:join([AppDir, "rebar.lock"]), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{lock, "fakelib"},{dep, "fakelib"}]} ), {ok, [{Vsn, LockData}|_]} = file:consult(Lockfile), ?assert(lists:any(fun({<<"fakelib">>,{pkg,<<"goodpkg">>,_},_}) -> true ; (_) -> false end, LockData)), %% An second run yields the same rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{lock, "fakelib"},{dep, "fakelib"}]} ), {ok, [{Vsn, LockData}|_]} = file:consult(Lockfile), %% So does an upgrade rebar_test_utils:run_and_check( Config, RebarConfig, ["upgrade", "--all"], {ok, [{lock, "fakelib"},{dep, "fakelib"}]} ), {ok, [{Vsn, LockData}|_]} = file:consult(Lockfile). diff_alias_vsn(Config) -> diff_alias(Config). transitive_alias(Config) -> %% ensure that the apps fetched under transitive aliases are %% locked properly, but also that they are stored in the right %% directory in the build dir to avoid breaking includes and %% static analysis tools that rely on the location to work AppDir = ?config(apps, Config), Lockfile = filename:join([AppDir, "rebar.lock"]), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{lock, "topdep"},{dep, "topdep"}, {lock,"transitive_app"},{dep,"transitive_app"}]} ), {ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile), ?assert(lists:any(fun({<<"transitive_app">>,{pkg,<<"transitive">>,_},_}) -> true ; (_) -> false end, LockData)), AppDir = ?config(apps, Config), AliasedName = filename:join([AppDir, "_build", "default", "lib", "transitive_app"]), PkgName = filename:join([AppDir, "_build", "default", "lib", "transitive"]), ?assert(filelib:is_dir(AliasedName)), ?assertNot(filelib:is_dir(PkgName)), %% An second run yields the same rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{lock, "topdep"},{dep, "topdep"}, {lock,"transitive_app"},{dep,"transitive_app"}]} ), {ok, [{Vsn, LockData}|_]} = file:consult(Lockfile), ?assert(filelib:is_dir(AliasedName)), ?assertNot(filelib:is_dir(PkgName)), %% So does an upgrade rebar_test_utils:run_and_check( Config, RebarConfig, ["upgrade", "--all"], {ok, [{lock, "topdep"},{dep, "topdep"}, {lock,"transitive_app"},{dep,"transitive_app"}]} ), {ok, [{Vsn, LockData}|_]} = file:consult(Lockfile), ?assert(filelib:is_dir(AliasedName)), ?assertNot(filelib:is_dir(PkgName)), ok. transitive_hash_mismatch(Config) -> %% ensure that the apps fetched under transitive aliases are %% locked properly, but also that they are stored in the right %% directory in the build dir to avoid breaking includes and %% static analysis tools that rely on the location to work AppDir = ?config(apps, Config), Lockfile = filename:join([AppDir, "rebar.lock"]), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( Config, RebarConfig, ["lock"], {ok, [{lock, "topdep"},{dep, "topdep"}, {lock,"transitive_app"},{dep,"transitive_app"}]} ), {ok, [LockData|Attrs]} = file:consult(Lockfile), %% Change Lock hash data to cause a failure next time, but on transitive %% deps only NewLock = [LockData|lists:map( fun([{pkg_hash, Hashes}|Rest]) -> [{pkg_hash, [{<<"transitive_app">>, <<"fakehash">>} | lists:keydelete(<<"transitive_app">>, 1, Hashes)]} | Rest] ; (Attr) -> Attr end, Attrs)], {ok, Io} = file:open(Lockfile, [write]), [io:format(Io, "~p.~n", [Attr]) || Attr <- NewLock], file:close(Io), ct:pal("lock: ~p", [file:consult(Lockfile)]), ec_file:remove(filename:join([AppDir, "_build"]), [recursive]), ?assertMatch( {error, {rebar_fetch, {unexpected_hash, _, _, _}}}, rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], return) ), ok. parse_deps(Deps) -> [{maps:get(app, D, Name), {pkg, Name, Constraint, undefined}} || D=#{package := Name, requirement := Constraint} <- Deps]. mock_config(Name, Config) -> {ChkFake, Etag} = create_lib(Name, Config, "fakelib"), {ChkTop, _} = create_lib(Name, Config, "topdep"), {ChkTrans, _} = create_lib(Name, Config, "transitive_app", "transitive"), ct:pal("{~p, _}",[ChkTop]), ct:pal("{~p, _}",[ChkTrans]), Priv = ?config(priv_dir, Config), TmpDir = filename:join([Priv, "tmp", atom_to_list(Name)]), %% Add an alias for goodpkg -> fakelib by hand AppDir = filename:join([Priv, "fakelib"]), CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]), CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]), rebar_test_utils:create_app(AppDir, "fakelib", "1.0.0", [kernel, stdlib]), ct:pal("{~p, ~p}",[ChkFake, Etag]), {ChkGood, EtagGood} = rebar_test_utils:package_app(AppDir, CacheDir, "goodpkg", "1.0.0"), AllDeps = [ {<<"fakelib">>,[[<<"1.0.0">>]]}, {<<"goodpkg">>,[[<<"1.0.0">>]]}, {<<"topdep">>,[[<<"1.0.0">>]]}, {<<"transitive">>, [[<<"1.0.0">>]]}, {{<<"fakelib">>,<<"1.0.0">>}, [[], ChkFake, [<<"rebar3">>]]}, {{<<"goodpkg">>,<<"1.0.0">>}, [[], ChkGood, [<<"rebar3">>]]}, {{<<"topdep">>,<<"1.0.0">>}, [[ {<<"transitive">>, <<"1.0.0">>, false, <<"transitive_app">>} ], ChkTop, [<<"rebar3">>]]}, {{<<"transitive">>,<<"1.0.0">>}, [[], ChkTrans, [<<"rebar3">>]]} ], Tid = ets:new(registry_table, [public]), ets:insert_new(Tid, AllDeps), ok = ets:tab2file(Tid, filename:join([CacheDir, "registry"])), %% ets:delete(Tid), %% The state returns us a fake registry meck:new(rebar_dir, [passthrough, no_link]), meck:expect(rebar_dir, global_cache_dir, fun(_) -> CacheRoot end), meck:new(rebar_packages, [passthrough, no_link]), meck:expect(rebar_packages, registry_dir, fun(_) -> {ok, CacheDir} end), meck:expect(rebar_packages, package_dir, fun(_, _) -> {ok, CacheDir} end), %% TODO: is something else wrong that we need this for transitive_alias to pass meck:expect(rebar_packages, update_package, fun(_, _, _) -> ok end), meck:new(rebar_prv_update, [passthrough]), meck:expect(rebar_prv_update, do, fun(State) -> {ok, State} end), catch ets:delete(?PACKAGE_TABLE), rebar_packages:new_package_table(), lists:foreach(fun({{N, Vsn}, [Deps, Checksum, _]}) -> case ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(N), Vsn, <<"hexpm">>}) of false -> ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(N), ec_semver:parse(Vsn), <<"hexpm">>}, dependencies=[{DAppName, {pkg, DN, DV, undefined}} || {DN, DV, _, DAppName} <- Deps], retired=false, outer_checksum=Checksum}); true -> ok end; ({_N, _Vsns}) -> ok end, AllDeps), meck:new(r3_hex_repo, [passthrough]), meck:expect(r3_hex_repo, get_package, fun(_Config, PkgName) -> Matches = ets:match_object(Tid, {{PkgName,'_'}, '_'}), Releases = [#{outer_checksum => Checksum, version => Vsn, dependencies => [{DAppName, {pkg, DN, DV, undefined}} || {DN, DV, _, DAppName} <- Deps]} || {{_, Vsn}, [Deps, Checksum, _]} <- Matches], {ok, {200, #{}, Releases}} end), meck:expect(r3_hex_repo, get_tarball, fun(_, _, _) -> {ok, {304, #{<<"etag">> => EtagGood}, <<>>}} end), %% Move all packages to cache NewConf = [{cache_root, CacheRoot}, {cache_dir, CacheDir}, {tmp_dir, TmpDir}, {mock_table, Tid} | Config], NewConf. unmock_config(Config) -> meck:unload(), Config. create_lib(Name, Config, PkgName) -> create_lib(Name, Config, PkgName, PkgName). create_lib(Name, Config, AppName, PkgName) -> Priv = ?config(priv_dir, Config), AppDir = filename:join([Priv, PkgName]), CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]), CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]), filelib:ensure_dir(filename:join([CacheDir, "registry"])), rebar_test_utils:create_app(AppDir, AppName, "1.0.0", [kernel, stdlib]), rebar_test_utils:package_app(AppDir, CacheDir, PkgName, "1.0.0"). rebar3-3.18.0/test/mock_pkg_resource.erl0000644000232200023220000001731014164317745020531 0ustar debalancedebalance%%% Mock a package resource and create an app magically for each URL submitted. -module(mock_pkg_resource). -export([mock/0, mock/1, unmock/0]). -define(MOD, rebar_pkg_resource). -include("rebar.hrl"). %%%%%%%%%%%%%%%%% %%% Interface %%% %%%%%%%%%%%%%%%%% %% @doc same as `mock([])'. mock() -> mock([]). %% @doc Mocks a fake version of the git resource fetcher that creates %% empty applications magically, rather than trying to download them. %% Specific config options are explained in each of the private functions. -spec mock(Opts) -> ok when Opts :: [Option], Option :: {upgrade, [App]} | {cache_dir, string()} | {default_vsn, Vsn} | {override_vsn, [{App, Vsn}]} | {not_in_index, [{App, Vsn}]} | {pkgdeps, [{{App,Vsn}, [Dep]}]}, App :: string(), Dep :: {App, string(), {pkg, App, Vsn, InnerHash, OuterHash}}, Vsn :: string(), InnerHash :: string() | undefined, OuterHash :: string() | undefined. mock(Opts) -> meck:new(?MOD, [no_link, passthrough]), mock_lock(Opts), mock_update(Opts), mock_vsn(Opts), mock_download(Opts), mock_pkg_index(Opts), ok. unmock() -> meck:unload(?MOD), meck:unload(rebar_packages). %%%%%%%%%%%%%%% %%% Private %%% %%%%%%%%%%%%%%% %% @doc creates values for a lock file. mock_lock(_) -> meck:expect(?MOD, lock, fun(AppInfo, _) -> {pkg, Name, Vsn, InnerHash, OuterHash, _RepoConfig} = rebar_app_info:source(AppInfo), {pkg, Name, Vsn, InnerHash, OuterHash} end). %% @doc The config passed to the `mock/2' function can specify which apps %% should be updated on a per-name basis: `{update, ["App1", "App3"]}'. mock_update(Opts) -> ToUpdate = proplists:get_value(upgrade, Opts, []), meck:expect( ?MOD, needs_update, fun(AppInfo, _) -> {pkg, App, _Vsn, _InnerHash, _OuterHash, _} = rebar_app_info:source(AppInfo), lists:member(binary_to_list(App), ToUpdate) end). %% @doc Replicated an unsupported call. mock_vsn(_Opts) -> meck:expect( ?MOD, make_vsn, fun(_AppInfo, _) -> {error, "Replacing version of type pkg not supported."} end). %% @doc For each app to download, create a dummy app on disk instead. %% The configuration for this one (passed in from `mock/1') includes: %% %% - Specify a version with `{pkg, _, Vsn, _}' %% - Dependencies for each application must be passed of the form: %% `{pkgdeps, [{"app1", [{app2, ".*", {pkg, ...}}]}]}' -- basically %% the `pkgdeps' option takes a key/value list of terms to output directly %% into a `rebar.config' file to describe dependencies. mock_download(Opts) -> Deps = proplists:get_value(pkgdeps, Opts, []), Config = proplists:get_value(config, Opts, []), meck:expect( ?MOD, download, fun (Dir, AppInfo, _, _) -> {pkg, AppBin, Vsn, _, _, _} = rebar_app_info:source(AppInfo), App = rebar_utils:to_list(AppBin), filelib:ensure_dir(Dir), AppDeps = proplists:get_value({App,Vsn}, Deps, []), {ok, AppInfo1} = rebar_test_utils:create_app( Dir, App, rebar_utils:to_list(Vsn), [kernel, stdlib] ++ [element(1,D) || D <- AppDeps] ), rebar_test_utils:create_config(Dir, [{deps, AppDeps}]++Config), TarApp = App++"-"++rebar_utils:to_list(Vsn)++".tar", Metadata = #{<<"app">> => AppBin, <<"version">> => Vsn}, Files = all_files(rebar_app_info:dir(AppInfo1)), {ok, #{tarball := Tarball}} = r3_hex_tarball:create(Metadata, archive_names(Dir, Files)), Archive = filename:join([Dir, TarApp]), file:write_file(Archive, Tarball), Cache = proplists:get_value(cache_dir, Opts, filename:join(Dir,"cache")), Cached = filename:join([Cache, TarApp]), filelib:ensure_dir(Cached), rebar_file_utils:mv(Archive, Cached), ok end). %% @doc On top of the pkg resource mocking, we need to mock the package %% index. %% %% A special option, `{not_in_index, [App]}' lets the index leave out %% specific applications otherwise listed. mock_pkg_index(Opts) -> Deps = proplists:get_value(pkgdeps, Opts, []), Repos = proplists:get_value(repos, Opts, [<<"hexpm">>]), Skip = proplists:get_value(not_in_index, Opts, []), %% Dict: {App, Vsn}: [{<<"link">>, <<>>}, {<<"deps">>, []}] %% Index: all apps and deps in the index Dict = find_parts(Deps, Skip), to_index(Deps, Dict, Repos), meck:new(rebar_packages, [passthrough, no_link]), meck:expect(rebar_packages, update_package, fun(_, _, _State) -> ok end), meck:expect(rebar_packages, verify_table, fun(_State) -> true end). %%%%%%%%%%%%%%% %%% Helpers %%% %%%%%%%%%%%%%%% all_files(Dir) -> filelib:wildcard(filename:join([Dir, "**"])). archive_names(Dir, Files) -> [{(F -- Dir) -- "/", F} || F <- Files]. find_parts(Apps, Skip) -> find_parts(Apps, Skip, dict:new()). find_parts([], _, Acc) -> Acc; find_parts([{AppName, Deps}|Rest], Skip, Acc) -> case lists:member(AppName, Skip) orelse dict:is_key(AppName,Acc) of true -> find_parts(Rest, Skip, Acc); false -> AccNew = dict:store(AppName, Deps, Acc), find_parts(Rest, Skip, AccNew) end. parse_deps(Deps) -> [{maps:get(app, D, Name), {pkg, Name, Constraint, undefined, undefined}} || D=#{package := Name, requirement := Constraint} <- Deps]. to_index(AllDeps, Dict, Repos) -> catch ets:delete(?PACKAGE_TABLE), rebar_packages:new_package_table(), dict:fold( fun({N, V}, Deps, _) -> DepsList = [#{package => DKB, app => DKB, requirement => DVB, source => {pkg, DKB, DVB, undefined, undefined}} || {DK, DV} <- Deps, DKB <- [ec_cnv:to_binary(DK)], DVB <- [ec_cnv:to_binary(DV)]], Repo = rebar_test_utils:random_element(Repos), ets:insert(?PACKAGE_TABLE, #package{key={N, ec_semver:parse(V), Repo}, dependencies=parse_deps(DepsList), retired=false, inner_checksum = <<"inner_checksum">>, outer_checksum = <<"checksum">>}) end, ok, Dict), lists:foreach(fun({{Name, Vsn}, _}) -> case lists:any(fun(R) -> ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(Name), ec_semver:parse(Vsn), R}) end, Repos) of false -> Repo = rebar_test_utils:random_element(Repos), ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(Name), ec_semver:parse(Vsn), Repo}, dependencies=[], retired=false, inner_checksum = <<"inner_checksum">>, outer_checksum = <<"checksum">>}); true -> ok end end, AllDeps). rebar3-3.18.0/test/rebar_discover_SUITE.erl0000644000232200023220000001036114164317745020771 0ustar debalancedebalance-module(rebar_discover_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [empty_app_src, bad_app_src, invalid_app_src, overwrite_extension]. %% note: invalid .app files without a .app.src also present %% has rebar3 just ignoring the directory as not OTP-related. init_per_testcase(_, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "discover_app_"), AppDir = ?config(apps, NewConfig), Name = rebar_test_utils:create_random_name("app1"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig]. end_per_testcase(_, Config) -> Config. empty_app_src() -> [{doc, "when there's an empty .app.src file, exit with a good error " "message rather than an uncaught exception"}]. empty_app_src(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), AppSrc = filename:join([AppDir, "src", Name ++ ".app.src"]), ok = file:write_file(AppSrc, ""), ?assertEqual( {error, {rebar_app_discover, {cannot_read_app_file, AppSrc}}}, rebar_test_utils:run_and_check(Config, [], ["compile"], return) ), ok. bad_app_src() -> [{doc, "when there's a syntactically invalid " ".app.src file, exit with a good error " "message rather than an uncaught exception"}]. bad_app_src(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), AppSrc = filename:join([AppDir, "src", Name ++ ".app.src"]), ok = file:write_file(AppSrc, "bad term file :("), ?assertMatch( {error, {rebar_app_discover, {bad_term_file, AppSrc, _}}}, rebar_test_utils:run_and_check(Config, [], ["compile"], return) ), ok. invalid_app_src() -> [{doc, "when there's a syntactically valid but semantically invalid " ".app.src file, exit with a good error " "message rather than an uncaught exception"}]. invalid_app_src(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), AppSrc = filename:join([AppDir, "src", Name ++ ".app.src"]), ok = file:write_file(AppSrc, "{applications, name_but_no_args}."), ?assertEqual( {error, {rebar_app_discover, {cannot_read_app_file, AppSrc}}}, rebar_test_utils:run_and_check(Config, [], ["compile"], return) ), ok. overwrite_extension() -> [{doc, "when we overwrite the default extension with " "`[\".test.app.src\", \".app.src\"]` " "check that the right application resource file is used. When " "the order is reversed multiple_app_files should be returned."}]. overwrite_extension(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), AppSrc = filename:join([AppDir, "src", Name ++ ".app.src"]), TestAppSrc = filename:join([AppDir, "src", Name ++ ".test.app.src"]), AppSrcData = io_lib:format( "{application, ~s, [{description, \"some description\"}, " "{vsn, \"0.1.0\"}, {applications, [kernel,stdlib]} ]}.~n", [Name] ), TestAppSrcData = io_lib:format( "{application, ~s, [{description, \"some description\"}, " "{vsn, \"0.42.0\"}, {applications, [kernel,stdlib]} ]}.~n", [Name] ), ok = file:write_file(AppSrc, AppSrcData), ok = file:write_file(TestAppSrc, TestAppSrcData), {ok, AfterCompileState} = rebar_test_utils:run_and_check( Config, [{application_resource_extensions, [".test.app.src", ".app.src"]}], ["compile"], return ), [App] = rebar_state:project_apps(AfterCompileState), ?assertEqual("0.42.0", rebar_app_info:vsn(App)), %% reverse order now, check that both are reported as conflicting {error, {rebar_prv_app_discovery, {multiple_app_files, Conflicting}}} = rebar_test_utils:run_and_check( Config, [{application_resource_extensions, [".app.src", ".test.app.src"]}], ["compile"], return ), ?assert(lists:member(AppSrc, Conflicting)), ?assert(lists:member(TestAppSrc, Conflicting)). rebar3-3.18.0/test/rebar_lock_SUITE.erl0000644000232200023220000001403614164317745020106 0ustar debalancedebalance%%% Most locking tests are implicit in other test suites handling %%% dependencies. %%% This suite is to test the compatibility layers between various %%% versions of lockfiles. -module(rebar_lock_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [current_version, beta_version, future_versions_no_attrs, future_versions_attrs]. current_version(Config) -> %% Current version just dumps the locks as is on disk. LockFile = filename:join(?config(priv_dir, Config), "current_version"), Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3}, {<<"pkg2">>,{pkg,<<"name1">>,<<"1.1.6">>},2}, {<<"pkg3">>,{pkg,<<"name2">>,<<"3.0.6">>},1} ], ExpandedNull = [ {<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>,undefined, undefined},3}, {<<"pkg2">>,{pkg,<<"name1">>,<<"1.1.6">>,undefined, undefined},2}, {<<"pkg3">>,{pkg,<<"name2">>,<<"3.0.6">>,undefined, undefined},1} ], %% Simulate a beta lockfile file:write_file(LockFile, io_lib:format("~p.~n", [Locks])), %% No properties fetched from a beta lockfile, expand locks %% to undefined ?assertEqual(ExpandedNull, rebar_config:consult_lock_file(LockFile)), %% Adding hash data Hashes = [{<<"pkg1">>, <<"tarballhash">>}, {<<"pkg3">>, <<"otherhash">>}], ExtHashes = [{<<"pkg1">>, <<"outer_tarballhash">>}, {<<"pkg3">>, <<"outer_otherhash">>}], ExpandedLocks = [ {<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>,<<"tarballhash">>, <<"outer_tarballhash">>},3}, {<<"pkg2">>,{pkg,<<"name1">>,<<"1.1.6">>,undefined, undefined},2}, {<<"pkg3">>,{pkg,<<"name2">>,<<"3.0.6">>,<<"otherhash">>, <<"outer_otherhash">>},1} ], file:write_file(LockFile, io_lib:format("~p.~n~p.~n", [{"1.2.0", Locks}, [{pkg_hash, Hashes}, {pkg_hash_ext, ExtHashes}]])), ?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)), %% Then check that we can reverse that ok = rebar_config:write_lock_file(LockFile, ExpandedLocks), ?assertEqual({ok, [{"1.2.0", Locks}, [{pkg_hash, Hashes}, {pkg_hash_ext, ExtHashes}]]}, file:consult(LockFile)). beta_version(Config) -> %% Current version just dumps the locks as is on disk. LockFile = filename:join(?config(priv_dir, Config), "current_version"), Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3}], ExpandedLocks = [ {<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>,undefined, undefined},3} ], file:write_file(LockFile, io_lib:format("~p.~n", [Locks])), ?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)). future_versions_no_attrs(Config) -> %% Future versions will keep the same core attribute in there, but %% will do so under a new format bundled with a version and potentially %% some trailing attributes LockFile = filename:join(?config(priv_dir, Config), "future_versions"), Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>, {pkg,<<"name">>,<<"0.1.6">>},3}], ExpandedLocks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>, {pkg,<<"name">>,<<"0.1.6">>,undefined, undefined},3}], LockData = {"3.5.2", Locks}, file:write_file(LockFile, io_lib:format("~p.~n", [LockData])), ?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)). future_versions_attrs(Config) -> %% Future versions will keep the same core attribute in there, but %% will do so under a new format bundled with a version and potentially %% some trailing attributes LockFile = filename:join(?config(priv_dir, Config), "future_versions"), Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3}], ExpandedLocks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2}, {<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0}, {<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1}, {<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>, <<"tarballhash">>, <<"outer_tarballhash">>},3}], Hashes = [{<<"pkg1">>, <<"tarballhash">>}], ExtHashes = [{<<"pkg1">>, <<"outer_tarballhash">>}], LockData = {"3.5.2", Locks}, file:write_file(LockFile, io_lib:format("~p.~n~p.~ngarbage.~n", [LockData, [{a, x}, {pkg_hash, Hashes},{pkg_hash_ext, ExtHashes}, {b, y}]])), ?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)). rebar3-3.18.0/test/rebar_unlock_SUITE_data/0000755000232200023220000000000014164317745020732 5ustar debalancedebalancerebar3-3.18.0/test/rebar_unlock_SUITE_data/rebar.lock0000644000232200023220000000241014164317745022674 0ustar debalancedebalance[{<<"meck">>, {git,"git://github.com/eproxus/meck", {ref,"69664df5d0e01a0ae27efb62831d6eea45cc1cd4"}}, 3}, {<<"itc">>, {git,"git://github.com/ferd/Interval-Tree-Clocks.git", {ref,"168449da42871892f6047733edddf33936dd660f"}}, 2}, {<<"bitcask">>, {git,"https://github.com/basho/bitcask.git", {ref,"c3e9cc5e64bcfd6e342a85932a90428cfdc1ee2d"}}, 2}, {<<"quickrand">>, {git,"https://github.com/okeuday/quickrand.git", {ref,"0395a10b94472ccbe38b62bbfa9d0fc1ddac1dd7"}}, 1}, {<<"merklet">>, {git,"git://github.com/ferd/merklet.git", {ref,"21b5797a21ab6aa1ddb6740799372d2d4b6a6054"}}, 1}, {<<"interclock">>, {git,"git://github.com/ferd/interclock.git", {ref,"6a8b7443fa200da16d819f058e4dc8a0a75eca1e"}}, 1}, {<<"gproc">>, {git,"git://github.com/uwiger/gproc.git", {ref,"7655bddc4397d0cc3f7c4d95e7b96790605946fe"}}, 1}, {<<"uuid">>, {git,"https://github.com/okeuday/uuid.git", {ref,"f7c141c8359cd690faba0d2684b449a07db8e915"}}, 0}, {<<"peeranha">>, {git,"https://github.com/ferd/peeranha.git", {ref,"3bdbdadf6e34a1705bf2669eb28acd32a4fc9166"}}, 0}, {<<"file_monitor">>, {git,"https://github.com/richcarl/file_monitor.git", {ref,"4910b991bf3166377985d7ed961665c4b24e3de6"}}, 0}]. rebar3-3.18.0/test/rebar_unlock_SUITE_data/pkg.rebar.lock0000644000232200023220000000276714164317745023473 0ustar debalancedebalance{"1.1.0", [{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.0.4">>},0}, {<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},0}, {<<"cf">>,{pkg,<<"cf">>,<<"0.2.1">>},0}, {<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.2.3">>},0}, {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"0.21.0">>},0}, {<<"eunit_formatters">>,{pkg,<<"eunit_formatters">>,<<"0.3.1">>},0}, {<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},0}, {<<"providers">>,{pkg,<<"providers">>,<<"1.6.0">>},0}, {<<"relx">>,{pkg,<<"relx">>,<<"3.20.0">>},0}, {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.1">>},0}]}. [ {pkg_hash,[ {<<"bbmustache">>, <<"7BA94F971C5AFD7B6617918A4BB74705E36CAB36EB84B19B6A1B7EE06427AA38">>}, {<<"certifi">>, <<"A7966EFB868B179023618D29A407548F70C52466BF1849B9E8EBD0E34B7EA11F">>}, {<<"cf">>, <<"69D0B1349FD4D7D4DC55B7F407D29D7A840BF9A1EF5AF529F1EBE0CE153FC2AB">>}, {<<"cth_readable">>, <<"293120673DFF82F0768612C5282E35C40CACC1B6F94FE99077438FD3749D0E27">>}, {<<"erlware_commons">>, <<"A04433071AD7D112EDEFC75AC77719DD3E6753E697AC09428FC83D7564B80B15">>}, {<<"eunit_formatters">>, <<"7A6FC351EB5B873E2356B8852EB751E20C13A72FBCA03393CF682B8483509573">>}, {<<"getopt">>, <<"B17556DB683000BA50370B16C0619DF1337E7AF7ECBF7D64FBF8D1D6BCE3109B">>}, {<<"providers">>, <<"DB0E2F9043AE60C0155205FCD238D68516331D0E5146155E33D1E79DC452964A">>}, {<<"relx">>, <<"B515B8317D25B3A1508699294C3D1FA6DC0527851DFFC87446661BCE21A36710">>}, {<<"ssl_verify_fun">>, <<"28A4D65B7F59893BC2C7DE786DEC1E1555BD742D336043FE644AE956C3497FBE">>}]} ]. rebar3-3.18.0/test/mock_git_subdir_resource.erl0000644000232200023220000001251014164317745022100 0ustar debalancedebalance%%% Mock a git_subdir resource and create an app magically for each %%% URL and subdirectory submitted. -module(mock_git_subdir_resource). -export([mock/0, mock/1, mock/2, unmock/0]). -define(MOD, rebar_git_subdir_resource). %%%%%%%%%%%%%%%%% %%% Interface %%% %%%%%%%%%%%%%%%%% %% @doc same as `mock([])'. mock() -> mock([]). %% @doc Mocks a fake version of the git resource fetcher that creates %% empty applications magically, rather than trying to download them. %% Specific config options are explained in each of the private functions. -spec mock(Opts) -> ok when Opts :: [Option], Option :: {update, [App]} | {default_vsn, Vsn} | {override_vsn, [{App, Vsn}]} | {deps, [{App, [Dep]}]}, App :: string(), Dep :: {App, {git_subdir, string(), term(), string()}} | {pkg, App, term()}, Vsn :: string(). mock(Opts) -> mock(Opts, create_app). mock(Opts, CreateType) -> meck:new(?MOD, [no_link, passthrough]), mock_lock(Opts), mock_update(Opts), mock_vsn(Opts), mock_download(Opts, CreateType), ok. unmock() -> meck:unload(?MOD). %%%%%%%%%%%%%%% %%% Private %%% %%%%%%%%%%%%%%% %% @doc creates values for a lock file. The refs are fake, but %% tags and existing refs declared for a dependency are preserved. mock_lock(_) -> meck:expect( ?MOD, lock, fun(AppInfo, _) -> case rebar_app_info:source(AppInfo) of {git_subdir, Url, {tag, Ref}, Dir} -> {git_subdir, Url, {ref, Ref}, Dir}; {git_subdir, Url, {ref, Ref}, Dir} -> {git_subdir, Url, {ref, Ref}, Dir}; {git_subdir, Url, Dir} -> {git_subdir, Url, {ref, "0.0.0"}, Dir}; {git_subdir, Url, _, Dir} -> {git_subdir, Url, {ref, "0.0.0"}, Dir} end end). %% @doc The config passed to the `mock/2' function can specify which apps %% should be updated on a per-name basis: `{update, ["App1", "App3"]}'. mock_update(Opts) -> ToUpdate = proplists:get_value(upgrade, Opts, []), % ct:pal("TOUp: ~p", [ToUpdate]), meck:expect( ?MOD, needs_update, fun(AppInfo, _) -> {git_subdir, Url, _Ref} = rebar_app_info:source(AppInfo), App = app(Url), % ct:pal("Needed update? ~p (~p) -> ~p", [App, {Url,_Ref}, lists:member(App, ToUpdate)]), lists:member(App, ToUpdate) end). %% @doc Tries to fetch a version from the `*.app.src' file or otherwise %% just returns random stuff, avoiding to check for the presence of git. %% This probably breaks the assumption that stable references are returned. %% %% This function can't respect the `override_vsn' option because if the %% .app.src file isn't there, we can't find the app name either. mock_vsn(Opts) -> Default = proplists:get_value(default_vsn, Opts, "0.0.0"), meck:expect( ?MOD, make_vsn, fun(AppInfo, _) -> Dir = rebar_app_info:dir(AppInfo), case filelib:wildcard("*.app.src", filename:join([Dir,"src"])) of [AppSrc] -> {ok, App} = file:consult(AppSrc), Vsn = proplists:get_value(vsn, App), {plain, Vsn}; _ -> {plain, Default} end end). %% @doc For each app to download, create a dummy app on disk instead. %% The configuration for this one (passed in from `mock/1') includes: %% %% - Specify a version, branch, ref, or tag via the `{git_subdir, URL, {_, Vsn}' %% format to specify a path. %% - If there is no version submitted (`{git_subdir, URL}'), the function instead %% reads from the `override_vsn' proplist (`{override_vsn, {"App1","1.2.3"}'), %% and otherwise uses the value associated with `default_vsn'. %% - Dependencies for each application must be passed of the form: %% `{deps, [{"app1", [{app2, ".*", {git_subdir, ...}}]}]}' -- basically %% the `deps' option takes a key/value list of terms to output directly %% into a `rebar.config' file to describe dependencies. mock_download(Opts, CreateType) -> Deps = proplists:get_value(deps, Opts, []), Config = proplists:get_value(config, Opts, []), Default = proplists:get_value(default_vsn, Opts, "0.0.0"), Overrides = proplists:get_value(override_vsn, Opts, []), meck:expect( ?MOD, download, fun (Dir, AppInfo, _, _) -> Git = rebar_app_info:source(AppInfo), filelib:ensure_dir(Dir), {git_subdir, Url, {_, Vsn}, SubDir} = normalize_git(Git, Overrides, Default), FullSubDir = filename:join(Dir, SubDir), filelib:ensure_dir(FullSubDir), App = app(Url), AppDeps = proplists:get_value({App,Vsn}, Deps, []), rebar_test_utils:CreateType( FullSubDir, App, Vsn, [kernel, stdlib] ++ [element(1,D) || D <- AppDeps] ), rebar_test_utils:create_config(FullSubDir, [{deps, AppDeps}]++Config), ok end). %%%%%%%%%%%%%%% %%% Helpers %%% %%%%%%%%%%%%%%% app(Path) -> filename:basename(Path, ".git"). normalize_git({git_subdir, Url, SubDir}, Overrides, Default) -> Vsn = proplists:get_value(app(Url), Overrides, Default), {git, Url, {tag, Vsn}, SubDir}; normalize_git({git_subdir, Url, Branch, SubDir}, _, _) when is_list(Branch) -> {git, Url, {branch, Branch}, SubDir}; normalize_git(Git, _, _) -> Git. rebar3-3.18.0/test/rebar_disable_app_SUITE.erl0000644000232200023220000000275714164317745021430 0ustar debalancedebalance-module(rebar_disable_app_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -define(MOD(Name), io_lib:format("-module(~s).~n-export([x/0]).~nx() -> ok.~n", [Name])). all() -> [disable_app]. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). end_per_testcase(_, _Config) -> ok. disable_app(Config) -> AppDir = ?config(apps, Config), Name1 = create_random_app(AppDir, "app1_"), Name2 = create_random_app(AppDir, "app2_"), RebarConfig = [{excluded_apps, [list_to_atom(Name1)]}], %RebarConfig = [], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name2}]}), App1 = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", Name1 ++ ".app"]), ?assertEqual(filelib:is_file(App1), false), App2 = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin", Name2 ++ ".app"]), ?assertEqual(filelib:is_file(App2), true). %% %% Utils %% create_random_app(AppDir, Prefix) -> Name = rebar_test_utils:create_random_name(Prefix), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_empty_app(filename:join([AppDir, "apps", Name]), Name, Vsn, [kernel, stdlib]), ModName = rebar_test_utils:create_random_name("mod1_"), Mod = filename:join([AppDir, "apps", Name, "src", ModName ++ ".erl"]), ok = filelib:ensure_dir(Mod), Src = ?MOD(ModName), ok = ec_file:write(Mod, Src), Name. rebar3-3.18.0/test/rebar_resource_SUITE.erl0000644000232200023220000000267214164317745021010 0ustar debalancedebalance-module(rebar_resource_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> [{group, git}, {group, pkg}, {group, hg}]. groups() -> [{all, [], [change_type_upgrade]}, {git, [], [{group, all}]}, {pkg, [], [{group, all}]}, {hg, [], [{group, all}]}]. init_per_group(all, Config) -> State = rebar_state:resources(rebar_state:new(), [{git, rebar_git_resource}, {pkg, rebar_pkg_resource}, {hg, rebar_hg_resource}]), [{state, State} | Config]; init_per_group(Name, Config) -> [{type, Name}, {resource, {Name, "https://example.org/user/app", "vsn"}} | Config]. end_per_group(_, _Config) -> ok. %% Changing the resource type is seen as an upgrade init_per_testcase(change_type_upgrade, Config) -> Type = ?config(type, Config), TypeStr = atom_to_list(Type), DirName = filename:join([?config(priv_dir, Config), "resource_"++TypeStr]), ec_file:mkdir_path(DirName), {ok, AppInfo} = rebar_app_info:new(test_app, "0.0.1", DirName), AppInfo1 = rebar_app_info:source(AppInfo, ?config(resource, Config)), [{app, AppInfo1} | Config]. end_per_testcase(_, Config) -> Config. change_type_upgrade(Config) -> ?assert(rebar_fetch:needs_update(?config(app, Config), ?config(state, Config))). rebar3-3.18.0/test/rebar_compile_SUITE.erl0000644000232200023220000036542414164317745020620 0ustar debalancedebalance-module(rebar_compile_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. all() -> [{group, basic_app}, {group, release_apps}, {group, checkout_apps}, {group, checkout_deps}, {group, basic_srcdirs}, {group, release_srcdirs}, {group, unbalanced_srcdirs}, {group, basic_extras}, {group, release_extras}, {group, unbalanced_extras}, {group, root_extras}, recompile_when_hrl_changes, recompile_when_included_hrl_changes, recompile_when_recursive_hrl_changes, recompile_extra_when_hrl_in_src_changes, recompile_when_opts_included_hrl_changes, recompile_when_foreign_included_hrl_changes, recompile_when_foreign_behaviour_changes, recompile_when_recursive_behaviour_changes, recompile_when_parent_behaviour_changes, recompile_when_opts_change, recompile_when_dag_opts_change, dont_recompile_when_opts_dont_change, dont_recompile_yrl_or_xrl, delete_beam_if_source_deleted, deps_in_path, checkout_priority, highest_version_of_pkg_dep, parse_transform_test, erl_first_files_test, mib_test, umbrella_mib_first_test, deps_mib_test, only_default_transitive_deps, clean_all, clean_specific, profile_deps, deps_build_in_prod, only_deps, override_deps, git_subdir_deps, override_add_deps, override_del_deps, override_del_pkg_deps, override_opts, override_add_opts, override_del_opts, apply_overrides_exactly_once, override_only_deps, profile_override_deps, profile_override_add_deps, profile_override_del_deps, profile_override_opts, profile_override_add_opts, profile_override_del_opts, include_file_relative_to_working_directory, include_file_in_src, include_file_relative_to_working_directory_test, include_file_in_src_test, include_file_in_src_test_multiapp, recompile_when_parse_transform_as_opt_changes, dont_recompile_when_parse_transform_as_opt_unchanged, recompile_when_parse_transform_inline_changes, regex_filter_skip, regex_filter_regression, recursive, no_recursive, extra_recursion, always_recompile_when_erl_compiler_options_set, dont_recompile_when_erl_compiler_options_env_does_not_change, recompile_when_erl_compiler_options_env_changes, rebar_config_os_var, split_project_apps_hooks, app_file_linting]. groups() -> [{basic_app, [], [build_basic_app, paths_basic_app, clean_basic_app]}, {release_apps, [], [build_release_apps, paths_release_apps, clean_release_apps]}, {checkout_apps, [], [paths_checkout_apps]}, {checkout_deps, [], [build_checkout_deps, paths_checkout_deps]}, {basic_srcdirs, [], [build_basic_srcdirs, paths_basic_srcdirs]}, {release_srcdirs, [], [build_release_srcdirs, paths_release_srcdirs]}, {unbalanced_srcdirs, [], [build_unbalanced_srcdirs, paths_unbalanced_srcdirs]}, {basic_extras, [], [build_basic_extra_dirs, paths_basic_extra_dirs, clean_basic_extra_dirs]}, {release_extras, [], [build_release_extra_dirs, paths_release_extra_dirs, clean_release_extra_dirs]}, {unbalanced_extras, [], [build_unbalanced_extra_dirs, paths_unbalanced_extra_dirs]}, {root_extras, [], [build_extra_dirs_in_project_root, paths_extra_dirs_in_project_root, clean_extra_dirs_in_project_root]}]. init_per_group(basic_app, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "basic_app_"), AppDir = ?config(apps, NewConfig), Name = rebar_test_utils:create_random_name("app1"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig]; init_per_group(release_apps, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "release_apps_"), AppDir = ?config(apps, NewConfig), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [kernel, stdlib]), [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig]; init_per_group(checkout_apps, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "checkout_apps_"), AppDir = ?config(apps, NewConfig), CheckoutsDir = ?config(checkouts, NewConfig), Name1 = rebar_test_utils:create_random_name("checkapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("checkapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([CheckoutsDir,Name2]), Name2, Vsn2, [kernel, stdlib]), [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig]; init_per_group(checkout_deps, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "checkout_deps_"), AppDir = ?config(apps, NewConfig), CheckoutsDir = ?config(checkouts, NewConfig), DepsDir = filename:join([AppDir, "_build", "default", "lib"]), Name1 = rebar_test_utils:create_random_name("checkapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("checkapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([CheckoutsDir,Name2]), Name2, Vsn2, [kernel, stdlib]), rebar_test_utils:create_app(filename:join([DepsDir,Name2]), Name2, Vsn1, [kernel, stdlib]), [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig]; init_per_group(Group, Config) when Group == basic_srcdirs; Group == basic_extras -> NewConfig = rebar_test_utils:init_rebar_state(Config, "basic_srcdirs_"), AppDir = ?config(apps, NewConfig), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name]), ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "extra", io_lib:format("~ts_extra.erl", [Name])]), ExtraSrc), [{app_names, [Name]}, {vsns, [Vsn]}|NewConfig]; init_per_group(Group, Config) when Group == release_srcdirs; Group == release_extras -> NewConfig = rebar_test_utils:init_rebar_state(Config, "release_srcdirs_"), AppDir = ?config(apps, NewConfig), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]), ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]), ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra", io_lib:format("~ts_extra.erl", [Name1])]), ExtraOne), ExtraTwo = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name2]), ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "apps", Name2, "extra", io_lib:format("~ts_extra.erl", [Name2])]), ExtraTwo), [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig]; init_per_group(Group, Config) when Group == unbalanced_srcdirs; Group == unbalanced_extras -> NewConfig = rebar_test_utils:init_rebar_state(Config, "unbalanced_srcdirs_"), AppDir = ?config(apps, NewConfig), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]), ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]), ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra", io_lib:format("~ts_extra.erl", [Name1])]), ExtraOne), [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig]; init_per_group(root_extras, Config) -> NewConfig = rebar_test_utils:init_rebar_state(Config, "root_extras_"), AppDir = ?config(apps, NewConfig), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]), Extra = <<"-module(extra).\n-export([ok/0]).\nok() -> ok.\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "extra", "extra.erl"]), Extra), [{app_names, [Name1, Name2]}, {vsns, [Vsn1, Vsn2]}|NewConfig]. end_per_group(_Group, _Config) -> ok. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(Test, Config) when Test == dont_recompile_when_erl_compiler_options_env_does_not_change orelse Test == recompile_when_erl_compiler_options_env_changes -> _ = code:ensure_loaded(os), UnSetEnv = erlang:function_exported(os, unsetenv, 1), _ = code:ensure_loaded(compile), EnvOpts = erlang:function_exported(compile, env_compiler_options, 0), case {UnSetEnv, EnvOpts} of {true, true} -> maybe_init_config(Config); _ -> {skip, "compile:env_compiler_options/0 unavailable"} end; init_per_testcase(always_recompile_when_erl_compiler_options_set, Config) -> _ = code:ensure_loaded(os), UnSetEnv = erlang:function_exported(os, unsetenv, 1), _ = code:ensure_loaded(compile), EnvOpts = erlang:function_exported(compile, env_compiler_options, 0), case {UnSetEnv, EnvOpts} of {true, true} -> {skip, "compile:env_compiler_options/0 available"}; {true, false} -> maybe_init_config(Config); _ -> {skip, "os:unsetenv/1 unavailable"} end; init_per_testcase(_, Config) -> maybe_init_config(Config). maybe_init_config(Config) -> case ?config(apps, Config) of undefined -> rebar_test_utils:init_rebar_state(Config); _ -> Config end. end_per_testcase(_, _Config) -> catch meck:unload(). %% test cases build_basic_app(Config) -> [Name] = ?config(app_names, Config), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}). build_release_apps(Config) -> [Name1, Name2] = ?config(app_names, Config), rebar_test_utils:run_and_check( Config, [], ["compile"], {ok, [{app, Name1}, {app, Name2}]} ). build_checkout_deps(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), [_, Vsn2] = ?config(vsns, Config), Deps = [{list_to_atom(Name2), Vsn2, {git, "", ""}}], {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, Deps}])), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {checkout, Name2}]} ). build_basic_srcdirs(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists ExtraBeam = filename:join([AppDir, "_build", "default", "lib", Name, "ebin", io_lib:format("~ts_extra.beam", [Name])]), %% check the extra src_dir was copied/linked into the _build dir ExtraDir = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}, {file, ExtraBeam}, {dir, ExtraDir}]} ). build_release_srcdirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", io_lib:format("~ts_extra.beam", [Name1])]), Extra2Beam = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin", io_lib:format("~ts_extra.beam", [Name2])]), %% check the extra src_dir was copied/linked into the _build dir Extra1Dir = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]), Extra2Dir = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {file, Extra2Beam}, {dir, Extra1Dir}, {dir, Extra2Dir}]} ). build_unbalanced_srcdirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", io_lib:format("~ts_extra.beam", [Name1])]), %% check the extra src_dir was copied/linked into the _build dir Extra1Dir = filename:join([AppDir, "_build", "default", "lib", Name1, "extra"]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {dir, Extra1Dir}]} ), %% check no extra src_dir were copied/linked into the _build dir Extra2Dir = filename:join([AppDir, "_build", "default", "lib", Name2, "extra"]), false = filelib:is_dir(Extra2Dir), %% check only expected beams are in the ebin dir {ok, Files} = rebar_utils:list_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"])), lists:all(fun(Beam) -> lists:member(Beam, [Name2 ++ ".app", "not_a_real_src_" ++ Name2 ++ ".beam"]) end, Files). build_basic_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists ExtraBeam = filename:join([AppDir, "_build", "default", "lib", Name, "extra", io_lib:format("~ts_extra.beam", [Name])]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}, {file, ExtraBeam}]} ). build_release_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "extra", io_lib:format("~ts_extra.beam", [Name1])]), Extra2Beam = filename:join([AppDir, "_build", "default", "lib", Name2, "extra", io_lib:format("~ts_extra.beam", [Name2])]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}, {file, Extra2Beam}]} ). build_unbalanced_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists Extra1Beam = filename:join([AppDir, "_build", "default", "lib", Name1, "extra", io_lib:format("~ts_extra.beam", [Name1])]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}, {file, Extra1Beam}]} ), %% check no extra src_dir were copied/linked into the _build dir false = filelib:is_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "extra"])), %% check only expected beams are in the ebin dir {ok, Files} = rebar_utils:list_dir(filename:join([AppDir, "_build", "default", "lib", Name2, "ebin"])), lists:all(fun(Beam) -> lists:member(Beam, [Name2 ++ ".app", "not_a_real_src_" ++ Name2 ++ ".beam"]) end, Files). build_extra_dirs_in_project_root(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], %% check a beam corresponding to the src in the extra src_dir exists ExtraBeam = filename:join([AppDir, "_build", "default", "extras", "extra", "extra.beam"]), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}, {file, ExtraBeam}]} ). paths_basic_app(Config) -> [Name] = ?config(app_names, Config), [Vsn] = ?config(vsns, Config), {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), ok = application:load(list_to_atom(Name)), Loaded = application:loaded_applications(), {_, _, Vsn} = lists:keyfind(list_to_atom(Name), 1, Loaded). paths_release_apps(Config) -> [Name1, Name2] = ?config(app_names, Config), [Vsn1, Vsn2] = ?config(vsns, Config), {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), ok = application:load(list_to_atom(Name1)), ok = application:load(list_to_atom(Name2)), Loaded = application:loaded_applications(), {_, _, Vsn1} = lists:keyfind(list_to_atom(Name1), 1, Loaded), {_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded). paths_checkout_apps(Config) -> [Name1, _Name2] = ?config(app_names, Config), [Vsn1, _Vsn2] = ?config(vsns, Config), {ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), ok = application:load(list_to_atom(Name1)), Loaded = application:loaded_applications(), {_, _, Vsn1} = lists:keyfind(list_to_atom(Name1), 1, Loaded). paths_checkout_deps(Config) -> AppDir = ?config(apps, Config), [_Name1, Name2] = ?config(app_names, Config), [_Vsn1, Vsn2] = ?config(vsns, Config), %% rebar_test_utils:init_rebar_state/1,2 uses rebar_state:new/3 which %% maybe incorrectly sets deps to [] (based on `rebar.lock`) instead of %% to the checkapps %% until that is sorted out the lock file has to be removed before %% this test will pass file:delete(filename:join([AppDir, "rebar.lock"])), {ok, RebarConfig} = file:consult(filename:join([AppDir, "rebar.config"])), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), [AppName2] = rebar_state:all_checkout_deps(State), Name2Bin = binary:list_to_bin(Name2), Name2Bin = rebar_app_info:name(AppName2), code:add_paths(rebar_state:code_paths(State, all_deps)), ok = application:load(list_to_atom(Name2)), Loaded = application:loaded_applications(), {_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded). paths_basic_srcdirs(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))), {module, Mod} = code:ensure_loaded(Mod), Expect = filename:join([AppDir, "_build", "default", "lib", Name, "ebin", io_lib:format("~ts_extra.beam", [Name])]), Expect = code:which(Mod). paths_release_srcdirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))), {module, Mod1} = code:ensure_loaded(Mod1), Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))), {module, Mod2} = code:ensure_loaded(Mod2), ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", io_lib:format("~ts_extra.beam", [Name1])]), ExpectOne = code:which(Mod1), ExpectTwo = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin", io_lib:format("~ts_extra.beam", [Name2])]), ExpectTwo = code:which(Mod2). paths_unbalanced_srcdirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))), {module, Mod1} = code:ensure_loaded(Mod1), Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))), {error, nofile} = code:ensure_loaded(Mod2), ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", io_lib:format("~ts_extra.beam", [Name1])]), ExpectOne = code:which(Mod1). paths_basic_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))), {module, Mod} = code:ensure_loaded(Mod), Expect = filename:join([AppDir, "_build", "default", "lib", Name, "extra", io_lib:format("~ts_extra.beam", [Name])]), Expect = code:which(Mod). paths_release_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))), {module, Mod1} = code:ensure_loaded(Mod1), Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))), {module, Mod2} = code:ensure_loaded(Mod2), ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "extra", io_lib:format("~ts_extra.beam", [Name1])]), ExpectOne = code:which(Mod1), ExpectTwo = filename:join([AppDir, "_build", "default", "lib", Name2, "extra", io_lib:format("~ts_extra.beam", [Name2])]), ExpectTwo = code:which(Mod2). paths_unbalanced_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))), {module, Mod1} = code:ensure_loaded(Mod1), Mod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))), {error, nofile} = code:ensure_loaded(Mod2), ExpectOne = filename:join([AppDir, "_build", "default", "lib", Name1, "extra", io_lib:format("~ts_extra.beam", [Name1])]), ExpectOne = code:which(Mod1). paths_extra_dirs_in_project_root(Config) -> AppDir = ?config(apps, Config), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return), code:add_paths(rebar_state:code_paths(State, all_deps)), {module, extra} = code:ensure_loaded(extra), Expect = filename:join([AppDir, "_build", "default", "extras", "extra", "extra.beam"]), Expect = code:which(extra). clean_basic_app(Config) -> [Name] = ?config(app_names, Config), rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}). clean_release_apps(Config) -> [Name1, Name2] = ?config(app_names, Config), rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}). clean_basic_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name] = ?config(app_names, Config), rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}), Beam = lists:flatten(io_lib:format("~ts_extra", [Name])), false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name, "extras", Beam])). clean_release_extra_dirs(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}), Beam1 = lists:flatten(io_lib:format("~ts_extra", [Name1])), false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name1, "extras", Beam1])), Beam2 = lists:flatten(io_lib:format("~ts_extra", [Name2])), false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name2, "extras", Beam2])). clean_extra_dirs_in_project_root(Config) -> AppDir = ?config(apps, Config), [Name1, Name2] = ?config(app_names, Config), rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}), false = ec_file:exists(filename:join([AppDir, "_build", "default", "extras"])). recompile_when_hrl_changes(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_header_include).\n" "-export([main/0]).\n" "-include(\"test_header_include.hrl\").\n" "main() -> ?SOME_DEFINE.\n">>, ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>, HeaderFile = filename:join([AppDir, "src", "test_header_include.hrl"]), ok = file:write_file(filename:join([AppDir, "src", "test_header_include.erl"]), ExtraSrc), ok = file:write_file(HeaderFile, ExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>, ok = file:write_file(HeaderFile, NewExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime). recompile_when_included_hrl_changes(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_header_include).\n" "-export([main/0]).\n" "-include(\"test_header_include.hrl\").\n" "main() -> ?SOME_DEFINE.\n">>, ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "include", "dummy"])), HeaderFile = filename:join([AppDir, "include", "test_header_include.hrl"]), ok = file:write_file(filename:join([AppDir, "src", "test_header_include.erl"]), ExtraSrc), ok = file:write_file(HeaderFile, ExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>, ok = file:write_file(HeaderFile, NewExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime). recompile_when_recursive_hrl_changes(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), %% The included path is specifically no specified with a ../ to %% check dynamic path search generation for includes RecurSrc = <<"-module(test_recursive_header_include).\n" "-export([main/0]).\n" "-include(\"test_header_include.hrl\").\n" "main() -> ?SOME_DEFINE.\n">>, ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "src", "recur", "dummy"])), HeaderFile = filename:join([AppDir, "src", "test_header_include.hrl"]), ok = file:write_file(filename:join([AppDir, "src", "recur", "test_recursive_header_include.erl"]), RecurSrc), ok = file:write_file(HeaderFile, ExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>, ok = file:write_file(HeaderFile, NewExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime), ok. recompile_extra_when_hrl_in_src_changes(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_header_include).\n" "-export([main/0]).\n" "-include(\"test_header_include.hrl\").\n" "main() -> ?SOME_DEFINE.\n">>, ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>, HeaderFile = filename:join([AppDir, "src", "test_header_include.hrl"]), SrcFile = filename:join([AppDir, "extra", "test_header_include.erl"]), filelib:ensure_dir(SrcFile), ok = file:write_file(SrcFile, ExtraSrc), ok = file:write_file(HeaderFile, ExtraHeader), RebarCfg = [{extra_src_dirs, ["extra"]}], rebar_test_utils:run_and_check(Config, RebarCfg, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "extra"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>, ok = file:write_file(HeaderFile, NewExtraHeader, [sync]), rebar_test_utils:run_and_check(Config, RebarCfg, ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime). recompile_when_opts_included_hrl_changes(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_header_include).\n" "-export([main/0]).\n" "-include(\"test_header_include.hrl\").\n" "main() -> ?SOME_DEFINE.\n">>, ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>, ok = filelib:ensure_dir(filename:join([AppsDir, "include", "dummy"])), HeaderFile = filename:join([AppsDir, "include", "test_header_include.hrl"]), ok = file:write_file(filename:join([AppDir, "src", "test_header_include.erl"]), ExtraSrc), ok = file:write_file(HeaderFile, ExtraHeader), %% Using relative path from the project root RebarConfig = [{erl_opts, [{i, "include/"}]}], {ok,Cwd} = file:get_cwd(), ok = file:set_cwd(AppsDir), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>, ok = file:write_file(HeaderFile, NewExtraHeader), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ok = file:set_cwd(Cwd), ?assert(ModTime =/= NewModTime). recompile_when_foreign_included_hrl_changes(Config) -> AppDir = ?config(apps, Config), AppsDir = filename:join([AppDir, "apps"]), Name1 = rebar_test_utils:create_random_name("app1_"), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join(AppsDir, Name1), Name1, Vsn, [kernel, stdlib]), rebar_test_utils:create_app(filename:join(AppsDir, Name2), Name2, Vsn, [kernel, stdlib]), ExtraSrc = [<<"-module(test_header_include).\n" "-export([main/0]).\n" "-include_lib(\"">>, Name2, <<"/include/test_header_include.hrl\").\n" "main() -> ?SOME_DEFINE.\n">>], ExtraHeader = <<"-define(SOME_DEFINE, true).\n">>, ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppsDir, Name2, "include", "dummy"])), HeaderFile = filename:join([AppsDir, Name2, "include", "test_header_include.hrl"]), ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_header_include.erl"]), ExtraSrc), ok = file:write_file(HeaderFile, ExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewExtraHeader = <<"-define(SOME_DEFINE, false).\n">>, ok = file:write_file(HeaderFile, NewExtraHeader), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime). recompile_when_foreign_behaviour_changes(Config) -> AppDir = ?config(apps, Config), AppsDir = filename:join([AppDir, "apps"]), Name1 = rebar_test_utils:create_random_name("app1_"), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join(AppsDir, Name1), Name1, Vsn, [kernel, stdlib]), rebar_test_utils:create_app(filename:join(AppsDir, Name2), Name2, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_behaviour_include).\n" "-export([main/0]).\n" "-behaviour(app2_behaviour).\n" "main() -> 1.\n">>, Behaviour = <<"-module(app2_behaviour).\n" "-callback main() -> term().\n">>, ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppsDir, Name2, "src", "dummy"])), BehaviourFile = filename:join([AppsDir, Name2, "src", "app2_behaviour.erl"]), ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_behaviour_include.erl"]), ExtraSrc), ok = file:write_file(BehaviourFile, Behaviour), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), NewBehaviour = <<"-module(app2_behaviour).\n" "-callback main(_) -> term().\n">>, ok = file:write_file(BehaviourFile, NewBehaviour), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime). recompile_when_recursive_behaviour_changes(Config) -> AppDir = ?config(apps, Config), AppsDir = filename:join([AppDir, "apps"]), Name1 = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join(AppsDir, Name1), Name1, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_behaviour_include).\n" "-export([main/0]).\n" "-behaviour(app1_behaviour).\n" "main() -> 1.\n">>, Behaviour = <<"-module(app1_behaviour).\n" "-callback main() -> term().\n">>, ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "sub", "dummy"])), BehaviourFile = filename:join([AppsDir, Name1, "src", "sub", "app1_behaviour.erl"]), ok = file:write_file(filename:join([AppsDir, Name1, "src", "test_behaviour_include.erl"]), ExtraSrc), ok = file:write_file(BehaviourFile, Behaviour), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam", filename:basename(F) =/= "app1_behaviour.beam"], timer:sleep(1000), NewBehaviour = <<"-module(app1_behaviour).\n" "-callback main(_) -> term().\n">>, ok = file:write_file(BehaviourFile, NewBehaviour), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam", filename:basename(F) =/= "app1_behaviour.beam"], ?assert(ModTime =/= NewModTime). recompile_when_parent_behaviour_changes(Config) -> AppDir = ?config(apps, Config), AppsDir = filename:join([AppDir, "apps"]), Name1 = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join(AppsDir, Name1), Name1, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(test_behaviour_include).\n" "-export([main/0]).\n" "-behaviour(app1_behaviour).\n" "main() -> 1.\n">>, Behaviour = <<"-module(app1_behaviour).\n" "-callback main() -> term().\n">>, %% fun thing requires 2+ levels of nesting to trigger a regression due to bad path %% merging/appending in lists levels. ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "sub", "dummy"])), ok = filelib:ensure_dir(filename:join([AppsDir, Name1, "src", "sub", "sub", "dummy"])), BehaviourFile = filename:join([AppsDir, Name1, "src", "sub", "app1_behaviour.erl"]), ok = file:write_file(filename:join([AppsDir, Name1, "src", "sub", "sub", "test_behaviour_include.erl"]), ExtraSrc), ok = file:write_file(BehaviourFile, Behaviour), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam", filename:basename(F) =/= "app1_behaviour.beam"], timer:sleep(1000), NewBehaviour = <<"-module(app1_behaviour).\n" "-callback main(_) -> term().\n">>, ok = file:write_file(BehaviourFile, NewBehaviour), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name1}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam", filename:basename(F) =/= "app1_behaviour.beam"], ?assert(ModTime =/= NewModTime). recompile_when_opts_change(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), rebar_test_utils:create_config(AppDir, [{erl_opts, [{d, some_define}]}]), rebar_test_utils:run_and_check(Config, [{erl_opts, [{d, some_define}]}], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime). recompile_when_dag_opts_change(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), Beams = [filename:join([EbinDir, F]) || F <- Files, filename:extension(F) == ".beam"], ModTime = [filelib:last_modified(Beam) || Beam <- Beams], timer:sleep(1000), DepsDir = filename:join([AppDir, "_build", "default", "lib"]), G = rebar_compiler_dag:init(DepsDir, rebar_compiler_erl, "project_apps", []), %% change the config in the DAG... [digraph:add_vertex(G, Beam, {artifact, [{d, some_define}]}) || Beam <- Beams], digraph:add_vertex(G, '$r3_dirty_bit', true), % trigger a save %% the rebar_compiler_erl module is annotated with a compiler version %% to help rebuild deps {ok, CompileVsn} = application:get_key(compiler, vsn), CritMeta = [{compiler, CompileVsn}], rebar_compiler_dag:maybe_store(G, DepsDir, rebar_compiler_erl, "project_apps", CritMeta), rebar_compiler_dag:terminate(G), %% ... but don't change the actual rebar3 config... rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), %% ... and checks that it rebuilds anyway due to DAG changes {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewBeams = [filename:join([EbinDir, F]) || F <- NewFiles, filename:extension(F) == ".beam"], NewModTime = [filelib:last_modified(Beam) || Beam <- NewBeams], ?assert(ModTime =/= NewModTime). dont_recompile_when_opts_dont_change(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assertEqual(ModTime, NewModTime). dont_recompile_yrl_or_xrl(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Xrl = filename:join([AppDir, "src", "not_a_real_xrl_" ++ Name ++ ".xrl"]), ok = filelib:ensure_dir(Xrl), XrlBody = "Definitions." "\n\n" "D = [0-9]" "\n\n" "Rules." "\n\n" "{D}+ :" " {token,{integer,TokenLine,list_to_integer(TokenChars)}}." "\n\n" "{D}+\\.{D}+((E|e)(\\+|\\-)?{D}+)? :" " {token,{float,TokenLine,list_to_float(TokenChars)}}." "\n\n" "Erlang code.", ok = ec_file:write(Xrl, XrlBody), Yrl = filename:join([AppDir, "src", "not_a_real_yrl_" ++ Name ++ ".yrl"]), ok = filelib:ensure_dir(Yrl), YrlBody = ["Nonterminals E T F.\n" "Terminals '+' '*' '(' ')' number.\n" "Rootsymbol E.\n" "E -> E '+' T: {'$2', '$1', '$3'}.\n" "E -> T : '$1'.\n" "T -> T '*' F: {'$2', '$1', '$3'}.\n" "T -> F : '$1'.\n" "F -> '(' E ')' : '$2'.\n" "F -> number : '$1'.\n"], ok = ec_file:write(Yrl, YrlBody), XrlErl = filename:join([AppDir, "src", filename:basename(Xrl, ".xrl") ++ ".erl"]), YrlErl = filename:join([AppDir, "src", filename:basename(Yrl, ".yrl") ++ ".erl"]), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), XrlBeam = filename:join([EbinDir, filename:basename(Xrl, ".xrl") ++ ".beam"]), YrlBeam = filename:join([EbinDir, filename:basename(Yrl, ".yrl") ++ ".beam"]), Hrl = filename:join([AppDir, "include", "some_header.hrl"]), ok = filelib:ensure_dir(Hrl), HrlBody = yeccpre_hrl(), ok = ec_file:write(Hrl, HrlBody), RebarConfig = [{yrl_opts, [{includefile, "include/some_header.hrl"}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), XrlModTime = filelib:last_modified(XrlErl), YrlModTime = filelib:last_modified(YrlErl), XrlBeamModTime = filelib:last_modified(XrlBeam), YrlBeamModTime = filelib:last_modified(YrlBeam), timer:sleep(1000), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), NewXrlModTime = filelib:last_modified(XrlErl), NewYrlModTime = filelib:last_modified(YrlErl), NewXrlBeamModTime = filelib:last_modified(XrlBeam), NewYrlBeamModTime = filelib:last_modified(YrlBeam), ?assert(XrlBeamModTime == NewXrlBeamModTime), ?assert(YrlBeamModTime == NewYrlBeamModTime), ?assert(XrlModTime == NewXrlModTime), ?assert(YrlModTime == NewYrlModTime). delete_beam_if_source_deleted(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), _SrcDir = filename:join([AppDir, "_build", "default", "lib", Name, "src"]), ?assert(filelib:is_regular(filename:join(EbinDir, "not_a_real_src_" ++ Name ++ ".beam"))), file:delete(filename:join([AppDir, "src", "not_a_real_src_" ++ Name ++ ".erl"])), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), ?assertNot(filelib:is_regular(filename:join(EbinDir, "not_a_real_src_" ++ Name ++ ".beam"))). deps_in_path(Config) -> AppDir = ?config(apps, Config), StartPaths = code:get_path(), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}, {list_to_atom(PkgName), Vsn} ]}]), {ok, RConf} = file:consult(RConfFile), %% Make sure apps we look for are not visible %% Hope not to find src name ?assertEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, DepName)]]), %% Hope not to find pkg name in there ?assertEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, PkgName)]]), %% Build things {ok, State} = rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]} ), code:add_paths(rebar_state:code_paths(State, all_deps)), %% Find src name in there ?assertNotEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, DepName)]]), %% find pkg name in there ?assertNotEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, PkgName)]]), true = code:set_path(lists:filter(fun(P) -> ec_file:exists(P) end, StartPaths)), %% Make sure apps we look for are not visible again %% Hope not to find src name ?assertEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, DepName)]]), %% Hope not to find pkg name in there ?assertEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, PkgName)]]), %% Rebuild {ok, State1} = rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]} ), %% Find src name in there code:add_paths(rebar_state:code_paths(State1, all_deps)), ?assertNotEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, DepName)]]), %% find pkg name in there ?assertNotEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, PkgName)]]). checkout_priority(Config) -> AppDir = ?config(apps, Config), CheckoutsDir = ?config(checkouts, Config), StartPaths = code:get_path(), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}, {list_to_atom(PkgName), Vsn} ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]} ), %% Build two checkout apps similar to dependencies to be fetched, %% but on a different version Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([CheckoutsDir,DepName]), DepName, Vsn2, [kernel, stdlib]), rebar_test_utils:create_app(filename:join([CheckoutsDir,PkgName]), PkgName, Vsn2, [kernel, stdlib]), %% Rebuild and make sure the checkout apps are in path code:set_path(StartPaths), {ok, State} = rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {checkout, DepName}, {checkout, PkgName}]} ), code:add_paths(rebar_state:code_paths(State, all_deps)), [DepPath] = [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, DepName)]], [PkgPath] = [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, PkgName)]], {ok, [DepApp]} = file:consult(filename:join([DepPath, DepName ++ ".app"])), {ok, [PkgApp]} = file:consult(filename:join([PkgPath, PkgName ++ ".app"])), {application, _, DepProps} = DepApp, {application, _, PkgProps} = PkgApp, ?assertEqual(Vsn2, proplists:get_value(vsn, DepProps)), ?assertEqual(Vsn2, proplists:get_value(vsn, PkgProps)). highest_version_of_pkg_dep(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.3">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [list_to_atom(PkgName)]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, PkgName, <<"0.1.3">>}]} ). parse_transform_test(Config) -> AppDir = ?config(apps, Config), RebarConfig = [{erl_opts, [{parse_transform, pascal}]}], Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = <<"-module(pascal). " "-export([parse_transform/2]). " "parse_transform(Forms, _Options) -> " "Forms.">>, ok = file:write_file(filename:join([AppDir, "src", "pascal.erl"]), ExtraSrc), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), true = filelib:is_file(filename:join([EbinDir, "pascal.beam"])). erl_first_files_test(Config) -> AppDir = ?config(apps, Config), RebarConfig = [{erl_opts, [{parse_transform, mark_time}]}, {erl_first_files, ["src/mark_time.erl", "src/b.erl", "src/d.erl", "src/a.erl"]}], Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:write_src_file(AppDir, "a.erl"), rebar_test_utils:write_src_file(AppDir, "b.erl"), rebar_test_utils:write_src_file(AppDir, "d.erl"), rebar_test_utils:write_src_file(AppDir, "e.erl"), ExtraSrc = <<"-module(mark_time). " "-export([parse_transform/2]). " "parse_transform([Form={attribute,_,module,Mod}|Forms], Options) -> " " [Form, {attribute,1,number, os:timestamp()} | Forms];" "parse_transform([Form|Forms], Options) -> " " [Form | parse_transform(Forms, Options)].">>, ok = file:write_file(filename:join([AppDir, "src", "mark_time.erl"]), ExtraSrc), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), true = filelib:is_file(filename:join([EbinDir, "mark_time.beam"])), code:load_abs(filename:join([EbinDir, "a"])), code:load_abs(filename:join([EbinDir, "b"])), code:load_abs(filename:join([EbinDir, "d"])), code:load_abs(filename:join([EbinDir, "e"])), A = proplists:get_value(number, a:module_info(attributes)), B = proplists:get_value(number, b:module_info(attributes)), D = proplists:get_value(number, d:module_info(attributes)), E = proplists:get_value(number, e:module_info(attributes)), ?assertEqual([B,D,A,E], lists:sort([A,B,D,E])). mib_test(Config) -> AppDir = ?config(apps, Config), RebarConfig = [{mib_first_files, ["mibs/SIMPLE-MIB.mib"]}], Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), MibsSrc = <<"-- SIMPLE-MIB.\n" "-- This is just a simple MIB used for testing!\n" "--\n" "SIMPLE-MIB DEFINITIONS ::= BEGIN\n" "IMPORTS\n" " MODULE-IDENTITY, enterprises\n" " FROM SNMPv2-SMI;\n" "\n" "ericsson MODULE-IDENTITY\n" " LAST-UPDATED\n" " \"201403060000Z\"\n" " ORGANIZATION\n" " \"rebar\"\n" " CONTACT-INFO\n" " \"rebar \n" " or\n" " whoever is currently responsible for the SIMPLE\n" " enterprise MIB tree branch (enterprises.999).\"\n" " DESCRIPTION\n" " \"This very small module is made available\n" " for mib-compilation testing.\"\n" " ::= { enterprises 999 }\n" "END\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "mibs", "dummy"])), ok = file:write_file(filename:join([AppDir, "mibs", "SIMPLE-MIB.mib"]), MibsSrc), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), %% check a bin corresponding to the mib in the mibs dir exists in priv/mibs PrivMibsDir = filename:join([AppDir, "_build", "default", "lib", Name, "priv", "mibs"]), true = filelib:is_file(filename:join([PrivMibsDir, "SIMPLE-MIB.bin"])), %% check a hrl corresponding to the mib in the mibs dir exists in include true = filelib:is_file(filename:join([AppDir, "include", "SIMPLE-MIB.hrl"])), %% check the mibs dir was linked into the _build dir true = filelib:is_dir(filename:join([AppDir, "_build", "default", "lib", Name, "mibs"])). umbrella_mib_first_test(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), BExporterSrc = <<"-- BEXPORTER-MIB.\n" "-- This is just a simple MIB used for testing!\n" "--\n" "BEXPORTER-MIB DEFINITIONS ::= BEGIN\n" "IMPORTS\n" " TEXTUAL-CONVENTION\n" " FROM SNMPv2-TC\n" " MODULE-IDENTITY, enterprises\n" " FROM SNMPv2-SMI;\n" "\n" "ericsson MODULE-IDENTITY\n" " LAST-UPDATED\n" " \"201812050000Z\"\n" " ORGANIZATION\n" " \"rebar\"\n" " CONTACT-INFO\n" " \"rebar \n" " or\n" " whoever is currently responsible for the SIMPLE\n" " enterprise MIB tree branch (enterprises.999).\"\n" " DESCRIPTION\n" " \"This very small module is made available\n" " for mib-compilation testing.\"\n" " ::= { enterprises 999 }\n" "\n" "Something ::= TEXTUAL-CONVENTION\n" " STATUS current\n" " DESCRIPTION \"\"\n" " SYNTAX OCTET STRING (SIZE (4))\n" "END\n">>, AImporterSrc = <<"-- AIMPORTER-MIB.\n" "-- This is just a simple MIB used for testing!\n" "--\n" "AIMPORTER-MIB DEFINITIONS ::= BEGIN\n" "IMPORTS\n" " Something\n" " FROM BEXPORTER-MIB\n" " MODULE-IDENTITY, enterprises\n" " FROM SNMPv2-SMI;\n" "\n" "ericsson MODULE-IDENTITY\n" " LAST-UPDATED\n" " \"201812050000Z\"\n" " ORGANIZATION\n" " \"rebar\"\n" " CONTACT-INFO\n" " \"rebar \n" " or\n" " whoever is currently responsible for the SIMPLE\n" " enterprise MIB tree branch (enterprises.999).\"\n" " DESCRIPTION\n" " \"This very small module is made available\n" " for mib-compilation testing.\"\n" " ::= { enterprises 1000 }\n" "END\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "mibs", "dummy"])), ok = file:write_file(filename:join([AppDir, "mibs", "AIMPORTER-MIB.mib"]), AImporterSrc), ok = file:write_file(filename:join([AppDir, "mibs", "BEXPORTER-MIB.mib"]), BExporterSrc), FailureRebarConfig = [{mib_first_files, ["mibs/AIMPORTER-MIB.mib"]}], SuccessRebarConfig = [{mib_first_files, ["mibs/BEXPORTER-MIB.mib"]}], PrivMibsDir = filename:join([AppsDir, "_build", "default", "lib", Name, "priv", "mibs"]), FailureRebarConfig = [{mib_first_files, ["mibs/AIMPORTER-MIB.mib"]}], catch ( rebar_test_utils:run_and_check(Config, FailureRebarConfig, ["compile"], {ok, [{app, Name}]}) ), %% check that the bin file was NOT cretated false = filelib:is_file(filename:join([PrivMibsDir, "AIMPORTER-MIB.bin"])), SuccessRebarConfig = [{mib_first_files, ["mibs/BEXPORTER-MIB.mib"]}], rebar_test_utils:run_and_check(Config, SuccessRebarConfig, ["compile"], {ok, [{app, Name}]}), %% check a bin corresponding to the mib in the mibs dir exists in priv/mibs true = filelib:is_file(filename:join([PrivMibsDir, "AIMPORTER-MIB.bin"])), %% check a hrl corresponding to the mib in the mibs dir exists in include true = filelib:is_file(filename:join([AppDir, "include", "AIMPORTER-MIB.hrl"])), %% check the mibs dir was linked into the _build dir true = filelib:is_dir(filename:join([AppsDir, "_build", "default", "lib", Name, "mibs"])). deps_mib_test() -> [{doc, "reproduces the dependency handling required for the issue " "reported in https://github.com/erlang/rebar3/issues/2372"}]. deps_mib_test(Config) -> Priv = ?config(priv_dir, Config), CliLvl2Mib = "---\n" "---\n" "---\n" "LVL2-MIB DEFINITIONS ::= BEGIN\n" "IMPORTS\n" " MODULE-IDENTITY, OBJECT-TYPE\n" " FROM SNMPv2-SMI\n" " lvlModules, lvlApplications\n" " FROM LVL0-REG\n" " LvlFoo\n" " FROM LVL0-TC\n" " ;\n" "\n" "lvl2Module MODULE-IDENTITY\n" " LAST-UPDATED \"202009261630Z\"\n" " ORGANIZATION \"'some org'\"\n" " CONTACT-INFO \"'Contact: some contact'\"\n" " DESCRIPTION\n" " \" \"\n" " ::= { lvlModules 3 }\n" "\n\n\n" "END", CpiLvl0Mib1 = " \n" "---\n" "---\n\n" "LVL0-TC DEFINITIONS ::= BEGIN\n" "IMPORTS\n" " lvlModules\n" " FROM LVL0-REG\n" " MODULE-IDENTITY\n" " FROM SNMPv2-SMI\n" " TEXTUAL-CONVENTION\n" " FROM SNMPv2-TC\n" " ;\n\n" "lvlTcModule MODULE-IDENTITY\n" " LAST-UPDATED \"202009261630Z\"\n" " ORGANIZATION \"'some org'\"\n" " CONTACT-INFO \"'Contact: some contact'\"\n" " DESCRIPTION\n" " \" This MIB is part of the LVL MIB. It defines common\n" " Textual Conventions used in other LVL mib modules.\"\n" " ::= { lvlModules 2 }\n\n\n" "LvlFoo ::= TEXTUAL-CONVENTION\n" " DISPLAY-HINT \"512a\"\n" " STATUS current\n" " DESCRIPTION \"\"\n" " SYNTAX OCTET STRING (SIZE (1..512))\n\n" "LvlEnum ::= TEXTUAL-CONVENTION\n" " STATUS current\n" " DESCRIPTION \"\"\n" " SYNTAX INTEGER { foo(1), bar(2), baz(3) }\n\n" "END\n", CpiLvl0Mib2 = "---\n---\n---\n\n" "LVL0-REG DEFINITIONS ::= BEGIN\n" "\n" "IMPORTS\n" " MODULE-IDENTITY, enterprises\n" " FROM SNMPv2-SMI\n" " ;\n\n" "lvlRegModule MODULE-IDENTITY\n" " LAST-UPDATED \"202009261630Z\"\n" " ORGANIZATION \"'some org'\"\n" " CONTACT-INFO \"'Contact: some contact'\"\n" " DESCRIPTION\n" " \"The root MIB module for LVL\"\n" " ::= { lvlModules 1 }\n\n" "-- Example Enterprise Number for Documentation use\n" "example OBJECT IDENTIFIER ::= { enterprises 32473 }\n" "\n" "lvl OBJECT IDENTIFIER ::= { example 1 }\n\n" "-- sub-tree for registrations (Modules information)\n" "lvlReg OBJECT IDENTIFIER ::= { lvl 1 }\n" "lvlModules OBJECT IDENTIFIER ::= { lvlReg 1 }\n" "\n" "-- the application subtree\n" "lvlApplications OBJECT IDENTIFIER ::= { lvl 2 }\n" "END\n", CliLvl2Path = filename:join([Priv, "deps_mib", "cli_lvl2", "mibs", "LVL2-MIB.mib"]), CpiLvl0Path1 = filename:join([Priv, "deps_mib", "cpi_lvl0", "mibs", "LVL0-TC.mib"]), CpiLvl0Path2 = filename:join([Priv, "deps_mib", "cpi_lvl0", "mibs", "LVL0-REG.mib"]), NprLvl1Path = filename:join([Priv, "deps_mib", "npr_lvl1", "mibs"]), % no mibs dir FakeLvl1Path = filename:join([Priv, "deps_mib", "fake_lvl1", "mibs", "no_file"]), % no mibs file ok = filelib:ensure_dir(CliLvl2Path), ok = filelib:ensure_dir(CpiLvl0Path1), % CpiLvl0Path2 is the same dir ok = filelib:ensure_dir(NprLvl1Path), ok = filelib:ensure_dir(FakeLvl1Path), ok = file:write_file(CliLvl2Path, CliLvl2Mib), ok = file:write_file(CpiLvl0Path1, CpiLvl0Mib1), ok = file:write_file(CpiLvl0Path2, CpiLvl0Mib2), Res = rebar_compiler_mib:dependencies( CliLvl2Path, filename:dirname(CliLvl2Path), [filename:dirname(CliLvl2Path), filename:dirname(CpiLvl0Path1), NprLvl1Path, filename:dirname(FakeLvl1Path)] ), ?assertEqual(lists:sort([CpiLvl0Path1, CpiLvl0Path2]), lists:sort(Res)), ok. only_default_transitive_deps(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), GitDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}]), PkgName = rebar_test_utils:create_random_name("pkg1_"), {SrcDeps, _} = rebar_test_utils:flat_deps(GitDeps), mock_git_resource:mock([{deps, SrcDeps}, {config, [{profiles, [{test, [{deps, [list_to_atom(PkgName)]}]}]}]}]), mock_pkg_resource:mock([{pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}]}]), Deps = rebar_test_utils:top_level_deps(GitDeps), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, Deps}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["as", "test", "compile"], {ok, [{app, Name}, {dep, "a", <<"1.0.0">>}, {dep_not_exist, PkgName}]} ). clean_all(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}, {list_to_atom(PkgName), Vsn} ]}]), {ok, RConf} = file:consult(RConfFile), %% Build things rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {app, DepName}, {app, PkgName}]} ), %% Clean all rebar_test_utils:run_and_check(Config, [], ["clean", "--all"], {ok, [{app, Name, invalid}, {app, DepName, invalid}, {app, PkgName, invalid}]}). clean_specific(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), iolist_to_binary(Vsn)}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}, {list_to_atom(PkgName), Vsn} ]}]), {ok, RConf} = file:consult(RConfFile), %% Build things rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {app, DepName}, {app, PkgName}]} ), %% Clean all rebar_test_utils:run_and_check(Config, [], ["clean", "--apps="++DepName++","++Name], {ok, [{app, Name, invalid}, {app, DepName, invalid}, {app, PkgName, valid}]}). override_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps}, {overrides, [ {override, some_dep, [ {deps, []} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{dep, "some_dep"}, {dep_not_exist, "other_dep"}]} ). git_subdir_deps(Config) -> Deps = rebar_test_utils:expand_deps(git_subdir, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_subdir_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{subdir_dep, "some_dep"}, {subdir_dep, "other_dep"}]} ). override_add_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), DepA = {dep_a, "0.0.1", {git, "http://site.com/dep_a.git", {tag, "0.0.1"}}}, DepB = {dep_b, "0.0.1", {git, "http://site.com/dep_b.git", {tag, "0.0.1"}}}, DepC = {dep_c, "0.0.1", {git, "http://site.com/dep_c.git", {tag, "0.0.1"}}}, {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, [DepA, DepB, DepC | SrcDeps]}]), RebarConfig = [ {deps, TopDeps}, {overrides, [ {add, some_dep, [ {deps, [DepA, DepB]} ]}, {add, [ {deps, [DepC]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{dep, "some_dep"}, {dep, "other_dep"}, {dep, "dep_a"}, {dep, "dep_b"}, {dep, "dep_c"}]} ). override_del_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"dep_a", "0.0.1", []}, {"dep_b", "0.0.1", []}, {"dep_c", "0.0.1", []}]}, {"other_dep", "0.0.1", [{"dep_c", "0.0.1", []}, {"dep_d", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), DepA = {dep_a, "0.0.1", {git, "https://example.org/user/dep_a.git", {tag, "0.0.1"}}}, DepB = {dep_b, "0.0.1", {git, "https://example.org/user/dep_b.git", {tag, "0.0.1"}}}, DepC = {dep_c, "0.0.1", {git, "https://example.org/user/dep_c.git", {tag, "0.0.1"}}}, {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps}, {overrides, [ {del, some_dep, [ {deps, [DepA, DepB]} ]}, {del, [ {deps, [DepC]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{dep, "some_dep"}, {dep, "other_dep"}, {dep_not_exist, "dep_a"}, {dep_not_exist, "dep_b"}, {dep_not_exist, "dep_c"}, {dep, "dep_d"}]} ). override_del_pkg_deps(Config) -> Deps = rebar_test_utils:expand_deps(pkg, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {_, PkgDeps} = rebar_test_utils:flat_deps(Deps), mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), RebarConfig = [ {deps, TopDeps}, {overrides, [ {del, some_dep, [ {deps, [other_dep]}, %% regression: a non-existing option deletion %% could trigger an infinite loop {provider_hooks, [{post, [{compile, xref}]}]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{dep, "some_dep"}, {dep_not_exist, "other_dep"}]} ). override_opts(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [ compressed, warn_missing_spec ]}, {overrides, [ {override, [ {erl_opts, [compressed]} ]} ]} ], rebar_test_utils:create_config(AppsDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), Path = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). %% test for fix of https://github.com/erlang/rebar3/issues/1801 %% only apply overrides once %% verify by having an override add the macro TEST to the dep some_dep %% building under `ct` will fail if the `add` is applied more than once apply_overrides_exactly_once(Config) -> AppDir = ?config(apps, Config), Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{deps, TopDeps}, {overrides, [ {add, some_dep, [ {erl_opts, [{d, 'TEST'}]} ]} ]}], rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["ct", "--compile_only"], {ok, [{app, Name}, {dep, "some_dep"}], "test"}). override_only_deps(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {deps, []}, %% with deps enabled, this test fails {overrides, [ {add, [ {erl_opts, [{d, bad, a}, {d, bad, b}]} ]} ]} ], rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), ok. override_add_opts(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [ warn_missing_spec ]}, {overrides, [ {add, [ {erl_opts, [compressed]} ]} ]} ], rebar_test_utils:create_config(AppsDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), Path = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), true = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). override_del_opts(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [ compressed, warn_missing_spec ]}, {overrides, [ {del, [ {erl_opts, [warn_missing_spec]} ]} ]} ], rebar_test_utils:create_config(AppsDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), Path = filename:join([AppsDir, "_build", "default", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])), ok. profile_override_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps}, {profiles, [ {a, [ {overrides, [ {override, some_dep, [ {deps, []} ]} ]} ]} ]}], rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{dep, "some_dep"}, {dep_not_exist, "other_dep"}]} ). profile_override_add_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), DepA = {dep_a, "0.0.1", {git, "http://site.com/dep_a.git", {tag, "0.0.1"}}}, DepB = {dep_b, "0.0.1", {git, "http://site.com/dep_b.git", {tag, "0.0.1"}}}, DepC = {dep_c, "0.0.1", {git, "http://site.com/dep_c.git", {tag, "0.0.1"}}}, {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, [DepA, DepB, DepC | SrcDeps]}]), RebarConfig = [ {deps, TopDeps}, {profiles, [ {a, [ {overrides, [ {add, some_dep, [ {deps, [DepA, DepB]} ]}, {add, [ {deps, [DepC]} ]} ]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{dep, "some_dep"}, {dep, "other_dep"}, {dep, "dep_a"}, {dep, "dep_b"}, {dep, "dep_c"}]} ). profile_override_del_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"dep_a", "0.0.1", []}, {"dep_b", "0.0.1", []}, {"dep_c", "0.0.1", []}]}, {"other_dep", "0.0.1", [{"dep_c", "0.0.1", []}, {"dep_d", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), DepA = {dep_a, "0.0.1", {git, "https://example.org/user/dep_a.git", {tag, "0.0.1"}}}, DepB = {dep_b, "0.0.1", {git, "https://example.org/user/dep_b.git", {tag, "0.0.1"}}}, DepC = {dep_c, "0.0.1", {git, "https://example.org/user/dep_c.git", {tag, "0.0.1"}}}, {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps}, {profiles, [ {a, [ {overrides, [ {del, some_dep, [ {deps, [DepA, DepB]} ]}, {del, [ {deps, [DepC]} ]} ]} ]} ]} ], rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{dep, "some_dep"}, {dep, "other_dep"}, {dep_not_exist, "dep_a"}, {dep_not_exist, "dep_b"}, {dep_not_exist, "dep_c"}, {dep, "dep_d"}]} ). profile_override_opts(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [ compressed, warn_missing_spec ]}, {profiles, [ {a, [ {overrides, [ {override, [ {erl_opts, [compressed]} ]} ]} ]} ]} ], rebar_test_utils:create_config(AppsDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}), Path = filename:join([AppsDir, "_build", "a", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). profile_override_add_opts(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [ warn_missing_spec ]}, {profiles, [ {a, [ {overrides, [ {add, [ {erl_opts, [compressed]} ]} ]} ]} ]} ], rebar_test_utils:create_config(AppsDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}), Path = filename:join([AppsDir, "_build", "a", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), true = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])). profile_override_del_opts(Config) -> AppsDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), AppDir = filename:join([AppsDir, "apps", Name]), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [ compressed, warn_missing_spec ]}, {profiles, [ {a, [ {overrides, [ {del, [ {erl_opts, [warn_missing_spec]} ]} ]} ]} ]} ], rebar_test_utils:create_config(AppsDir, RebarConfig), rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{app, Name}]}), Path = filename:join([AppsDir, "_build", "a", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), false = lists:member(warn_missing_spec, proplists:get_value(options, Mod:module_info(compile), [])), ok. profile_deps(Config) -> Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RebarConfig = [ {deps, TopDeps}, {profiles, [{a, []}]}], rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "a", "compile"], {ok, [{dep, "some_dep"},{dep, "other_dep"}]} ). only_deps(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", [{"other_dep", "0.0.1", []}]}]), TopDeps = rebar_test_utils:top_level_deps(Deps), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]), {ok, RConf} = file:consult(RConfFile), rebar_test_utils:run_and_check( Config, RConf, ["compile", "--deps_only"], {ok, [{app_not_exist, Name}, {dep, "some_dep"},{dep, "other_dep"}]} ). %% verify a deps prod profile is used %% tested by checking prod hooks run and outputs to default profile dir for dep %% and prod deps are installed for dep deps_build_in_prod(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), GitDeps = rebar_test_utils:expand_deps(git, [{"asdf", "1.0.0", []}]), PkgName = rebar_test_utils:create_random_name("pkg1_"), {SrcDeps, _} = rebar_test_utils:flat_deps(GitDeps), mock_git_resource:mock([{deps, SrcDeps}, {config, [{profiles, [{prod, [{pre_hooks, [{compile, "echo whatsup > randomfile"}]}, {deps, [list_to_atom(PkgName)]}]}]}]}]), mock_pkg_resource:mock([{pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}]}]), Deps = rebar_test_utils:top_level_deps(GitDeps), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, Deps}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, "asdf", <<"1.0.0">>}, {dep, PkgName}, {file, filename:join([AppDir, "_build", "default", "lib", "asdf", "randomfile"])}]} ). %% verify that the proper include path is defined %% according the erlang doc which states: %% If the filename File is absolute (possibly after variable substitution), %% the include file with that name is included. Otherwise, the specified file %% is searched for in the following directories, and in this order: %% * The current working directory %% * The directory where the module is being compiled %% * The directories given by the include option include_file_relative_to_working_directory(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Src = <<"-module(test).\n" "\n" "-include(\"include/test.hrl\").\n" "\n" "test() -> ?TEST_MACRO.\n" "\n">>, Include = <<"-define(TEST_MACRO, test).\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ok = file:write_file(filename:join([AppDir, "src", "test.erl"]), Src), ok = filelib:ensure_dir(filename:join([AppDir, "include", "dummy"])), ok = file:write_file(filename:join([AppDir, "include", "test.hrl"]), Include), RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}). include_file_in_src(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Src = <<"-module(test).\n" "\n" "-include(\"test.hrl\").\n" "\n" "test() -> ?TEST_MACRO.\n" "\n">>, Include = <<"-define(TEST_MACRO, test).\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ok = file:write_file(filename:join([AppDir, "src", "test.erl"]), Src), ok = file:write_file(filename:join([AppDir, "src", "test.hrl"]), Include), RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}). %% verify that the proper include path is defined %% according the erlang doc which states: %% If the filename File is absolute (possibly after variable substitution), %% the include file with that name is included. Otherwise, the specified file %% is searched for in the following directories, and in this order: %% * The current working directory %% * The directory where the module is being compiled %% * The directories given by the include option %% %% This test ensures that things keep working when additional directories %% are used for apps, such as the test/ directory within the test profile. include_file_relative_to_working_directory_test(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Src = <<"-module(test).\n" "\n" "-include(\"include/test.hrl\").\n" "\n" "test() -> ?TEST_MACRO.\n" "\n">>, Include = <<"-define(TEST_MACRO, test).\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir, "test", "dummy"])), ok = file:write_file(filename:join([AppDir, "test", "test.erl"]), Src), ok = filelib:ensure_dir(filename:join([AppDir, "include", "dummy"])), ok = file:write_file(filename:join([AppDir, "include", "test.hrl"]), Include), RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "test", "compile"], {ok, [{app, Name}]}). %% Same as `include_file_in_src/1' but using the `test/' directory %% within the test profile. include_file_in_src_test(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Src = <<"-module(test).\n" "\n" "-include(\"test.hrl\").\n" "\n" "test() -> ?TEST_MACRO.\n" "\n">>, Include = <<"-define(TEST_MACRO, test).\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir, "test", "dummy"])), ok = file:write_file(filename:join([AppDir, "test", "test.erl"]), Src), ok = file:write_file(filename:join([AppDir, "src", "test.hrl"]), Include), RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "test", "compile"], {ok, [{app, Name}]}). %% Same as `include_file_in_src_test/1' but using multiple top-level %% apps as dependencies. include_file_in_src_test_multiapp(Config) -> Name1 = rebar_test_utils:create_random_name("app2_"), Name2 = rebar_test_utils:create_random_name("app1_"), AppDir1 = filename:join([?config(apps, Config), "lib", Name1]), AppDir2 = filename:join([?config(apps, Config), "lib", Name2]), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir1, Name1, Vsn, [kernel, stdlib, list_to_atom(Name2)]), rebar_test_utils:create_app(AppDir2, Name2, Vsn, [kernel, stdlib]), Src = "-module(test).\n" "\n" "-include_lib(\"" ++ Name2 ++ "/include/test.hrl\").\n" "\n" "test() -> ?TEST_MACRO.\n" "\n", Include = <<"-define(TEST_MACRO, test).\n">>, ok = filelib:ensure_dir(filename:join([AppDir1, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir1, "test", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir2, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir2, "include", "dummy"])), ok = file:write_file(filename:join([AppDir1, "test", "test.erl"]), Src), ok = file:write_file(filename:join([AppDir2, "include", "test.hrl"]), Include), RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "test", "compile"], {ok, [{app, Name1}]}), ok. %% this test sets the env var, compiles, records the file last modified timestamp, %% recompiles and compares the file last modified timestamp to ensure it hasn't %% changed. this test should run on 19.x+ dont_recompile_when_erl_compiler_options_env_does_not_change(Config) -> %% save existing env to restore after test ExistingEnv = os:getenv("ERL_COMPILER_OPTIONS"), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("erl_compiler_options_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), true = os:unsetenv("ERL_COMPILER_OPTIONS"), true = os:putenv("ERL_COMPILER_OPTIONS", "[{d, some_macro}]"), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime == NewModTime), %% restore existing env case ExistingEnv of false -> ok; _ -> os:putenv("ERL_COMPILER_OPTIONS", ExistingEnv) end. %% this test compiles, records the file last modified timestamp, sets the env %% var, recompiles and compares the file last modified timestamp to ensure it %% has changed. this test should run on 19.x+ recompile_when_erl_compiler_options_env_changes(Config) -> %% save existing env to restore after test ExistingEnv = os:getenv("ERL_COMPILER_OPTIONS"), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("erl_compiler_options_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), true = os:unsetenv("ERL_COMPILER_OPTIONS"), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), true = os:putenv("ERL_COMPILER_OPTIONS", "[{d, some_macro}]"), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime), %% restore existing env case ExistingEnv of false -> ok; _ -> os:putenv("ERL_COMPILER_OPTIONS", ExistingEnv) end. rebar_config_os_var(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("rebar_config_os_var_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(AppDir, [{erl_opts, []}]), AltConfig = filename:join(AppDir, "test.rebar.config"), file:write_file(AltConfig, "{erl_opts, [compressed]}."), true = os:putenv("REBAR_CONFIG", AltConfig), rebar_test_utils:run_and_check(Config, ["compile"], {ok, [{app, Name}]}), Path = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member(compressed, proplists:get_value(options, Mod:module_info(compile), [])), ok. %% this test sets the env var, compiles, records the file last modified %% timestamp, recompiles and compares the file last modified timestamp to %% ensure it has changed. this test should run on 18.x always_recompile_when_erl_compiler_options_set(Config) -> %% save existing env to restore after test ExistingEnv = os:getenv("ERL_COMPILER_OPTIONS"), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("erl_compiler_options_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), true = os:unsetenv("ERL_COMPILER_OPTIONS"), true = os:putenv("ERL_COMPILER_OPTIONS", "[{d, some_macro}]"), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:extension(F) == ".beam"], timer:sleep(1000), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:extension(F) == ".beam"], ?assert(ModTime =/= NewModTime), %% restore existing env case ExistingEnv of false -> ok; _ -> os:putenv("ERL_COMPILER_OPTIONS", ExistingEnv) end. recompile_when_parse_transform_inline_changes(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("parse_transform_inline_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ModSrc = <<"-module(example).\n" "-export([foo/2]).\n" "-compile([{parse_transform, example_parse_transform}]).\n" "foo(_, _) -> ok.">>, ok = file:write_file(filename:join([AppDir, "src", "example.erl"]), ModSrc), ParseTransform = <<"-module(example_parse_transform).\n" "-export([parse_transform/2]).\n" "parse_transform(AST, _) -> AST.\n">>, ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]), ParseTransform), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:basename(F, ".beam") == "example"], timer:sleep(1000), NewParseTransform = <<"-module(example_parse_transform).\n" "-export([parse_transform/2]).\n" "parse_transform(AST, _) -> identity(AST).\n" "identity(AST) -> AST.\n">>, ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]), NewParseTransform), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:basename(F, ".beam") == "example"], ?assert(ModTime =/= NewModTime). recompile_when_parse_transform_as_opt_changes(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("parse_transform_opt_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ModSrc = <<"-module(example).\n" "-export([foo/2]).\n" "foo(_, _) -> ok.">>, ok = file:write_file(filename:join([AppDir, "src", "example.erl"]), ModSrc), ParseTransform = <<"-module(example_parse_transform).\n" "-export([parse_transform/2]).\n" "parse_transform(AST, _) -> AST.">>, ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]), ParseTransform), RebarConfig = [{erl_opts, [{parse_transform, example_parse_transform}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:basename(F, ".beam") == "example"], timer:sleep(1000), NewParseTransform = <<"-module(example_parse_transform).\n" "-export([parse_transform/2]).\n" "parse_transform(AST, _) -> identity(AST).\n" "identity(AST) -> AST.">>, ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]), NewParseTransform), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:basename(F, ".beam") == "example"], ?assert(ModTime =/= NewModTime). dont_recompile_when_parse_transform_as_opt_unchanged(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("parse_transform_opt_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])), ModSrc = <<"-module(example).\n" "-export([foo/2]).\n" "foo(_, _) -> ok.">>, ok = file:write_file(filename:join([AppDir, "src", "example.erl"]), ModSrc), ParseTransform = <<"-module(example_parse_transform).\n" "-export([parse_transform/2]).\n" "parse_transform(AST, _) -> AST.">>, ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]), ParseTransform), RebarConfig = [{erl_opts, [{parse_transform, example_parse_transform}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- Files, filename:basename(F, ".beam") == "example"], timer:sleep(1000), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), {ok, NewFiles} = rebar_utils:list_dir(EbinDir), NewModTime = [filelib:last_modified(filename:join([EbinDir, F])) || F <- NewFiles, filename:basename(F, ".beam") == "example"], ?assert(ModTime =:= NewModTime). recursive(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:write_src_file(filename:join(AppDir,src),"rec.erl"), rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files} = rebar_utils:list_dir(EbinDir), ?assert(lists:member("rec.beam",Files)), %% check that rec is in modules list of .app file AppFile = filename:join(EbinDir, Name++".app"), {ok, [{application, _, List}]} = file:consult(AppFile), {modules, Modules} = lists:keyfind(modules, 1, List), ?assert(lists:member(rec, Modules)). no_recursive(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:write_src_file(filename:join(AppDir,src),"rec.erl"), RebarConfig1 = [{erlc_compiler,[{recursive,false}]}], rebar_test_utils:run_and_check(Config, RebarConfig1, ["compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]), {ok, Files1} = rebar_utils:list_dir(EbinDir), ?assert(false==lists:member("rec.beam",Files1)), RebarConfig2 = [{src_dirs,[{"src",[{recursive,false}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig2, ["compile"], {ok, [{app, Name}]}), {ok, Files2} = rebar_utils:list_dir(EbinDir), ?assert(false==lists:member("rec.beam",Files2)), ok. extra_recursion(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:write_src_file(filename:join([AppDir, "src", "src2"]), "rec.erl"), rebar_test_utils:write_src_file(filename:join([AppDir, "test", "test2"]), "rectest.erl"), %% Default for src directories: recursive %% default for extra_src directories: non-recursive RebarConfig1 = [], rebar_test_utils:run_and_check(Config, RebarConfig1, ["as", "test", "compile"], {ok, [{app, Name}]}), EbinDir = filename:join([AppDir, "_build", "test", "lib", Name, "ebin"]), {ok, Files1} = rebar_utils:list_dir(EbinDir), ?assert(lists:member("rec.beam", Files1)), file:delete(filename:join(EbinDir, "rec.beam")), TestEbinDir = filename:join([AppDir, "_build", "test", "lib", Name, "test"]), {ok, TestFiles1} = rebar_utils:list_dir(TestEbinDir), ?assertNot(lists:member("rectest.beam", TestFiles1)), RebarConfig2 = [{src_dirs,[{"src",[{recursive,false}]}]}, {extra_src_dirs, [{"test", [{recursive, true}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig2, ["as", "test", "compile"], {ok, [{app, Name}]}), {ok, Files2} = rebar_utils:list_dir(EbinDir), ?assertNot(lists:member("rec.beam",Files2)), {ok, TestFiles2} = rebar_utils:list_dir(TestEbinDir), ?assert(lists:member("rectest.beam", TestFiles2)), ok. regex_filter_skip(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("regex_skip"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:write_src_file(filename:join(AppDir,src),"._rec.erl"), Expected = filename:join([AppDir, "_build", "default", "lib", Name, "ebin","._rec.beam"]), RebarConfig = [], try rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{file, Expected}]}), throw(should_not_be_found) catch %% the file was not found, as desired! error:{assertion_failed,_} -> %% OTP =< 17 ok; error:{assert,_} -> %% OTP >= 18 ok end. regex_filter_regression(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("regex_regression"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:write_src_file(filename:join(AppDir,src),"r_f.erl"), Expected = filename:join([AppDir, "_build", "default", "lib", Name, "ebin","r_f.beam"]), RebarConfig = [], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{file, Expected}]}), ok. %% This test could also have existed in rebar_hooks_SUITE but it's more %% about compiler implementation details than the hook logic itself, %% so it was located here. split_project_apps_hooks() -> [{doc, "Ensure that a project with multiple project apps runs the " "pre-hooks before all the apps are compiled, and the post " "hooks after they are all compiled."}]. split_project_apps_hooks(Config) -> BaseDir = ?config(apps, Config), Name1 = rebar_test_utils:create_random_name("app2_"), Name2 = rebar_test_utils:create_random_name("app1_"), AppDir1 = filename:join([BaseDir, "lib", Name1]), AppDir2 = filename:join([BaseDir, "lib", Name2]), HookDir = filename:join([BaseDir, "hooks"]), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir1, Name1, Vsn, [kernel, stdlib, list_to_atom(Name2)]), rebar_test_utils:create_app(AppDir2, Name2, Vsn, [kernel, stdlib]), ok = filelib:ensure_dir(filename:join([AppDir1, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir1, "test", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir2, "src", "dummy"])), ok = filelib:ensure_dir(filename:join([AppDir2, "include", "dummy"])), ok = filelib:ensure_dir(filename:join([HookDir, "dummy"])), Cmd = case os:type() of {win32, _} -> "dir /B"; _ -> "ls" end, Cfg = fun(Name) -> [{pre_hooks, [{compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "pre-compile-"++Name)++"\""}, {erlc_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "pre-erlc-"++Name)++"\""}, {app_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "pre-app-"++Name)++"\""}]}, {post_hooks, [{compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "post-compile-"++Name)++"\""}, {erlc_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "post-erlc-"++Name)++"\""}, {app_compile, Cmd++" \""++HookDir++"\" > \""++filename:join(HookDir, "post-app-"++Name)++"\""}]} ] end, ok = file:write_file(filename:join(AppDir1, "rebar.config"), io_lib:format("~p.~n~p.", Cfg("app1"))), ok = file:write_file(filename:join(AppDir2, "rebar.config"), io_lib:format("~p.~n~p.", Cfg("app2"))), RebarConfig = Cfg("all"), rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name1}, {app, Name2}]}), %% Now for the big party: %% - we expect whole pre-hooks to run before either app is compiled %% - we don't expect app and erlc hooks on the total run %% - we expect app2 to be compiled before app1 (rev alphabetical order) %% - we expect all pre-hooks to show up before post-hooks %% - the pre-order is: compile->erlc, taking place before any app %% is actually compiled, so that analysis can be done on all apps. %% - the post-order is more as expected: %% - erlc post hook runs right with the app %% - app pre hook runs right with the app %% - app post hook runs right with the app %% - compile post hook runs for each app individually %% - we expect app compile post-hooks to show up in order %% - we expect whole post-hooks to run last CallOrder = [ "pre-compile-all", "pre-compile-app2", "pre-compile-app1", "pre-erlc-app2", "pre-erlc-app1", "post-erlc-app2", "post-erlc-app1", "pre-app-app2", "pre-app-app1", "post-app-app2", "post-app-app1", "post-compile-app2", "post-compile-app1", "post-compile-all" ], validate_call_order(CallOrder, HookDir), ok. validate_call_order(Calls, Dir) -> validate_call_order(Calls, Dir, []). validate_call_order([], _, _) -> ok; validate_call_order([Name|T], Dir, Seen) -> {ok, Bin} = file:read_file(filename:join(Dir, Name)), %% weird list of tokens, but works on lexemes/tokens for backwards compat Found = rebar_string:lexemes(binary_to_list(Bin), [$\n, $\r, "\r\n"]), NewSeen = [Name|Seen], ?assertEqual({Name, Found}, {Name, lists:sort(NewSeen)}), validate_call_order(T, Dir, NewSeen). app_file_linting(Config) -> meck:new(rebar_log, [no_link, passthrough]), AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app_file_linting"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [foo]), _ = rebar_test_utils:run_and_check(Config, [], ["compile"], return), History = meck:history(rebar_log), Warnings = [{Str, Args} || {_, {rebar_log, log, [warn, Str, Args]}, _} <- History], ?assert(none /= proplists:lookup("~p is missing description entry", Warnings)), ?assert(none /= proplists:lookup("~p is missing kernel from applications list", Warnings)), ?assert(none /= proplists:lookup("~p is missing stdlib from applications list", Warnings)). %% %% a copy of lib/parsetools/include/yeccpre.hrl so we can test yrl includefile yeccpre_hrl() -> <<"-type yecc_ret() :: {'error', _} | {'ok', _}. -spec parse(Tokens :: list()) -> yecc_ret(). parse(Tokens) -> yeccpars0(Tokens, {no_func, no_line}, 0, [], []). -spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) -> yecc_ret(). parse_and_scan({F, A}) -> yeccpars0([], {{F, A}, no_line}, 0, [], []); parse_and_scan({M, F, A}) -> Arity = length(A), yeccpars0([], {{fun M:F/Arity, A}, no_line}, 0, [], []). -spec format_error(any()) -> [char() | list()]. format_error(Message) -> case io_lib:deep_char_list(Message) of true -> Message; _ -> io_lib:write(Message) end. %% To be used in grammar files to throw an error message to the parser %% toplevel. Doesn't have to be exported! -compile({nowarn_unused_function, return_error/2}). -spec return_error(integer(), any()) -> no_return(). return_error(Line, Message) -> throw({error, {Line, ?MODULE, Message}}). -define(CODE_VERSION, \"1.4\"). yeccpars0(Tokens, Tzr, State, States, Vstack) -> try yeccpars1(Tokens, Tzr, State, States, Vstack) catch error:Error -> try yecc_error_type(Error, []) of Desc -> erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc}, []) catch _:_ -> erlang:raise(error, Error, []) end; %% Probably thrown from return_error/2: throw: {error, {_Line, ?MODULE, _M}} = Error -> Error end. yecc_error_type(function_clause, _) -> not_implemented. yeccpars1([Token | Tokens], Tzr, State, States, Vstack) -> yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr); yeccpars1([], {{F, A},_Line}, State, States, Vstack) -> case apply(F, A) of {ok, Tokens, Endline} -> yeccpars1(Tokens, {{F, A}, Endline}, State, States, Vstack); {eof, Endline} -> yeccpars1([], {no_func, Endline}, State, States, Vstack); {error, Descriptor, _Endline} -> {error, Descriptor} end; yeccpars1([], {no_func, no_line}, State, States, Vstack) -> Line = 999999, yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [], {no_func, Line}); yeccpars1([], {no_func, Endline}, State, States, Vstack) -> yeccpars2(State, '$end', States, Vstack, yecc_end(Endline), [], {no_func, Endline}). %% yeccpars1/7 is called from generated code. %% %% When using the {includefile, Includefile} option, make sure that %% yeccpars1/7 can be found by parsing the file without following %% include directives. yecc will otherwise assume that an old %% yeccpre.hrl is included (one which defines yeccpars1/5). yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) -> yeccpars2(State, element(1, Token), [State1 | States], [Token0 | Vstack], Token, Tokens, Tzr); yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Line}=Tzr) -> yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]); yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_line}) -> Line = yecctoken_end_location(Token0), yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack], yecc_end(Line), [], {no_func, Line}); yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Line}) -> yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack], yecc_end(Line), [], {no_func, Line}). %% For internal use only. yecc_end({Line,_Column}) -> {'$end', Line}; yecc_end(Line) -> {'$end', Line}. yecctoken_end_location(Token) -> try erl_anno:end_location(element(2, Token)) of undefined -> yecctoken_location(Token); Loc -> Loc catch _:_ -> yecctoken_location(Token) end. -compile({nowarn_unused_function, yeccerror/1}). yeccerror(Token) -> Text = yecctoken_to_string(Token), Location = yecctoken_location(Token), {error, {Location, ?MODULE, [\"syntax error before: \", Text]}}. -compile({nowarn_unused_function, yecctoken_to_string/1}). yecctoken_to_string(Token) -> try erl_scan:text(Token) of undefined -> yecctoken2string(Token); Txt -> Txt catch _:_ -> yecctoken2string(Token) end. yecctoken_location(Token) -> try erl_scan:location(Token) catch _:_ -> element(2, Token) end. -compile({nowarn_unused_function, yecctoken2string/1}). yecctoken2string({atom, _, A}) -> io_lib:write_atom(A); yecctoken2string({integer,_,N}) -> io_lib:write(N); yecctoken2string({float,_,F}) -> io_lib:write(F); yecctoken2string({char,_,C}) -> io_lib:write_char(C); yecctoken2string({var,_,V}) -> io_lib:format(\"~s\", [V]); yecctoken2string({string,_,S}) -> io_lib:write_string(S); yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A); yecctoken2string({_Cat, _, Val}) -> io_lib:format(\"~p\", [Val]); yecctoken2string({dot, _}) -> \"'.'\"; yecctoken2string({'$end', _}) -> []; yecctoken2string({Other, _}) when is_atom(Other) -> io_lib:write_atom(Other); yecctoken2string(Other) -> io_lib:format(\"~p\", [Other]). ">>. rebar3-3.18.0/test/rebar_utils_SUITE.erl0000644000232200023220000003115214164317745020314 0ustar debalancedebalance-module(rebar_utils_SUITE). -export([all/0, init_per_testcase/2, end_per_testcase/2, groups/0, init_per_group/2, end_per_group/2, empty_arglist/1, single_task/1, single_task_with_immediate_comma/1, single_task_with_trailing_comma/1, multiple_task/1, multiple_task_no_spaces/1, multiple_task_with_immediate_comma/1, multiple_task_with_trailing_comma/1, task_with_arg/1, task_with_arg_with_immediate_comma/1, task_with_arg_with_trailing_comma/1, task_with_multiple_args/1, task_with_flag/1, task_with_flag_with_immediate_comma/1, task_with_flag_with_trailing_comma/1, task_with_flag_with_commas/1, task_with_multiple_flags/1, special_task_do/1, valid_otp_version/1, valid_old_format_otp_version/1, valid_otp_version_equal/1, invalid_otp_version/1, nonblacklisted_otp_version/1, blacklisted_otp_version/1, sh_does_not_miss_messages/1, tup_merge/1, proxy_auth/1, is_list_of_strings/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). end_per_testcase(_, _Config) -> catch meck:unload(). all() -> [{group, args_to_tasks}, sh_does_not_miss_messages, tup_merge, proxy_auth, is_list_of_strings]. groups() -> [{args_to_tasks, [], [empty_arglist, single_task, single_task_with_immediate_comma, single_task_with_trailing_comma, multiple_task, multiple_task_no_spaces, multiple_task_with_immediate_comma, multiple_task_with_trailing_comma, task_with_arg, task_with_arg_with_immediate_comma, task_with_arg_with_trailing_comma, task_with_multiple_args, task_with_flag, task_with_flag_with_immediate_comma, task_with_flag_with_trailing_comma, task_with_flag_with_commas, task_with_multiple_flags, special_task_do, valid_otp_version, valid_old_format_otp_version, valid_otp_version_equal, invalid_otp_version, nonblacklisted_otp_version, blacklisted_otp_version ]}]. init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. empty_arglist(_Config) -> [] = rebar_utils:args_to_tasks([]). single_task(_Config) -> [{"foo", []}] = rebar_utils:args_to_tasks(["foo"]). single_task_with_immediate_comma(_Config) -> [{"foo", []}] = rebar_utils:args_to_tasks(["foo,"]). single_task_with_trailing_comma(_Config) -> [{"foo", []}] = rebar_utils:args_to_tasks(["foo", ","]). multiple_task(_Config) -> [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo,", "bar,", "baz"]). multiple_task_no_spaces(_Config) -> [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo,bar,baz"]). multiple_task_with_immediate_comma(_Config) -> [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo,", "bar,", "baz,"]). multiple_task_with_trailing_comma(_Config) -> [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", ",", "bar", ",", "baz", ","]). task_with_arg(_Config) -> [{"foo", ["bar"]}] = rebar_utils:args_to_tasks(["foo", "bar"]). task_with_arg_with_immediate_comma(_Config) -> [{"foo", ["bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "bar,", "baz"]). task_with_arg_with_trailing_comma(_Config) -> [{"foo", ["bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "bar", ",", "baz"]). task_with_multiple_args(_Config) -> [{"foo", ["bar", "baz"]}] = rebar_utils:args_to_tasks(["foo", "bar", "baz"]). task_with_flag(_Config) -> [{"foo", ["--bar"]}] = rebar_utils:args_to_tasks(["foo", "--bar"]). task_with_flag_with_immediate_comma(_Config) -> [{"foo", ["--bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "--bar,", "baz"]). task_with_flag_with_trailing_comma(_Config) -> [{"foo", ["--bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "--bar", ",", "baz"]). task_with_flag_with_commas(_Config) -> [{"foo", ["--bar=baz,qux"]}] = rebar_utils:args_to_tasks(["foo", "--bar=baz,qux"]). task_with_multiple_flags(_Config) -> [{"foo", ["--bar", "--baz"]}] = rebar_utils:args_to_tasks(["foo", "--bar", "--baz"]). special_task_do(_Config) -> [{"foo", []}, {"do", ["bar,", "baz"]}] = rebar_utils:args_to_tasks(["foo,", "do", "bar,", "baz"]). valid_otp_version(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, otp_release, fun() -> "42.4" end), rebar_utils:check_min_otp_version("42.3"), meck:unload(rebar_utils). valid_old_format_otp_version(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, otp_release, fun() -> "R15B03-1" end), rebar_utils:check_min_otp_version("14"), meck:expect(rebar_utils, otp_release, fun() -> "R16B03" end), rebar_utils:check_min_otp_version("16.0"), meck:expect(rebar_utils, otp_release, fun() -> "18.0.1" end), rebar_utils:check_min_otp_version("17.5.4"), meck:expect(rebar_utils, otp_release, fun() -> "18.0-rc1" end), ?assertException(throw, rebar_abort, rebar_utils:check_min_otp_version("19")), meck:unload(rebar_utils). valid_otp_version_equal(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, otp_release, fun() -> "42.3" end), rebar_utils:check_min_otp_version("42.3"), meck:unload(rebar_utils). invalid_otp_version(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, otp_release, fun() -> "17.4" end), ?assertException(throw, rebar_abort, rebar_utils:check_min_otp_version("42.3")), meck:unload(rebar_utils). nonblacklisted_otp_version(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, otp_release, fun() -> "42.4" end), rebar_utils:check_blacklisted_otp_versions(["1\\.2", "42\\.3"]), meck:unload(rebar_utils). blacklisted_otp_version(_Config) -> meck:new(rebar_utils, [passthrough]), meck:expect(rebar_utils, otp_release, fun() -> "42.4" end), ?assertException(throw, rebar_abort, rebar_utils:check_blacklisted_otp_versions(["1\\.2", "42\\.[1-4]"])), meck:unload(rebar_utils). sh_does_not_miss_messages(_Config) -> Source = "~nmain(_) ->~n io:format(\"donotmissme\").~n", file:write_file("do_not_miss_messages", io_lib:format(Source,[])), {ok, "donotmissme"} = rebar_utils:sh("escript do_not_miss_messages", []), AnyMessageRemained = receive What -> What after 100 -> false end, AnyMessageRemained = false. tup_merge(_Config) -> ?assertEqual( [a,{a,a},{a,a,a},{a,b},{a,b,b},b,{b,a},{b,a,a},{b,b},{b,b,b},z,{z,a},{z,a,a},{z,b},{z,b,b}], rebar_utils:tup_umerge( rebar_utils:tup_sort([a,{a,a},{a,a,a},b,{b,a},{b,a,a},z,{z,a},{z,a,a}]), rebar_utils:tup_sort([a,{a,b},{a,b,b},b,{b,b},{b,b,b},z,{z,b},{z,b,b}]) ) ), ?assertEqual( [a,{a,b},{a,b,b},{a,a},{a,a,a},b,{b,b},{b,b,b},{b,a},{b,a,a},z,{z,b},{z,b,b},{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([a,{a,b},{a,b,b},b,{b,b},{b,b,b},z,{z,b},{z,b,b}]), rebar_utils:tup_sort([a,{a,a},{a,a,a},b,{b,a},{b,a,a},z,{z,a},{z,a,a}]) ) ), ?assertEqual( [a,{a,b},{a,b,b},{a,a},{a,a,a},b,{b,b},{b,b,b},{b,a},{b,a,a},z,{z,b},{z,b,b},{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([a,b,z,{a,b},{b,b},{z,b},{a,b,b},{b,b,b},{z,b,b}]), rebar_utils:tup_sort([a,{a,a},{a,a,a},b,{b,a},{b,a,a},z,{z,a},{z,a,a}]) ) ), ?assertEqual( [{a,b},a,{a,b,b},{a,a},{a,a,a},{b,b},b,{b,b,b},{b,a},{b,a,a},{z,b},z,{z,b,b},{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([{a,b},{b,b},{z,b},a,b,z,{a,b,b},{b,b,b},{z,b,b}]), rebar_utils:tup_sort([a,{a,a},{a,a,a},b,{b,a},{b,a,a},z,{z,a},{z,a,a}]) ) ), ?assertEqual( [a,{a,b},{a,b,b},{a,a},{a,a,a},b,{b,b},{b,b,b},{b,a},{b,a,a},z,{z,b},{z,b,b},{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([a,{a,b},{a,b,b},b,{b,b},{b,b,b},z,{z,b},{z,b,b}]), rebar_utils:tup_sort([{a,a},a,{a,a,a},{b,a},b,{b,a,a},{z,a},z,{z,a,a}]) ) ), ?assertEqual( [{a,b},a,{a,b,b},{a,a},{a,a,a},{b,b},b,{b,b,b},{b,a},{b,a,a},{z,b},z,{z,b,b},{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([{a,b},{b,b},{z,b},a,b,z,{a,b,b},{b,b,b},{z,b,b}]), rebar_utils:tup_sort([{a,a},a,{a,a,a},{b,a},b,{b,a,a},{z,a},z,{z,a,a}]) ) ), ?assertEqual( [{a,b},{a,b,b},a,{a,a},{a,a,a},{b,b},{b,b,b},b,{b,a},{b,a,a},{z,b},{z,b,b},z,{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([{a,b},{a,b,b},{b,b},{b,b,b},{z,b},{z,b,b},a,b,z]), rebar_utils:tup_sort([{a,a},{a,a,a},a,{b,a},{b,a,a},b,{z,a},{z,a,a},z]) ) ), ?assertEqual( [{a,b},{a,b,b},a,{a,a},{a,a,a},{b,b},{b,b,b},b,{b,a},{b,a,a},{z,b},{z,b,b},z,{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([{a,b},{a,b,b},{b,b},{b,b,b},{z,b},{z,b,b},a,b,z]), rebar_utils:tup_sort([{a,a},{a,b},{a,a,a},{a,b,b},a,{b,a},{b,a,a},b,{z,a},{z,a,a},z]) ) ), ?assertEqual( [{l, a}, {r, a, b}, {s, a}, {s, b}], rebar_utils:tup_umerge( rebar_utils:tup_sort([{r, a, b}, {s, a}, {l, a}]), rebar_utils:tup_sort([{s, b}]) ) ), ?assertEqual( [{a,b,b},{a,b},a,{a,a},{a,a,a},{b,b},{b,b,b},b,{b,a,a},{b,a},{z,b},{z,b,b},z,{z,a},{z,a,a}], rebar_utils:tup_umerge( rebar_utils:tup_sort([{a,b,b},{b,b},{a,b},{b,b,b},{z,b},{z,b,b},a,b,z]), rebar_utils:tup_sort([{a,a},{a,a,a},a,{b,a,a},b,{z,a},{z,a,a},{b,a},z]) ) ). proxy_auth(Config) -> proxy_auth(Config, "http://", "http_proxy"), proxy_auth(Config, "https://", "https_proxy"), proxy_auth(Config, "", "http_proxy"), proxy_auth(Config, "", "https_proxy"). proxy_auth(_Config, Schema, ProxyEnvKey) -> Host = "host:", Port = "1234", %% remember current proxy specification OldProxySpec = os:getenv(ProxyEnvKey), %% proxy auth not set application:unset_env(rebar, proxy_auth), ?assertEqual([], rebar_utils:get_proxy_auth()), %% proxy auth with regular username/password os:putenv(ProxyEnvKey, Schema++"Username:Password@" ++ Host ++ Port), rebar_utils:set_httpc_options(), ?assertEqual([{proxy_auth, {"Username", "Password"}}], rebar_utils:get_proxy_auth()), %% proxy auth with username missing and url encoded password os:putenv(ProxyEnvKey, Schema++":%3F!abc%23%24@" ++ Host ++ Port), rebar_utils:set_httpc_options(), ?assertEqual([{proxy_auth, {"", "?!abc#$"}}], rebar_utils:get_proxy_auth()), %% restore original proxy specification if any restore_proxy_env(ProxyEnvKey, OldProxySpec), application:unset_env(rebar, proxy_auth). restore_proxy_env(ProxyEnvKey, false) -> os:putenv(ProxyEnvKey, ""); restore_proxy_env(ProxyEnvKey, ProxySpec) -> os:putenv(ProxyEnvKey, ProxySpec). is_list_of_strings(_Config) -> ?assert(rebar_utils:is_list_of_strings(["foo"])), ?assert(rebar_utils:is_list_of_strings([])), ?assert(rebar_utils:is_list_of_strings("")), ?assert(rebar_utils:is_list_of_strings("foo") == false). rebar3-3.18.0/test/rebar_paths_SUITE.erl0000644000232200023220000002531414164317745020276 0ustar debalancedebalance-module(rebar_paths_SUITE). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). -compile(export_all). all() -> [clashing_apps, check_modules, set_paths, misloaded_mods ]. %%%%%%%%%%%%%%%%%% %%% TEST SETUP %%% %%%%%%%%%%%%%%%%%% init_per_testcase(Case, Config) -> BasePaths = code:get_path(), %% This test checks that the right module sets get loaded; however, we must %% ensure that we do not have clashes with other test suites' loaded modules, %% which we cannot track. As such, we have to ensure all module names here are %% unique. %% %% This is done by hand; if you see this test suite failing on its own, you %% probably wrote a test suite that clashes! Dir = filename:join([?config(priv_dir, Config), atom_to_list(?MODULE), atom_to_list(Case)]), InDir = fun(Path) -> filename:join([Dir, Path]) end, ADep = fake_app(<<"rp_a">>, <<"1.0.0">>, InDir("_build/default/lib/rp_a/")), BDep = fake_app(<<"rp_b">>, <<"1.0.0">>, InDir("_build/default/lib/rp_b/")), CDep = fake_app(<<"rp_c">>, <<"1.0.0">>, InDir("_build/default/lib/rp_c/")), DDep = fake_app(<<"rp_d">>, <<"1.0.0">>, InDir("_build/default/lib/rp_d/")), RelxDep = fake_app(<<"relx">>, <<"1.0.0">>, InDir("_build/default/lib/relx/")), APlug = fake_app(<<"rp_a">>, <<"1.0.0">>, InDir("_build/default/plugins/lib/rp_a/")), RelxPlug = fake_app(<<"relx">>, <<"1.1.1">>, InDir("_build/default/plugins/lib/relx")), EPlug = fake_app(<<"rp_e">>, <<"1.0.0">>, InDir("_build/default/plugins/lib/rp_e/")), TopApp0 = fake_app(<<"top_app">>, <<"1.0.0">>, InDir("_build/default/lib/top_app/"), [<<"rp_a">>, <<"rp_b">>]), TopApp1 = rebar_app_info:applications(TopApp0, ['rp_a', 'rp_b']), S0 = rebar_state:new(), S1 = rebar_state:all_deps(S0, [ADep, BDep, CDep, DDep, RelxDep]), S2 = rebar_state:all_plugin_deps(S1, [APlug, RelxPlug]), S3 = rebar_state:project_apps(S2, [TopApp1]), S4 = rebar_state:code_paths(S3, default, code:get_path()), S5 = rebar_state:code_paths( S4, all_deps, [rebar_app_info:ebin_dir(A) || A <- [ADep, BDep, CDep, DDep, RelxDep]] ), S6 = rebar_state:code_paths( S5, all_plugin_deps, [rebar_app_info:ebin_dir(A) || A <- [APlug, RelxPlug, EPlug]] ), [{base_paths, BasePaths}, {root_dir, Dir}, {state, S6} | Config]. end_per_testcase(_, Config) -> %% this is deeply annoying because we interfere with rebar3's own %% path handling! rebar_paths:unset_paths([plugins, deps], ?config(state, Config)), Config. fake_app(Name, Vsn, OutDir) -> {ok, App} = rebar_app_info:new(Name, Vsn, OutDir), compile_fake_appmod(App, []), App. fake_app(Name, Vsn, OutDir, Apps) -> {ok, App} = rebar_app_info:new(Name, Vsn, OutDir), compile_fake_appmod(App, Apps), App. compile_fake_appmod(App, Apps) -> OutDir = rebar_app_info:ebin_dir(App), Vsn = rebar_app_info:original_vsn(App), Name = rebar_app_info:name(App), AppsStr = apps_to_str(Apps), ok = filelib:ensure_dir(filename:join([OutDir, ".touch"])), AppFile = [ "{application,", Name, ", " " [{description, \"some app\"}, " " {vsn, \"", Vsn, "\"}, " " {modules, [",Name,"]}, " " {registered, []}, " " {applications, [" ++ AppsStr ++ "]} " " ]}. "], ok = file:write_file(filename:join([OutDir, <>]), AppFile), Mod = [{attribute, 1, module, binary_to_atom(Name, utf8)}, {attribute, 2, export, [{f,0}]}, {function,3,f,0, [{clause,3, [], [], [{string,3,OutDir}] }]} ], {ok, _, Bin} = compile:forms(Mod), ok = file:write_file(filename:join([OutDir, <>]), Bin). %%%%%%%%%%%%% %%% TESTS %%% %%%%%%%%%%%%% clashing_apps(Config) -> Clashes = rebar_paths:clashing_apps([deps, plugins], ?config(state, Config)), ct:pal("Clashes: ~p", [Clashes]), ?assertEqual([<<"relx">>, <<"rp_a">>], lists:sort(proplists:get_value(deps, Clashes))), ?assertEqual([], proplists:get_value(plugins, Clashes)), ok. set_paths(Config) -> State = ?config(state, Config), RootDir = filename:split(?config(root_dir, Config)), %% Take a snapshot of runtime deps being set; to see if your test is valid, this should fail %% when you set the [deps] paths here rebar_paths:set_paths([runtime], State), RuntimePaths = code:get_path(), %% Revert back to regular dep paths rebar_paths:set_paths([plugins, deps], State), PluginPaths = code:get_path(), rebar_paths:set_paths([deps, plugins], State), DepPaths = code:get_path(), %% Plugin related paths checks ?assertEqual( RootDir ++ ["_build", "default", "plugins", "lib", "rp_a", "ebin"], find_first_instance(RootDir, "rp_a", PluginPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_b", "ebin"], find_first_instance(RootDir, "rp_b", PluginPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_c", "ebin"], find_first_instance(RootDir, "rp_c", PluginPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_d", "ebin"], find_first_instance(RootDir, "rp_d", PluginPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "plugins", "lib", "rp_e", "ebin"], find_first_instance(RootDir, "rp_e", PluginPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "plugins", "lib", "relx", "ebin"], find_first_instance(RootDir, "relx", PluginPaths) ), %% Dependency related paths checks ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_a", "ebin"], find_first_instance(RootDir, "rp_a", DepPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_b", "ebin"], find_first_instance(RootDir, "rp_b", DepPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_c", "ebin"], find_first_instance(RootDir, "rp_c", DepPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_d", "ebin"], find_first_instance(RootDir, "rp_d", DepPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "plugins", "lib", "rp_e", "ebin"], find_first_instance(RootDir, "rp_e", DepPaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "relx", "ebin"], find_first_instance(RootDir, "relx", DepPaths) ), %% Runtime related paths checks ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_a", "ebin"], find_first_instance(RootDir, "rp_a", RuntimePaths) ), ?assertEqual( RootDir ++ ["_build", "default", "lib", "rp_b", "ebin"], find_first_instance(RootDir, "rp_b", RuntimePaths) ), ?assertMatch( {not_found, _}, find_first_instance(RootDir, "rp_c", RuntimePaths) ), ?assertMatch( {not_found, _}, find_first_instance(RootDir, "rp_d", RuntimePaths) ), ?assertMatch( {not_found, _}, find_first_instance(RootDir, "rp_e", RuntimePaths) ), ?assertMatch( {not_found, _}, find_first_instance(RootDir, "relx", RuntimePaths) ), ok. check_modules(Config) -> State = ?config(state, Config), RootDir = ?config(root_dir, Config)++"/", rebar_paths:set_paths([plugins, deps], State), ct:pal("code:get_path() -> ~p", [code:get_path()]), ?assertEqual(RootDir ++ "_build/default/plugins/lib/rp_a/ebin", rp_a:f()), ct:pal("~p", [catch file:list_dir(RootDir ++ "_build/default/lib/")]), ct:pal("~p", [catch file:list_dir(RootDir ++ "_build/default/lib/rp_b/")]), ct:pal("~p", [catch file:list_dir(RootDir ++ "_build/default/lib/rp_b/ebin")]), ct:pal("~p", [catch b:module_info()]), ?assertEqual(RootDir ++ "_build/default/lib/rp_b/ebin", rp_b:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_c/ebin", rp_c:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_d/ebin", rp_d:f()), ?assertEqual(RootDir ++ "_build/default/plugins/lib/rp_e/ebin", rp_e:f()), ?assertEqual(RootDir ++ "_build/default/plugins/lib/relx/ebin", relx:f()), ?assertEqual(3, length(relx:module_info(exports))), % can't replace bundled rebar_paths:set_paths([deps, plugins], State), ct:pal("code:get_path() -> ~p", [code:get_path()]), ?assertEqual(RootDir ++ "_build/default/lib/rp_a/ebin", rp_a:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_b/ebin", rp_b:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_c/ebin", rp_c:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_d/ebin", rp_d:f()), ?assertEqual(RootDir ++ "_build/default/plugins/lib/rp_e/ebin", rp_e:f()), ?assertEqual(RootDir ++ "_build/default/lib/relx/ebin", relx:f()), ?assertEqual(3, length(relx:module_info(exports))), % can't replace bundled %% once again rebar_paths:set_paths([plugins, deps], State), ct:pal("code:get_path() -> ~p", [code:get_path()]), ?assertEqual(RootDir ++ "_build/default/plugins/lib/rp_a/ebin", rp_a:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_b/ebin", rp_b:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_c/ebin", rp_c:f()), ?assertEqual(RootDir ++ "_build/default/lib/rp_d/ebin", rp_d:f()), ?assertEqual(RootDir ++ "_build/default/plugins/lib/rp_e/ebin", rp_e:f()), ?assertEqual(RootDir ++ "_build/default/plugins/lib/relx/ebin", relx:f()), ?assertEqual(3, length(relx:module_info(exports))), % can't replace bundled ok. misloaded_mods(_Config) -> Res = rebar_paths:misloaded_modules( ["/1/2/3/4", "/1/2/4", "/2/1/1", "/3/4/5"], [{a, "/0/1/2/file.beam"}, {b, "/1/2/3/4/file.beam"}, {c, "/2/1/file.beam"}, {f, preloaded}, {d, "/3/5/7/file.beam"}, {e, "/3/4/5/file.beam"}] ), ?assertEqual([a,c,d], Res), ok. %%%%%%%%%%%%%%% %%% HELPERS %%% %%%%%%%%%%%%%%% find_first_instance(_RootDir, Frag, []) -> {not_found, Frag}; find_first_instance(RootDir, Frag, [Path|Rest]) -> Frags = filename:split(Path), case lists:member(Frag, Frags) of true -> %% When testing the runtime deps the paths would have %% apps such as `relx' that were not from within the root dir. case re:run(Frags, RootDir) of nomatch -> find_first_instance(RootDir, Frag, Rest); {match, _} -> Frags end; false -> find_first_instance(RootDir, Frag, Rest) end. apps_to_str([]) -> "stdlib, kernel"; apps_to_str(Apps) -> AppsStr = unicode:characters_to_list(lists:join(", ", Apps)), "stdlib, kernel, " ++ AppsStr.rebar3-3.18.0/test/rebar_pkg_SUITE.erl0000644000232200023220000003720414164317745017741 0ustar debalancedebalance%% Test suite for the rebar pkg index caching and decompression %% mechanisms. -module(rebar_pkg_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include("rebar.hrl"). -define(bad_etag, <<"abcdef">>). -define(good_etag, <<"22e1d7387c9085a462340088a2a8ba67">>). -define(badpkg_checksum, <<"A14E3718B33F8124E98004433193509EC6660F6CA03302657CAB8785751D77A0">>). -define(badindex_checksum, <<"7B2CBED315C89F3126B5BF553DD7FF0FB5FE94B064888DD1B095CE8BF4B6A16A">>). -define(bad_checksum, <<"D576B442A68C7B92BACDE1EFE9C6E54D8D6C74BDB71D8175B9D3C6EC8C7B62A7">>). -define(good_checksum, <<"ABA3B638A653A2414BF9DFAF76D90C937C53D1BE5B5D51A990C6FCC3A775C6F">>). -define(BADPKG_ETAG, <<"BADETAG">>). all() -> [good_uncached, good_cached, badpkg, badhash_nocache, badindexchk, badhash_cache, bad_to_good, good_disconnect, bad_disconnect, pkgs_provider, find_highest_matching]. init_per_suite(Config) -> application:start(meck), Config. end_per_suite(_Config) -> application:stop(meck). init_per_testcase(pkgs_provider=Name, Config) -> %% Need to mock out a registry for this test now because it will try to update it automatically Priv = ?config(priv_dir, Config), Tid = ets:new(registry_table, [public]), ets:insert_new(Tid, []), CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]), CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]), filelib:ensure_dir(filename:join([CacheDir, "registry"])), ok = ets:tab2file(Tid, filename:join([CacheDir, "registry"])), Config; init_per_testcase(good_uncached=Name, Config0) -> Config = [{good_cache, false}, {pkg, {<<"goodpkg">>, <<"1.0.0">>}} | Config0], mock_config(Name, Config); init_per_testcase(good_cached=Name, Config0) -> Pkg = {<<"goodpkg">>, <<"1.0.0">>}, Config1 = [{good_cache, true}, {pkg, Pkg} | Config0], Config = mock_config(Name, Config1), copy_to_cache(Pkg, Config), Config; init_per_testcase(badindexchk=Name, Config0) -> Config = [{good_cache, false}, {pkg, {<<"badindexchk">>, <<"1.0.0">>}} | Config0], mock_config(Name, Config); init_per_testcase(badpkg=Name, Config0) -> Config = [{good_cache, false}, {pkg, {<<"badpkg">>, <<"1.0.0">>}} | Config0], mock_config(Name, Config); init_per_testcase(badhash_nocache=Name, Config0) -> Config = [{good_cache, false}, {pkg, {<<"goodpkg">>, <<"1.0.0">>}} | Config0], mock_config(Name, Config); init_per_testcase(badhash_cache=Name, Config0) -> Pkg = {<<"goodpkg">>, <<"1.0.0">>}, Config1 = [{good_cache, true}, {pkg, Pkg} | Config0], Config = mock_config(Name, Config1), copy_to_cache(Pkg, Config), Config; init_per_testcase(bad_to_good=Name, Config0) -> Config1 = [{good_cache, false}, {pkg, {<<"goodpkg">>, <<"1.0.0">>}} | Config0], Config = mock_config(Name, Config1), Source = filename:join(?config(data_dir, Config), <<"badpkg-1.0.0.tar">>), Dest = filename:join(?config(cache_dir, Config), <<"goodpkg-1.0.0.tar">>), ec_file:copy(Source, Dest), Config; init_per_testcase(good_disconnect=Name, Config0) -> Pkg = {<<"goodpkg">>, <<"1.0.0">>}, Config1 = [{good_cache, false}, {pkg, Pkg} | Config0], Config = mock_config(Name, Config1), copy_to_cache(Pkg, Config), %% meck:unload(httpc), meck:new(httpc, [passthrough, unsticky]), meck:expect(httpc, request, fun(_, _, _, _) -> {error, econnrefused} end), Config; init_per_testcase(bad_disconnect=Name, Config0) -> Pkg = {<<"goodpkg">>, <<"1.0.0">>}, Config1 = [{good_cache, false}, {pkg, Pkg} | Config0], Config = mock_config(Name, Config1), meck:expect(r3_hex_repo, get_tarball, fun(_, _, _) -> {error, econnrefused} end), Config; init_per_testcase(Name, Config0) -> Config = [{good_cache, false}, {pkg, {<<"goodpkg">>, <<"1.0.0">>}} | Config0], mock_config(Name, Config). end_per_testcase(_, Config) -> unmock_config(Config), Config. good_uncached(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), ?assertEqual(ok, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum, ?good_checksum, #{}}, State, #{}, true)), Cache = ?config(cache_dir, Config), ?assert(filelib:is_regular(filename:join(Cache, <>))). good_cached(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), Cache = ?config(cache_dir, Config), CachedFile = filename:join(Cache, <>), ?assert(filelib:is_regular(CachedFile)), {ok, Content} = file:read_file(CachedFile), ?assertEqual(ok, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum, ?good_checksum, #{}}, State, #{}, true)), {ok, Content} = file:read_file(CachedFile). badindexchk(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), ?assertMatch({error, {rebar_pkg_resource, {bad_registry_checksum, _, _, _, _}}}, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?bad_checksum, ?bad_checksum, #{}}, State, #{}, true)), %% The cached file is there for forensic purposes Cache = ?config(cache_dir, Config), ?assert(filelib:is_regular(filename:join(Cache, <>))). badpkg(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), Cache = ?config(cache_dir, Config), CachePath = filename:join(Cache, <>), ETagPath = filename:join(Cache, <>), rebar_pkg_resource:store_etag_in_cache(ETagPath, ?BADPKG_ETAG), ?assertMatch({error, {hex_tarball, {tarball, {inner_checksum_mismatch, _, _}}}}, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?badpkg_checksum, ?badpkg_checksum, #{}}, State, #{}, false)), %% The cached/etag files are there for forensic purposes ?assert(filelib:is_regular(ETagPath)), ?assert(filelib:is_regular(CachePath)). badhash_nocache(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), ?assertMatch({error, {rebar_pkg_resource, {bad_registry_checksum, _, _, _, _}}}, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?bad_checksum, ?bad_checksum, #{}}, State, #{}, true)), %% The cached file is there for forensic purposes Cache = ?config(cache_dir, Config), ?assert(filelib:is_regular(filename:join(Cache, <>))). badhash_cache(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), Cache = ?config(cache_dir, Config), State = ?config(state, Config), CachedFile = filename:join(Cache, <>), ?assert(filelib:is_regular(CachedFile)), {ok, Content} = file:read_file(CachedFile), ?assertMatch({error, {rebar_pkg_resource, {bad_registry_checksum, _, _, _, _}}}, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?bad_checksum, ?bad_checksum, #{}}, State, #{}, true)), %% The cached file is there still, unchanged. ?assert(filelib:is_regular(CachedFile)), ?assertEqual({ok, Content}, file:read_file(CachedFile)). bad_to_good(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), Cache = ?config(cache_dir, Config), CachedFile = filename:join(Cache, <>), ?assert(filelib:is_regular(CachedFile)), {ok, Contents} = file:read_file(CachedFile), ?assertEqual(ok, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum, ?good_checksum, #{}}, State, #{}, true)), %% Cache has refreshed ?assert({ok, Contents} =/= file:read_file(CachedFile)). good_disconnect(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), Cache = ?config(cache_dir, Config), CachedFile = filename:join(Cache, <>), ETagFile = filename:join(Cache, <>), ?assert(filelib:is_regular(CachedFile)), {ok, Content} = file:read_file(CachedFile), rebar_pkg_resource:store_etag_in_cache(ETagFile, ?BADPKG_ETAG), ?assertEqual(ok, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum, ?good_checksum, #{}}, State, #{}, true)), {ok, Content} = file:read_file(CachedFile). bad_disconnect(Config) -> Tmp = ?config(tmp_dir, Config), {Pkg,Vsn} = ?config(pkg, Config), State = ?config(state, Config), ?assertEqual({fetch_fail, Pkg, Vsn}, rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum, ?good_checksum, #{}}, State, #{}, true)). pkgs_provider(Config) -> Config1 = rebar_test_utils:init_rebar_state(Config), rebar_test_utils:run_and_check( Config1, [], ["pkgs", "relx"], {ok, []} ). find_highest_matching(_Config) -> State = rebar_state:new(), {ok, Vsn} = rebar_packages:find_highest_matching_( <<"goodpkg">>, ec_semver:parse(<<"1.0.0">>), #{name => <<"hexpm">>}, ?PACKAGE_TABLE, State), ?assertEqual({{1,0,1},{[],[]}}, Vsn), {ok, Vsn1} = rebar_packages:find_highest_matching( <<"goodpkg">>, ec_semver:parse(<<"1.0">>), #{name => <<"hexpm">>}, ?PACKAGE_TABLE, State), ?assertEqual({{1,1,1},{[],[]}}, Vsn1), {ok, Vsn2} = rebar_packages:find_highest_matching( <<"goodpkg">>, ec_semver:parse(<<"2.0">>), #{name => <<"hexpm">>}, ?PACKAGE_TABLE, State), ?assertEqual({{2,0,0},{[],[]}}, Vsn2), %% regression test. ~> constraints higher than the available packages would result %% in returning the first package version instead of 'none'. ?assertEqual(none, rebar_packages:find_highest_matching_(<<"goodpkg">>, ec_semver:parse(<<"5.0">>), #{name => <<"hexpm">>}, ?PACKAGE_TABLE, State)), {ok, Vsn3} = rebar_packages:find_highest_matching_(<<"goodpkg">>, ec_semver:parse(<<"3.0.0-rc.0">>), #{name => <<"hexpm">>}, ?PACKAGE_TABLE, State), ?assertEqual({{3,0,0},{[<<"rc">>,0],[]}}, Vsn3). %%%%%%%%%%%%%%% %%% Helpers %%% %%%%%%%%%%%%%%% mock_config(Name, Config) -> Priv = ?config(priv_dir, Config), CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]), TmpDir = filename:join([Priv, "tmp", atom_to_list(Name)]), Tid = ets:new(registry_table, [public]), AllDeps = [ {{<<"badindexchk">>,<<"1.0.0">>}, [[], ?bad_checksum, ?bad_checksum, [<<"rebar3">>]]}, {{<<"goodpkg">>,<<"1.0.0">>}, [[], ?good_checksum, ?good_checksum, [<<"rebar3">>]]}, {{<<"goodpkg">>,<<"1.0.1">>}, [[], ?good_checksum, ?good_checksum, [<<"rebar3">>]]}, {{<<"goodpkg">>,<<"1.1.1">>}, [[], ?good_checksum, ?good_checksum, [<<"rebar3">>]]}, {{<<"goodpkg">>,<<"2.0.0">>}, [[], ?good_checksum, ?good_checksum, [<<"rebar3">>]]}, {{<<"goodpkg">>,<<"3.0.0-rc.0">>}, [[], ?good_checksum, ?good_checksum, [<<"rebar3">>]]}, {{<<"badpkg">>,<<"1.0.0">>}, [[], ?badpkg_checksum, ?badpkg_checksum, [<<"rebar3">>]]} ], ets:insert_new(Tid, AllDeps), CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]), filelib:ensure_dir(filename:join([CacheDir, "registry"])), ok = ets:tab2file(Tid, filename:join([CacheDir, "registry"])), catch ets:delete(?PACKAGE_TABLE), rebar_packages:new_package_table(), lists:foreach(fun({{N, Vsn}, [Deps, InnerChecksum, OuterChecksum, _]}) -> case ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(N), Vsn, <<"hexpm">>}) of false -> ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(N), ec_semver:parse(Vsn), <<"hexpm">>}, dependencies=Deps, retired=false, inner_checksum=InnerChecksum, outer_checksum=OuterChecksum}); true -> ok end end, AllDeps), meck:new(r3_hex_repo, [passthrough]), meck:expect(r3_hex_repo, get_package, fun(_Config, PkgName) -> Matches = ets:match_object(Tid, {{PkgName,'_'}, '_'}), Releases = [#{outer_checksum => OuterChecksum, inner_checksum => InnerChecksum, version => Vsn, dependencies => Deps} || {{_, Vsn}, [Deps, InnerChecksum, OuterChecksum, _]} <- Matches], {ok, {200, #{}, Releases}} end), %% The state returns us a fake registry meck:new(rebar_state, [passthrough]), meck:expect(rebar_state, get, fun(_State, rebar_packages_cdn, _Default) -> "http://test.com/"; (_, _, Default) -> Default end), meck:expect(rebar_state, resources, fun(_State) -> DefaultConfig = r3_hex_core:default_config(), [rebar_resource_v2:new(pkg, rebar_pkg_resource, #{repos => [DefaultConfig#{name => <<"hexpm">>}], base_config => #{}})] end), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_cache_dir, fun(_) -> CacheRoot end), meck:expect(rebar_packages, registry_dir, fun(_) -> {ok, CacheDir} end), meck:expect(rebar_packages, package_dir, fun(_, _) -> {ok, CacheDir} end), meck:new(rebar_prv_update, [passthrough]), meck:expect(rebar_prv_update, do, fun(State) -> {ok, State} end), %% Cache fetches are mocked -- we assume the server and clients are %% correctly used. GoodCache = ?config(good_cache, Config), {Pkg,Vsn} = ?config(pkg, Config), PkgFile = <>, {ok, PkgContents} = file:read_file(filename:join(?config(data_dir, Config), PkgFile)), meck:expect(r3_hex_repo, get_tarball, fun(_, _, _) when GoodCache -> {ok, {304, #{<<"etag">> => ?good_etag}, <<>>}}; (_, _, _) -> {ok, {200, #{<<"etag">> => ?good_etag}, PkgContents}} end), [{cache_root, CacheRoot}, {cache_dir, CacheDir}, {tmp_dir, TmpDir}, {mock_table, Tid} | Config]. unmock_config(Config) -> meck:unload(), catch ets:delete(?config(mock_table, Config)). copy_to_cache({Pkg,Vsn}, Config) -> Name = <>, Source = filename:join(?config(data_dir, Config), Name), Dest = filename:join(?config(cache_dir, Config), Name), ec_file:copy(Source, Dest). rebar3-3.18.0/test/rebar_profiles_SUITE.erl0000644000232200023220000006244514164317745021010 0ustar debalancedebalance-module(rebar_profiles_SUITE). -export([init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, all/0, profile_new_key/1, profile_merge_keys/1, profile_merge_umbrella_keys/1, explicit_profile_deduplicate_deps/1, implicit_profile_deduplicate_deps/1, all_deps_code_paths/1, profile_merges/1, same_profile_deduplication/1, stack_deduplication/1, add_to_profile/1, add_to_existing_profile/1, profiles_remain_applied_with_config_present/1, deduplicated_paths/1, test_profile_applied_at_completion/1, test_profile_applied_before_compile/1, test_profile_applied_before_eunit/1, test_profile_applied_to_apps/1, test_profile_erl_opts_order_1/1, test_profile_erl_opts_order_2/1, test_profile_erl_opts_order_3/1, test_profile_erl_opts_order_4/1, test_profile_erl_opts_order_5/1, test_erl_opts_debug_info/1, test_profile_erl_opts_precedence/1, first_files_exception/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). all() -> [profile_new_key, profile_merge_keys, profile_merge_umbrella_keys, all_deps_code_paths, profile_merges, explicit_profile_deduplicate_deps, implicit_profile_deduplicate_deps, same_profile_deduplication, stack_deduplication, add_to_profile, add_to_existing_profile, profiles_remain_applied_with_config_present, deduplicated_paths, test_profile_applied_at_completion, test_profile_applied_before_compile, test_profile_applied_before_eunit, test_profile_applied_to_apps, test_profile_erl_opts_order_1, test_profile_erl_opts_order_2, test_profile_erl_opts_order_3, test_profile_erl_opts_order_4, test_profile_erl_opts_order_5, test_erl_opts_debug_info, test_profile_erl_opts_precedence, first_files_exception]. init_per_suite(Config) -> application:start(meck), Config. end_per_suite(_Config) -> application:stop(meck). init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config, "profiles_"). end_per_testcase(_, Config) -> meck:unload(), Config. profile_new_key(Config) -> AppDir = ?config(apps, Config), AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", []}]), {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("profile_new_key_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Deps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", []}])), ct:pal("Deps ~p", [Deps]), RebarConfig = [{profiles, [{ct, [{deps, Deps}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "ct", "compile"], {ok, [{app, Name} ,{dep, "a", "1.0.0"} ,{dep, "b", "1.0.0"}]}). profile_merge_keys(Config) -> AppDir = ?config(apps, Config), AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", []} ,{"b", "2.0.0", []}]), {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("profile_new_key_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Deps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "1.0.0", []}])), ProfileDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])), RebarConfig = [{deps, Deps}, {profiles, [{ct, [{deps, ProfileDeps}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "ct", "compile"], {ok, [{app, Name} ,{dep, "a", "1.0.0"} ,{dep, "b", "2.0.0"}]}). profile_merge_umbrella_keys(Config) -> AppDir = ?config(apps, Config), ct:pal("Path: ~s", [AppDir]), Name = rebar_test_utils:create_random_name("profile_merge_umbrella_keys"), Vsn = rebar_test_utils:create_random_vsn(), SubAppDir = filename:join([AppDir, "apps", Name]), RebarConfig = [{vals, [{a,1},{b,1}]}, {profiles, [{ct, [{vals, [{a,1},{b,2}]}]}]}], SubRebarConfig = [{vals, []}, {profiles, [{ct, [{vals, [{c,1}]}]}]}], rebar_test_utils:create_app(SubAppDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(SubAppDir, SubRebarConfig), {ok, RebarConfigRead} = file:consult(rebar_test_utils:create_config(AppDir, RebarConfig)), {ok, State} = rebar_test_utils:run_and_check( Config, RebarConfigRead, ["as", "ct", "compile"], return ), [ProjectApp] = rebar_state:project_apps(State), ?assertEqual(Name, binary_to_list(rebar_app_info:name(ProjectApp))), Opts = rebar_app_info:opts(ProjectApp), ?assertEqual([{a,1},{b,2},{b,1},{c,1}], dict:fetch(vals, Opts)), ok. explicit_profile_deduplicate_deps(Config) -> AppDir = ?config(apps, Config), AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"a", "2.0.0", []} ,{"b", "1.0.0", []} ,{"b", "2.0.0", []}]), {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("explicit_profile_deduplicate_deps_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), FooDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}, {"b", "2.0.0", []}])), BarDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])), RebarConfig = [{profiles, [{foo, [{deps, FooDeps}]}, {bar, [{deps, BarDeps}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "bar,foo,bar", "compile"], {ok, [{app, Name} ,{dep, "a", "1.0.0"} ,{dep, "b", "1.0.0"}]}). implicit_profile_deduplicate_deps(Config) -> AppDir = ?config(apps, Config), AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"a", "2.0.0", []} ,{"b", "1.0.0", []} ,{"b", "2.0.0", []}]), {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("implicit_profile_deduplicate_deps_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), TestDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}, {"b", "2.0.0", []}])), ProfileDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])), RebarConfig = [{profiles, [{test, [{deps, TestDeps}]}, {bar, [{deps, ProfileDeps}]}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "test,bar", "eunit"], {ok, [{app, Name} ,{dep, "a", "1.0.0"} ,{dep, "b", "1.0.0"}]}). all_deps_code_paths(Config) -> AppDir = ?config(apps, Config), AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []} ,{"b", "2.0.0", []}]), {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps), mock_git_resource:mock([{deps, SrcDeps}]), Name = rebar_test_utils:create_random_name("all_deps_code_paths"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), Deps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}])), ProfileDeps = rebar_test_utils:top_level_deps( rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])), RebarConfig = [{deps, Deps}, {profiles, [{all_deps_test, [{deps, ProfileDeps}]}]}], os:putenv("REBAR_PROFILE", "all_deps_test"), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name} ,{dep, "a", "1.0.0"} ,{dep, "b", "2.0.0"}]}), os:putenv("REBAR_PROFILE", ""), Paths = rebar_state:code_paths(State, all_deps), Path = lists:reverse(["_build", "all_deps_test", "lib", "b", "ebin"]), ?assert(lists:any(fun(X) -> Path =:= lists:sublist(lists:reverse(filename:split(X)), 5) end, Paths)). profile_merges(_Config) -> RebarConfig = [{test1, [{key1, 1, 2}, key2]}, {test2, "hello"}, {test3, [key3]}, {test4, "oldvalue"}, {test5, [{key5, true}]}, {test6, [{key6, false}]}, {profiles, [{profile1, [{test1, [{key3, 5}, key1]}]}, {profile2, [{test2, "goodbye"}, {test3, []}, {test4, []}, {test5, [{key5, false}]}, {test6, [{key6, true}]} ]}]}], State = rebar_state:new(RebarConfig), State1 = rebar_state:apply_profiles(State, [profile1, profile2]), %% Combine lists ?assertEqual(lists:sort([key1, key2, {key1, 1, 2}, {key3, 5}]), lists:sort(rebar_state:get(State1, test1))), %% Use new value for strings "goodbye" = rebar_state:get(State1, test2), %% Check that a newvalue of []/"" doesn't override non-string oldvalues [key3] = rebar_state:get(State1, test3), [] = rebar_state:get(State1, test4), [{key5, false}, {key5, true}] = rebar_state:get(State1, test5), [{key6, true}, {key6, false}] = rebar_state:get(State1, test6). same_profile_deduplication(_Config) -> RebarConfig = [{test1, [{key1, 1, 2}, key2]}, {test2, [foo]}, {test3, [key3]}, {profiles, [{profile1, [{test1, [{key3, 5}, {key2, "hello"}]}, {test2, [bar]}, {test3, []} ]}] }], State = rebar_state:new(RebarConfig), State1 = rebar_state:apply_profiles(State, [profile1, profile1, profile1]), ?assertEqual([default, profile1], rebar_state:current_profiles(State1)), Test1 = rebar_state:get(State1, test1), %% Combine lists ?assertEqual(lists:sort([key2, {key1, 1, 2}, {key3, 5}, {key2, "hello"}]), lists:sort(Test1)), %% Key2 from profile1 overrides key2 from default profile ?assertEqual("hello", proplists:get_value(key2, Test1)), %% Check that a newvalue of []/"" doesn't override non-string oldvalues ?assertEqual([key3], rebar_state:get(State1, test3)), ?assertEqual([bar, foo], rebar_state:get(State1, test2)). stack_deduplication(_Config) -> RebarConfig = [ {test_key, default}, {test_list, [ {foo, default} ]}, {profiles, [ {a, [ {test_key, a}, {test_list, [ {foo, a} ]} ]}, {b, [ {test_key, b}, {test_list, [ {foo, b} ]} ]}, {c, [ {test_key, c}, {test_list, [ {foo, c} ]} ]}, {d, [ {test_key, d}, {test_list, [ {foo, d} ]} ]}, {e, [ {test_key, e}, {test_list, [ {foo, e} ]} ]} ]} ], State = rebar_state:new(RebarConfig), State1 = rebar_state:apply_profiles(State, [a, b, c, d, e, a, e, b]), ?assertEqual(b, rebar_state:get(State1, test_key)), TestList = rebar_state:get(State1, test_list), ?assertEqual( [{foo, b}, {foo, e}, {foo, a}, {foo, d}, {foo, c}, {foo, default} ], TestList ), ?assertEqual(b, proplists:get_value(foo, TestList)). add_to_profile(_Config) -> RebarConfig = [{foo, true}, {bar, false}], State = rebar_state:new(RebarConfig), State1 = rebar_state:add_to_profile(State, test, [{foo, false}]), State2 = rebar_state:apply_profiles(State1, test), Opts = rebar_state:opts(State2), lists:map(fun(K) -> false = dict:fetch(K, Opts) end, [foo, bar]). add_to_existing_profile(_Config) -> RebarConfig = [{foo, true}, {bar, false}, {profiles, [ {test, [{foo, false}]} ]}], State = rebar_state:new(RebarConfig), State1 = rebar_state:add_to_profile(State, test, [{baz, false}]), State2 = rebar_state:apply_profiles(State1, test), Opts = rebar_state:opts(State2), lists:map(fun(K) -> false = dict:fetch(K, Opts) end, [foo, bar, baz]). profiles_remain_applied_with_config_present(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("profiles_remain_applied_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, []}, {profiles, [ {not_ok, [{erl_opts, [{d, not_ok}]}]} ]}], rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "not_ok", "compile"], {ok, [{app, Name}]}), Path = filename:join([AppDir, "_build", "not_ok", "lib", Name, "ebin"]), code:add_patha(Path), Mod = list_to_atom("not_a_real_src_" ++ Name), true = lists:member({d, not_ok}, proplists:get_value(options, Mod:module_info(compile), [])). deduplicated_paths(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("deduplicated_paths_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [], rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "a,b,c,d,e,a,e,b", "compile"], {ok, [{app, Name}]}), Path = filename:join([AppDir, "_build", "c+d+a+e+b", "lib", Name, "ebin"]), ?assert(filelib:is_dir(Path)). test_profile_applied_at_completion(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("test_profile_at_completion_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:create_config(AppDir, RebarConfig), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], return), [App] = rebar_state:project_apps(State), ErlOpts = rebar_app_info:get(App, erl_opts), true = lists:member({d, 'TEST'}, ErlOpts). test_profile_applied_before_compile(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("test_profile_before_compile_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:create_config(AppDir, RebarConfig), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}), code:add_paths(rebar_state:code_paths(State, all_deps)), S = list_to_atom("not_a_real_src_" ++ Name), true = lists:member({d, 'TEST'}, proplists:get_value(options, S:module_info(compile), [])). test_profile_applied_before_eunit(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("test_profile_before_eunit_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:create_config(AppDir, RebarConfig), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}), code:add_paths(rebar_state:code_paths(State, all_deps)), T = list_to_atom("not_a_real_src_" ++ Name ++ "_tests"), true = lists:member({d, 'TEST'}, proplists:get_value(options, T:module_info(compile), [])). test_profile_applied_to_apps(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("test_profile_applied_to_apps_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:create_config(AppDir, RebarConfig), {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], return), Apps = rebar_state:project_apps(State), lists:foreach(fun(App) -> Opts = rebar_app_info:opts(App), ErlOpts = dict:fetch(erl_opts, Opts), true = lists:member({d, 'TEST'}, ErlOpts) end, Apps). test_profile_erl_opts_order_1(Config) -> Opts = get_compiled_profile_erl_opts([default], Config), Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined), undefined = Opt. test_profile_erl_opts_order_2(Config) -> Opts = get_compiled_profile_erl_opts([strict], Config), Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined), warn_export_all = Opt. test_profile_erl_opts_order_3(Config) -> Opts = get_compiled_profile_erl_opts([loose], Config), Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined), nowarn_export_all = Opt. test_profile_erl_opts_order_4(Config) -> Opts = get_compiled_profile_erl_opts([strict, loose], Config), Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined), nowarn_export_all = Opt. test_profile_erl_opts_order_5(Config) -> Opts = get_compiled_profile_erl_opts([loose, strict], Config), Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined), warn_export_all = Opt. test_erl_opts_debug_info(_Config) -> ToOpts = fun(List) -> rebar_opts:erl_opts(dict:from_list([{erl_opts, List}])) end, ?assertEqual([debug_info,a,b,c], ToOpts([a,b,c])), ?assertEqual([{debug_info,{mod,123}},a,b,c,debug_info], ToOpts([{debug_info,{mod,123}},a,b,c,debug_info])), ?assertEqual([a,b,debug_info,c], ToOpts([no_debug_info,a,b,debug_info,c])), ?assertEqual([a,b,c], ToOpts([debug_info,a,b,no_debug_info,c])), ?assertEqual([a,b,c,debug_info], ToOpts([{debug_info_key, "12345"},a,b, no_debug_info,c,debug_info])), ?assertEqual([a,b,c], ToOpts([{debug_info,{mod,123}},{debug_info_key, "12345"}, a,no_debug_info,b,c,debug_info,no_debug_info])), ?assertEqual([a,b,c,{debug_info_key,"123"}], ToOpts([{debug_info_key, "12345"},a,b,no_debug_info,debug_info, c,{debug_info_key, "123"}])), ?assertEqual([{debug_info_key,"12345"},a,b,c,{debug_info,{mod,"123"}}], ToOpts([debug_info,{debug_info_key,"12345"},a, no_debug_info,b,c,{debug_info,{mod,"123"}}])), ok. test_profile_erl_opts_precedence(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("profile_new_key_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [no_debug_info]}, {profiles, [ {test, [{erl_opts, [debug_info, {d,'HI'}]}]}, {other, [{erl_opts, [debug_info, {d,'HI'}]}]} ]}], {ok, State1} = rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "test", "compile"], return ), {ok, State2} = rebar_test_utils:run_and_check( Config, RebarConfig, ["as", "other", "compile"], return ), {ok, State3} = rebar_test_utils:run_and_check( Config, RebarConfig, ["compile"], return ), Opts1 = rebar_state:opts(State1), Opts2 = rebar_state:opts(State2), Opts3 = rebar_state:opts(State3), ErlOpts1 = rebar_opts:erl_opts(Opts1), ErlOpts2 = rebar_opts:erl_opts(Opts2), ErlOpts3 = rebar_opts:erl_opts(Opts3), ?assertEqual([{d,'TEST'}, debug_info, {d,'HI'}], ErlOpts1), ?assertEqual([debug_info, {d,'HI'}], ErlOpts2), ?assertEqual([], ErlOpts3), ok. first_files_exception(_Config) -> RebarConfig = [{erl_first_files, ["c","a","b"]}, {mib_first_files, ["c","a","b"]}, {other, ["c","a","b"]}, {profiles, [{profile2, [{erl_first_files, ["a","e"]}, {mib_first_files, ["a","e"]}, {other, ["a","e"]} ]}]}], State = rebar_state:new(RebarConfig), State1 = rebar_state:apply_profiles(State, [profile2]), %% Combine lists ?assertEqual(["a","b","c","e"], rebar_state:get(State1, other)), %% there is no specific reason not to dedupe "a" here aside from "this is how it is" ?assertEqual(["c","a","b","a","e"], rebar_state:get(State1, erl_first_files)), ?assertEqual(["c","a","b","a","e"], rebar_state:get(State1, mib_first_files)), ok. get_compiled_profile_erl_opts(Profiles, Config) -> AppDir = ?config(apps, Config), PStrs = [atom_to_list(P) || P <- Profiles], Name = rebar_test_utils:create_random_name( lists:flatten(["erl_opts_order_" | [[S, $_] || S <- PStrs]])), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [ {erl_opts, [warnings_as_errors, {d, profile_default}]}, {profiles, [ {strict, [{erl_opts, [warn_export_all, {d, profile_strict}]}]}, {loose, [{erl_opts, [nowarn_export_all, {d, profile_loose}]}]} ]}], rebar_test_utils:create_config(AppDir, RebarConfig), Command = case Profiles of [] -> ["compile"]; [default] -> ["compile"]; _ -> ["as", rebar_string:join(PStrs, ","), "compile"] end, {ok, State} = rebar_test_utils:run_and_check( Config, RebarConfig, Command, {ok, [{app, Name}]}), code:add_paths(rebar_state:code_paths(State, all_deps)), Mod = list_to_atom(Name), proplists:get_value(options, Mod:module_info(compile), []). % macro definitions get special handling last_erl_opt([{d, Macro} = Opt | Opts], Targets, Last) -> case lists:any(erl_opt_macro_match_fun(Macro), Targets) of true -> last_erl_opt(Opts, Targets, Opt); _ -> last_erl_opt(Opts, Targets, Last) end; last_erl_opt([{d, Macro, _} = Opt | Opts], Targets, Last) -> case lists:any(erl_opt_macro_match_fun(Macro), Targets) of true -> last_erl_opt(Opts, Targets, Opt); _ -> last_erl_opt(Opts, Targets, Last) end; last_erl_opt([Opt | Opts], Targets, Last) -> case lists:member(Opt, Targets) of true -> last_erl_opt(Opts, Targets, Opt); _ -> last_erl_opt(Opts, Targets, Last) end; last_erl_opt([], _, Last) -> Last. erl_opt_macro_match_fun(Macro) -> fun({d, M}) -> M == Macro; ({d, M, _}) -> M == Macro; (_) -> false end. rebar3-3.18.0/test/rebar_compiler_epp_SUITE.erl0000644000232200023220000001763014164317745021637 0ustar debalancedebalance%%% @doc %%% Unit tests for epp-related compiler utils. %%% Make it easier to validate internal behaviour of compiler data and %%% handling of module parsing without having to actually set up %%% entire projects. %%% @end -module(rebar_compiler_epp_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile([export_all, nowarn_export_all]). all() -> [{group, module}]. groups() -> [{module, [], [ analyze, analyze_old_behaviour, analyze_old_behavior, analyze_empty, analyze_bad_mod, resolve_module ]} ]. init_per_group(module, Config) -> to_file(Config, {"direct.hrl", "-direct(val). "}), Config; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. init_per_testcase(_, Config) -> Config. end_per_testcase(_, Config) -> Config. %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% module analysis group %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%% analyze() -> [{docs, "Analyzing a module returns all the " "parseable dependencies for it in a map."}]. analyze(Config) -> ?assert(check_analyze( #{include => [ "eunit-[0-9.]+/include/eunit.hrl$", "stdlib-[0-9.]+/include/assert.hrl$", "/direct.hrl$" ], %% missing includes missing_include_file => [ "^false.hrl$" ], missing_include_lib => [ "^some_app/include/lib.hrl$" ], parse_transform => [ erl_id_trans, eunit_autoexport, % added by include file! missing_parse_trans1, missing_parse_trans2 ], behaviour => [gen_server, gen_statem], is_behaviour => true }, rebar_compiler_epp:deps( to_file(Config, fake_mod()), [{includes, []}, {macros, []}] ) )), ok. analyze_old_behaviour() -> [{docs, "Analyzing old-style behaviour annotation"}]. analyze_old_behaviour(Config) -> ?assert(check_analyze( #{include => [], missing_include_file => [], missing_include_lib => [], parse_transform => [], behaviour => [], is_behaviour => true }, rebar_compiler_epp:deps( to_file(Config, old_behaviour_mod()), [{includes, []}, {macros, []}] ) )), ok. analyze_old_behavior() -> [{docs, "Analyzing old-style behavior annotation"}]. analyze_old_behavior(Config) -> ?assert(check_analyze( #{include => [], missing_include_file => [], missing_include_lib => [], parse_transform => [], behaviour => [], is_behaviour => true }, rebar_compiler_epp:deps( to_file(Config, old_behavior_mod()), [{includes, []}, {macros, []}] ) )), ok. analyze_empty() -> [{docs, "Making sure empty files are properly handled as valid but null " "and let some other compiler phase handle this. We follow " "what EPP handles."}]. analyze_empty(Config) -> ?assert(check_analyze( #{include => [], missing_include_file => [], missing_include_lib => [], parse_transform => [], behaviour => [], is_behaviour => false }, rebar_compiler_epp:deps( to_file(Config, empty_mod()), [{includes, []}, {macros, []}] ) )), ok. analyze_bad_mod() -> [{docs, "Errors for bad modules that don't compile are skipped " "by EPP and so we defer that to a later phase of the " "compilation process"}]. analyze_bad_mod(Config) -> ?assert(check_analyze( #{include => [], missing_include_file => [], missing_include_lib => [], parse_transform => [], behaviour => [], is_behaviour => false }, rebar_compiler_epp:deps( to_file(Config, bad_mod()), [{includes, []}, {macros, []}] ) )), ok. resolve_module() -> [{doc, "given a module name and a bunch of paths, find " "the first path that matches the module"}]. resolve_module(Config) -> Path1 = to_file(Config, fake_mod()), Path2 = to_file(Config, old_behaviour_mod()), Path3 = to_file(Config, empty_mod()), ?assertEqual( {ok, Path2}, rebar_compiler_epp:resolve_module( old_behaviour, [Path1, Path2, Path3] ) ), ok. %%%%%%%%%%%%%%% %%% HELPERS %%% %%%%%%%%%%%%%%% %% check each field of `Map' and validate them against `CheckMap'. %% This allows to check each value in the map has a matching assertion. %% Then check each field of `CheckMap' against `Map' to find if %% any missing value exists. check_analyze(CheckMap, Map) -> ct:pal("check_analyze:~n~p~n~p", [CheckMap, Map]), maps:fold(fun(K,V,Acc) -> check(CheckMap, K, V) and Acc end, true, Map) andalso maps:fold( fun(K,_,Acc) -> check(CheckMap, K, maps:get(K, Map, make_ref())) and Acc end, true, Map ). check(Map, K, V) -> case maps:is_key(K, Map) of false -> false; true -> #{K := Val} = Map, compare_val(Val, V) end. %% two identical values always works compare_val(V, V) -> true; %% compare lists of strings; each string must be checked individually %% because they are assumed to be regexes. compare_val(V1, V2) when is_list(hd(V1)) -> match_regexes(V1, V2); compare_val(V1, _V2) when not is_integer(hd(V1)) -> %% failing list of some sort, but not a string false; %% strings as regexes compare_val(V1, V2) when is_list(V1) -> match_regex(V1, [V2]) =/= nomatch; %% anything else is not literally the same and is bad compare_val(_, _) -> false. match_regexes([], List) -> List == []; % no extra patterns, that would be weird match_regexes([H|T], List) -> case match_regex(H, List) of nomatch -> false; {ok, Entry} -> match_regexes(T, List -- [Entry]) end. match_regex(_Pattern, []) -> nomatch; match_regex(Pattern, [H|T]) -> case re:run(H, Pattern) of nomatch -> match_regex(Pattern, T); _ -> {ok, H} end. %% custom zip function that causes value failures (by using make_ref() %% that will never match in compare_val/2) rather than crashing because %% of lists of different lengths. zip([], []) -> []; zip([], [H|T]) -> [{make_ref(),H} | zip([], T)]; zip([H|T], []) -> [{H,make_ref()} | zip(T, [])]; zip([X|Xs], [Y|Ys]) -> [{X,Y} | zip(Xs, Ys)]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Module specifications %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% turn a module string to a file that will live in CT's scratch dir to_file(Config, {Name,Contents}) -> Path = filename:join([?config(priv_dir, Config), Name]), file:write_file(Path, Contents, [sync]), Path. %% base module with all the interesting includes and attributes %% we want to track fake_mod() -> {"somemod.erl", " -module(somemod). -export([f/1]). -include(\"direct.hrl\"). -include(\"direct.hrl\"). -include_lib(\"some_app/include/lib.hrl\"). -include_lib(\"eunit/include/eunit.hrl\"). -compile({parse_transform, {erl_id_trans, []}}). -compile({parse_transform, missing_parse_trans1}). -compile([{parse_transform, {missing_parse_trans2, []}}]). -behaviour(gen_server). -behavior(gen_statem). -callback f() -> ok. -ifdef(OPT). -include(\"true.hrl\"). -else. -include(\"false.hrl\"). -endif. f(X) -> X. "}. %% variations for attributes that can't be checked in the %% same base module old_behaviour_mod() -> {"old_behaviour.erl", " -module(old_behaviour). -export([f/1, behaviour_info/1]). f(X) -> X. behaviour_info(callbacks) -> [{f,1}]. "}. old_behavior_mod() -> {"old_behaviour.erl", " -module(old_behaviour). -export([f/1, behaviour_info/1]). f(X) -> X. behavior_info(callbacks) -> [{f,1}]. "}. empty_mod() -> {"empty.erl", ""}. bad_mod() -> {"badmod.erl", " -module(bad_mod). % wrong name! f(x) -> X+1. % bad vars f((x)cv) -> bad syntax. "}. rebar3-3.18.0/test/rebar_uri_SUITE.erl0000644000232200023220000000373514164317745017761 0ustar debalancedebalance-module(rebar_uri_SUITE). -export([all/0, parse/1, append_path/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). all() -> [parse, append_path]. parse(_Config) -> #{scheme := Scheme, host := Host, path := Path} = rebar_uri:parse("https://repo.hex.pm"), ?assertEqual("https", Scheme), ?assertEqual("repo.hex.pm", Host), ?assertEqual(Path, "/"), % Normalize on OTP-23 behaviour. #{scheme := Scheme2, host := Host2, port := Port2, path := Path2, query := Query2} = rebar_uri:parse("https://repo.hex.pm:443?foo=bar"), ?assertEqual("https", Scheme2), ?assertEqual("repo.hex.pm", Host2), ?assertEqual(443, Port2), ?assertEqual(Path2, "/"), % Normalize on old http_uri behaviour ?assertEqual("foo=bar", Query2), #{scheme := Scheme3, host := Host3, path := Path3, query := Query3} = rebar_uri:parse("https://repo.hex.pm/over/here?foo=bar"), ?assertEqual("https", Scheme3), ?assertEqual("repo.hex.pm", Host3), ?assertEqual("/over/here", Path3), ?assertEqual("foo=bar", Query3), %% override default port and get it parsed as such ?assertMatch(#{port := 1337}, rebar_uri:parse("https://repo.hex.pm/", [{scheme_defaults, [{https,1337}]}])), ok. append_path(_Config) -> %% Default port for the proto is omitted if not mentioned originally {ok, Val1} = rebar_uri:append_path("https://repo.hex.pm/", "/repos/org"), ?assertEqual("https://repo.hex.pm/repos/org", Val1), %% QS elements come after the path {ok, Val2} = rebar_uri:append_path("https://repo.hex.pm?foo=bar", "/repos/org"), ?assertEqual("https://repo.hex.pm/repos/org?foo=bar", Val2), %% If the port is explicitly mentioned, keep it. ?assertEqual({ok, "https://repo.hex.pm:443/repos/org?foo=bar"}, rebar_uri:append_path("https://repo.hex.pm:443?foo=bar", "/repos/org")). rebar3-3.18.0/test/rebar_cover_SUITE.erl0000644000232200023220000003132514164317745020274 0ustar debalancedebalance-module(rebar_cover_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, all/0, flag_coverdata_written/1, config_coverdata_written/1, config_coverdata_overridden_name_written/1, basic_extra_src_dirs/1, release_extra_src_dirs/1, root_extra_src_dirs/1, index_written/1, flag_verbose/1, config_verbose/1, excl_mods_and_apps/1, coverdata_is_reset_on_write/1, flag_min_coverage/1, config_min_coverage/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config, "cover_"). all() -> [flag_coverdata_written, config_coverdata_written, config_coverdata_overridden_name_written, basic_extra_src_dirs, release_extra_src_dirs, root_extra_src_dirs, index_written, flag_verbose, config_verbose, excl_mods_and_apps, coverdata_is_reset_on_write, flag_min_coverage, config_min_coverage]. flag_coverdata_written(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit", "--cover"], {ok, [{app, Name}]}), true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "eunit.coverdata"])). config_coverdata_written(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_enabled, true}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}), true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "eunit.coverdata"])). config_coverdata_overridden_name_written(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_enabled, true}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit", "--cover_export_name=test_name"], {ok, [{app, Name}]}), true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "test_name.coverdata"])). basic_extra_src_dirs(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_extra_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), ExtraSrc = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name]), ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "extra", io_lib:format("~ts_extra.erl", [Name])]), ExtraSrc), RebarConfig = [{erl_opts, [{d, some_define}]}, {extra_src_dirs, ["extra"]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit", "--cover"], {ok, [{app, Name}]}), Mod = list_to_atom(Name), {file, _} = cover:is_compiled(Mod), ExtraMod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))), false = cover:is_compiled(ExtraMod). release_extra_src_dirs(Config) -> AppDir = ?config(apps, Config), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]), ExtraOne = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name1]), ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name1, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "apps", Name1, "extra", io_lib:format("~ts_extra.erl", [Name1])]), ExtraOne), ExtraTwo = io_lib:format("-module(~ts_extra).\n-export([ok/0]).\nok() -> ok.\n", [Name2]), ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "apps", Name2, "extra", io_lib:format("~ts_extra.erl", [Name2])]), ExtraTwo), RebarConfig = [{erl_opts, [{d, some_define}]}, {extra_src_dirs, ["extra"]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit", "--cover"], {ok, [{app, Name1}, {app, Name2}]}), Mod1 = list_to_atom(Name1), {file, _} = cover:is_compiled(Mod1), Mod2 = list_to_atom(Name2), {file, _} = cover:is_compiled(Mod2), ExtraMod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))), false = cover:is_compiled(ExtraMod1), ExtraMod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))), false = cover:is_compiled(ExtraMod2). root_extra_src_dirs(Config) -> AppDir = ?config(apps, Config), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]), Extra = <<"-module(extra).\n-export([ok/0]).\nok() -> ok.\n">>, ok = filelib:ensure_dir(filename:join([AppDir, "extra", "dummy"])), ok = file:write_file(filename:join([AppDir, "extra", "extra.erl"]), Extra), RebarConfig = [{erl_opts, [{d, some_define}]}, {extra_src_dirs, ["extra"]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit", "--cover"], {ok, [{app, Name1}, {app, Name2}]}), Mod1 = list_to_atom(Name1), {file, _} = cover:is_compiled(Mod1), Mod2 = list_to_atom(Name2), {file, _} = cover:is_compiled(Mod2), false = cover:is_compiled(extra). index_written(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["do", "eunit", "--cover", ",", "cover"], {ok, [{app, Name}]}), true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "index.html"])). flag_verbose(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["do", "eunit", "--cover", ",", "cover", "--verbose"], {ok, [{app, Name}]}), true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "index.html"])). config_verbose(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_opts, [verbose]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["do", "eunit", "--cover", ",", "cover"], {ok, [{app, Name}]}), true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "index.html"])). excl_mods_and_apps(Config) -> AppDir = ?config(apps, Config), Name1 = rebar_test_utils:create_random_name("relapp1_"), Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name1]), Name1, Vsn1, [kernel, stdlib]), Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name2]), Name2, Vsn2, [kernel, stdlib]), Name3 = rebar_test_utils:create_random_name("excludeme_"), Vsn3 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir, "apps", Name3]), Name3, Vsn3, [kernel, stdlib]), Mod1 = list_to_atom(Name1), Mod2 = list_to_atom(Name2), Mod3 = list_to_atom(Name3), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_excl_mods, [Mod2]}, {cover_excl_apps, [Name3]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit", "--cover"], {ok, [{app, Name1}, {app, Name2}, {app, Name3}]}), {file, _} = cover:is_compiled(Mod1), false = cover:is_compiled(Mod2), false = cover:is_compiled(Mod3). coverdata_is_reset_on_write(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("coverdata_is_reset_on_write_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_enabled, true}], rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}), Res = lists:map(fun(M) -> cover:analyse(M) end, cover:modules()), Ok = lists:foldl(fun({ok, R}, Acc) -> R ++ Acc end, [], Res), [] = lists:filter(fun({_, {0,_}}) -> false; (_) -> true end, Ok). flag_min_coverage(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("min_cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], ?assertMatch({ok, _}, rebar_test_utils:run_and_check( Config, RebarConfig, ["do", "eunit", "--cover", ",", "cover", "--min_coverage=5"], return)), ?assertMatch({error,{rebar_prv_cover,{min_coverage_failed,{65,_}}}}, rebar_test_utils:run_and_check( Config, RebarConfig, ["do", "eunit", "--cover", ",", "cover", "--min_coverage=65"], return)), ok. config_min_coverage(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig1 = [{erl_opts, [{d, some_define}]}, {cover_opts, [{min_coverage,5}]}], ?assertMatch({ok, _}, rebar_test_utils:run_and_check( Config, RebarConfig1, ["do", "eunit", "--cover", ",", "cover"], return)), RebarConfig2 = [{erl_opts, [{d, some_define}]}, {cover_opts, [{min_coverage,65}]}], ?assertMatch({error,{rebar_prv_cover,{min_coverage_failed,{65,_}}}}, rebar_test_utils:run_and_check( Config, RebarConfig2, ["do", "eunit", "--cover", ",", "cover"], return)), ok. rebar3-3.18.0/README.md0000644000232200023220000002430114164317745014622 0ustar debalancedebalance# Rebar3 [![Build Status](https://github.com/erlang/rebar3/workflows/Common%20Test/badge.svg)](https://github.com/erlang/rebar3/actions?query=branch%3Amaster+workflow%3A"Common+Test") [![Erlang Versions](https://img.shields.io/badge/Supported%20Erlang%2FOTP-22.0%20to%2024.0-blue)](http://www.erlang.org) 1. [What is Rebar3?](#what-is-rebar3) 2. [Why Rebar3?](#why-rebar3) 3. [Should I Use Rebar3?](#should-i-use-rebar3) 4. [Getting Started](#getting-started) 5. [Documentation](#documentation) 6. [Features](#features) 7. [Migrating from rebar2](#migrating-from-rebar2) 8. [Additional Resources](#additional-resources) ## What is Rebar3 Rebar3 is an Erlang tool that makes it easy to create, develop, and release Erlang libraries, applications, and systems in a repeatable manner. Rebar3 will: - respect and enforce standard Erlang/OTP conventions for project structure so they are easily reusable by the community; - manage source dependencies and Erlang [packages](https://hex.pm) while ensuring repeatable builds; - handle build artifacts, paths, and libraries such that standard development tools can be used without a headache; - adapt to projects of all sizes on almost any platform; - treat [documentation](https://rebar3.org/docs/) as a feature, and errors or lack of documentation as a bug. Rebar3 is also a self-contained Erlang script. It is easy to distribute or embed directly in a project. Tasks or behaviours can be modified or expanded with a [plugin system](https://rebar3.org/docs/configuration/plugins) [flexible enough](https://github.com/lfe-rebar3/rebar3_lfe) that even other languages on the Erlang VM will use it as a build tool. ## Why Rebar3 Rebar3 is the spiritual successor to [rebar 2.x](https://github.com/rebar/rebar), which was the first usable build tool for Erlang that ended up seeing widespread community adoption. It however had several shortcomings that made it difficult to use with larger projects or with teams with users new to Erlang. Rebar3 was our attempt at improving over the legacy of Rebar 2.x, providing the features we felt it was missing, and to provide a better environment in which newcomers joining our teams could develop. ## Should I use Rebar3? If your main language for your system is Erlang, that you value repeatable builds and want your various tools to integrate together, we do believe Rebar3 is the best experience you can get. ## Getting Started A [getting started guide is maintained on the official documentation website](https://rebar3.org/docs/getting-started), but installing rebar3 can be done by any of the ways described below Latest stable compiled version: ```bash $ wget https://s3.amazonaws.com/rebar3/rebar3 && chmod +x rebar3 ``` From Source (assuming you have a full Erlang install): ```bash $ git clone https://github.com/erlang/rebar3.git $ cd rebar3 $ ./bootstrap ``` Stable versions can also be obtained from the [releases page](https://github.com/erlang/rebar3/releases). The rebar3 escript can also extract itself with a run script under the user's home directory: ```bash $ ./rebar3 local install ===> Extracting rebar3 libs to ~/.cache/rebar3/lib... ===> Writing rebar3 run script ~/.cache/rebar3/bin/rebar3... ===> Add to $PATH for use: export PATH=~/.cache/rebar3/bin:$PATH ``` To keep it up to date after you've installed rebar3 this way you can use `rebar3 local upgrade` which fetches the latest stable release and extracts to the same place as above. A [nightly version can also be obtained](https://s3.amazonaws.com/rebar3-nightly/rebar3) if desired. Rebar3 may also be available on various OS-specific package managers such as FreeBSD Ports. Those are maintained by the community and Rebar3 maintainers themselves are generally not involved in that process. If you do not have a full Erlang install, we recommend using [erln8](https://erln8.github.io/erln8/) or [kerl](https://github.com/yrashk/kerl). For binary packages, use those provided by [Erlang Solutions](https://www.erlang-solutions.com/resources/download.html), but be sure to choose the "Standard" download option or you'll have issues building projects. Do note that if you are planning to work with multiple Erlang versions on the same machine, you will want to build Rebar3 with the oldest one of them. The 3 newest major Erlang releases are supported at any given time: if the newest version is OTP-24, building with versions as old as OTP-22 will be supported, and produce an executable that will work with those that follow. ## Documentation Rebar3 documentation is maintained on [https://rebar3.org/docs](https://rebar3.org/docs) ## Features Rebar3 supports the following features or tools by default, and may provide many others via the plugin ecosystem: | features | Description | |--------------------- |------------ | | Command composition | Rebar3 allows multiple commands to be run in sequence by calling `rebar3 do ,,...,`. | | Command dependencies | Rebar3 commands know their own dependencies. If a test run needs to fetch dependencies and build them, it will do so. | | Command namespaces | Allows multiple tools or commands to share the same name. | | Compiling | Build the project, including fetching all of its dependencies by calling `rebar3 compile` | | Clean up artifacts | Remove the compiled beam files from a project with `rebar3 clean` or just remove the `_build` directory to remove *all* compilation artifacts | | Code Coverage | Various commands can be instrumented to accumulate code coverage data (such as `eunit` or `ct`). Reports can be generated with `rebar3 cover` | | Common Test | The test framework can be run by calling `rebar3 ct` | | Dependencies | Rebar3 maintains local copies of dependencies on a per-project basis. They are fetched deterministically, can be locked, upgraded, fetched from source, packages, or from local directories. See [Dependencies on the documentation website](https://rebar3.org/docs/configuration/dependencies/). Call `rebar3 tree` to show the whole dependency tree. | | Documentation | Print help for rebar3 itself (`rebar3 help`) or for a specific task (`rebar3 help `). Full reference at [rebar3.org](https://rebar3.org/docs). | | Dialyzer | Run the Dialyzer analyzer on the project with `rebar3 dialyzer`. Base PLTs for each version of the language will be cached and reused for faster analysis | | Edoc | Generate documentation using edoc with `rebar3 edoc` | | Escript generation | Rebar3 can be used to generate [escripts](http://www.erlang.org/doc/man/escript.html) providing an easy way to run all your applications on a system where Erlang is installed | | Eunit | The test framework can be run by calling `rebar3 eunit` | | Locked dependencies | Dependencies are going to be automatically locked to ensure repeatable builds. Versions can be changed with `rebar3 upgrade` or `rebar3 upgrade `, or locks can be released altogether with `rebar3 unlock`. | | Packages | A given [Hex package](https://hex.pm) can be inspected `rebar3 pkgs `. This will output its description and available versions | | Path | While paths are managed automatically, you can print paths to the current build directories with `rebar3 path`. | | Plugins | Rebar3 can be fully extended with [plugins](https://rebar3.org/docs/configuration/plugins/). List or upgrade plugins by using the plugin namespace (`rebar3 plugins`). | | Profiles | Rebar3 can have subconfiguration options for different profiles, such as `test` or `prod`. These allow specific dependencies or compile options to be used in specific contexts. See [Profiles](https://rebar3.org/docs/configuration/profiles) in the docs. | | Releases | Rebar3 supports [building releases](https://rebar3.org/docs/deployment/releases) with the `relx` tool, providing a way to ship fully self-contained Erlang systems. Release update scripts for live code updates can also be generated. | | Shell | A full shell with your applications available can be started with `rebar3 shell`. From there, call tasks as `r3:do(compile)` to automatically recompile and reload the code without interruption | | Tarballs | Releases can be packaged into tarballs ready to be deployed. | | Templates | Configurable templates ship out of the box (try `rebar3 new` for a list or `rebar3 new help