Add separate tests for .stowrc from $HOME and $PWD

.stowrc can be obtained from $HOME and/or the current working
directory; however only the $HOME case was tested before, because
during tests Stow was being run from $HOME.

So switch $TEST_DIR to an absolute path, create a new run_from/
subdirectory, and chdir to that before invoking any Stow code.  This
allows us to test the behaviour of .stowrc in $HOME and run_from/
separately.
This commit is contained in:
Adam Spiers 2019-06-28 09:56:46 +01:00
parent ac74d75a98
commit 74f0182834
4 changed files with 156 additions and 67 deletions

28
NEWS
View file

@ -98,12 +98,7 @@ News file for Stow.
consistency. consistency.
- INSTALL.md now also documents how to build directly from git. - INSTALL.md now also documents how to build directly from git.
** Fixes for bugs and technical debt ** Fixes for bugs, tests, and other technical debt
*** Fix for test suite on Cygwin
Thanks to Lucas Theisen for this fix!
*** aclocal.m4 was updated using aclocal 1.15.1.
*** Add Docker files for convenient testing across multiple Perl versions *** Add Docker files for convenient testing across multiple Perl versions
@ -118,17 +113,28 @@ News file for Stow.
Thanks to Charles LeDoux for this! Thanks to Charles LeDoux for this!
*** Add Coveralls integration with GitHub
This means that test coverage analysis will be automatically be run
on any pull requests submitted to GitHub.
*** Set up continuous testing via Travis CI *** Set up continuous testing via Travis CI
This means that the test suite will be automatically run on any This means that the test suite will be automatically run on any
pull requests submitted to GitHub, as well as "make distcheck" pull requests submitted to GitHub, as well as "make distcheck"
and "./Build distcheck". and "./Build distcheck".
*** Add Coveralls integration with GitHub
This means that test coverage analysis will be automatically be run
on any pull requests submitted to GitHub.
*** Miscellaneous improvements to the test suite
These include proper testing of the distinct impact of ~/.stowrc
and .stowrc in the directory from which Stow is invoked.
*** Fix for test suite on Cygwin
Thanks to Lucas Theisen for this fix!
*** aclocal.m4 was updated using aclocal 1.15.1.
*** Miscellaneous fixes to the build and distribution process *** Miscellaneous fixes to the build and distribution process
*** Improve handling of directories with unusual names *** Improve handling of directories with unusual names

View file

@ -515,14 +515,14 @@ sub main {
#============================================================================ #============================================================================
sub process_options { sub process_options {
# Get cli options. # Get cli options.
my ($cli_options, my ($cli_options,
$pkgs_to_unstow, $pkgs_to_unstow,
$pkgs_to_stow) = parse_options(@ARGV); $pkgs_to_stow) = parse_options(@ARGV);
# Get the .stowrc options. # Get the .stowrc options.
# Note that rc_pkgs_to_unstow and rc_pkgs_to_stow are ignored. # Note that rc_pkgs_to_unstow and rc_pkgs_to_stow are ignored.
my ($rc_options, my ($rc_options,
$rc_pkgs_to_unstow, $rc_pkgs_to_unstow,
$rc_pkgs_to_stow) = get_config_file_options(); $rc_pkgs_to_stow) = get_config_file_options();
# Merge .stowrc and command line options. # Merge .stowrc and command line options.
@ -547,8 +547,8 @@ sub process_options {
# Example: parse_options(@ARGV) # Example: parse_options(@ARGV)
# Returns : (\%options, \@pkgs_to_unstow, \@pkgs_to_stow) # Returns : (\%options, \@pkgs_to_unstow, \@pkgs_to_stow)
# Throws : a fatal error if a bad command line option is given # Throws : a fatal error if a bad command line option is given
# Comments : Used for parsing both command line options and rc file. Used # Comments : Used for parsing both command line options and rc file. Used
# for parsing only. Sanity checks and post-processing belong in # for parsing only. Sanity checks and post-processing belong in
# process_options(). # process_options().
#============================================================================ #============================================================================
sub parse_options { sub parse_options {
@ -614,6 +614,7 @@ sub parse_options {
return (\%options, \@pkgs_to_unstow, \@pkgs_to_stow); return (\%options, \@pkgs_to_unstow, \@pkgs_to_stow);
} }
sub sanitize_path_options { sub sanitize_path_options {
my ($options) = @_; my ($options) = @_;

View file

@ -22,67 +22,144 @@
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 23; use Test::More tests => 33;
use testutil; use testutil;
require 'stow'; require 'stow';
# stowrc file used for testing. # .stowrc files used for testing, relative to run_from/
my $RC_FILE = "$TEST_DIR/.stowrc"; my $CWD_RC_FILE = ".stowrc";
my $HOME_RC_FILE = "../.stowrc";
# Take the safe route and cowardly refuse to continue if there's # Take the safe route and cowardly refuse to continue if there's
# already a file at $RC_FILE. # already a file at $HOME_RC_FILE.
if (-e $RC_FILE) { if (-e $HOME_RC_FILE) {
die "RC file location $RC_FILE already exists!\n"; die "RC file location $HOME_RC_FILE already exists!\n";
} }
# Define the variable that will be used to write stowrc. my ($options, $pkgs_to_delete, $pkgs_to_stow);
my $rc_contents;
# Init testing directory structure and overwrite ENV{HOME} to prevent # Init testing directory structure and overwrite ENV{HOME} to prevent
# squashing existing stowrc file. # squashing existing .stowrc file.
init_test_dirs(); init_test_dirs();
# =========== RC Loading Tests =========== # =========== RC Loading Tests ===========
# Basic parsing and loading rc file tests. # Basic parsing and loading rc file tests.
# ======================================== # ========================================
my $orig_HOME = $ENV{HOME};
# #
# Test stowrc file with one options per line. # Test no .stowrc file anywhere
#
delete $ENV{HOME};
local @ARGV = ('dummy');
cd("$TEST_DIR/run_from");
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{target}, "$ABS_TEST_DIR", "default --target with no .stowrc");
is($options->{dir}, "$ABS_TEST_DIR/run_from", "default -d with no .stowrc");
#
# Test .stowrc file in cwd with relative paths, and $HOME not defined
#
make_file($CWD_RC_FILE, <<HERE);
-d ../stow
--target ../target
HERE
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{target}, "../target"
=> "relative --target from \$PWD/.stowrc");
is($options->{dir}, "../stow"
=> "relative -d from \$PWD/.stowrc");
$ENV{HOME} = $orig_HOME;
remove_file($CWD_RC_FILE);
#
# Test .stowrc file in cwd with absolute paths, and $HOME not defined
#
make_file($CWD_RC_FILE, <<HERE);
-d $ABS_TEST_DIR/stow
--target $ABS_TEST_DIR/target
HERE
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{target}, "$ABS_TEST_DIR/target"
=> "absolute --target from \$PWD/.stowrc");
is($options->{dir}, "$ABS_TEST_DIR/stow"
=> "abs_test_dir -d from \$PWD/.stowrc");
$ENV{HOME} = $orig_HOME;
remove_file($CWD_RC_FILE);
#
# Test ~/.stowrc file with one relative option per line.
# #
local @ARGV = ('dummy'); local @ARGV = ('dummy');
$rc_contents = <<HERE; make_file($HOME_RC_FILE, <<HERE);
-d $TEST_DIR/stow -d ../stow
--target $TEST_DIR/target --target ../target
HERE HERE
make_file($RC_FILE, $rc_contents);
my ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{target}, "$TEST_DIR/target", "rc options different lines"); is($options->{target}, "../target", "--target from \$HOME/.stowrc");
is($options->{dir}, "$TEST_DIR/stow", "rc options different lines"); is($options->{dir}, "../stow", "-d from \$HOME/.stowrc");
# #
# Test that scalar cli option overwrites conflicting stowrc option. # Test ~/.stowrc file with one absolute option per line.
# #
local @ARGV = ('-d', "$TEST_DIR/stow",'dummy'); local @ARGV = ('dummy');
$rc_contents = <<HERE; make_file($HOME_RC_FILE, <<HERE);
-d $ABS_TEST_DIR/stow
--target $ABS_TEST_DIR/target
HERE
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{target}, "$ABS_TEST_DIR/target"
=> "--target from \$HOME/.stowrc");
is($options->{dir}, "$ABS_TEST_DIR/stow"
=> "-d from \$HOME/.stowrc");
#
# Test ~/.stowrc file is overridden by .stowrc in cwd.
#
local @ARGV = ('dummy');
make_file($HOME_RC_FILE, <<HERE);
-d $ABS_TEST_DIR/stow-will-be-overridden
--target $ABS_TEST_DIR/target-will-be-overridden
HERE
make_file($CWD_RC_FILE, <<HERE);
-d $ABS_TEST_DIR/stow
--target $ABS_TEST_DIR/target
HERE
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{target}, "$ABS_TEST_DIR/target"
=> "--target overridden by \$PWD/.stowrc");
is($options->{dir}, "$ABS_TEST_DIR/stow"
=> "-d overridden \$PWD/.stowrc");
unlink($CWD_RC_FILE) or die "Failed to unlink $CWD_RC_FILE";
#
# Test that scalar cli option overwrites conflicting ~/.stowrc option.
#
local @ARGV = ('-d', "$ABS_TEST_DIR/stow", 'dummy');
make_file($HOME_RC_FILE, <<HERE);
-d bad/path -d bad/path
HERE HERE
make_file($RC_FILE, $rc_contents);
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is($options->{dir}, "$TEST_DIR/stow", "cli overwrite scalar rc option."); is($options->{dir}, "$ABS_TEST_DIR/stow", "cli overwrite scalar rc option.");
# #
# Test that list cli option merges with conflicting stowrc option. # Test that list cli option merges with conflicting .stowrc option.
# Documentation states that stowrc options are prepended to cli options. # Documentation states that .stowrc options are prepended to cli options.
# #
local @ARGV = ( local @ARGV = (
'--defer=man', '--defer=man',
'dummy' 'dummy'
); );
$rc_contents = <<HERE; make_file($HOME_RC_FILE, <<HERE);
--defer=info --defer=info
HERE HERE
make_file($RC_FILE, $rc_contents);
($options, $pkgs_to_delete, $pkgs_to_stow) = process_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = process_options();
is_deeply($options->{defer}, [qr(\Ainfo), qr(\Aman)], is_deeply($options->{defer}, [qr(\Ainfo), qr(\Aman)],
'defer man and info'); 'defer man and info');
@ -98,8 +175,8 @@ is_deeply($options->{defer}, [qr(\Ainfo), qr(\Aman)],
# Test environment variable expansion function. # Test environment variable expansion function.
# #
# Basic expansion # Basic expansion
is(expand_environment('$HOME/stow'), "$TEST_DIR/stow", 'expand $HOME'); is(expand_environment('$HOME/stow'), "$ABS_TEST_DIR/stow", 'expand $HOME');
is(expand_environment('${HOME}/stow'), "$TEST_DIR/stow", 'expand ${HOME}'); is(expand_environment('${HOME}/stow'), "$ABS_TEST_DIR/stow", 'expand ${HOME}');
delete $ENV{UNDEFINED}; # just in case delete $ENV{UNDEFINED}; # just in case
foreach my $var ('$UNDEFINED', '${UNDEFINED}') { foreach my $var ('$UNDEFINED', '${UNDEFINED}') {
@ -135,19 +212,18 @@ is(expand_tilde('\~/path'), '~/path', 'escaped tilde');
# #
# Test that environment variable expansion is applied. # Test that environment variable expansion is applied.
# #
$rc_contents = <<'HERE'; make_file($HOME_RC_FILE, <<'HERE');
--dir=$HOME/stow --dir=$HOME/stow
--target=$HOME/stow --target=$HOME/stow
--ignore=\$HOME --ignore=\$HOME
--defer=\$HOME --defer=\$HOME
--override=\$HOME --override=\$HOME
HERE HERE
make_file($RC_FILE, $rc_contents);
($options, $pkgs_to_delete, $pkgs_to_stow) = get_config_file_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = get_config_file_options();
is($options->{dir}, "$TEST_DIR/stow", is($options->{dir}, "$ABS_TEST_DIR/stow",
"apply environment expansion on stowrc --dir"); "apply environment expansion on \$HOME/.stowrc --dir");
is($options->{target}, "$TEST_DIR/stow", is($options->{target}, "$ABS_TEST_DIR/stow",
"apply environment expansion on stowrc --target"); "apply environment expansion on \$HOME/.stowrc --target");
is_deeply($options->{ignore}, [qr(\$HOME\z)], is_deeply($options->{ignore}, [qr(\$HOME\z)],
"environment expansion not applied on --ignore"); "environment expansion not applied on --ignore");
is_deeply($options->{defer}, [qr(\A\$HOME)], is_deeply($options->{defer}, [qr(\A\$HOME)],
@ -158,28 +234,28 @@ is_deeply($options->{override}, [qr(\A\$HOME)],
# #
# Test that tilde expansion is applied in correct places. # Test that tilde expansion is applied in correct places.
# #
$rc_contents = <<'HERE'; make_file($HOME_RC_FILE, <<'HERE');
--dir=~/stow --dir=~/stow
--target=~/stow --target=~/stow
--ignore=~/stow --ignore=~/stow
--defer=~/stow --defer=~/stow
--override=~/stow --override=~/stow
HERE HERE
make_file($RC_FILE, $rc_contents);
($options, $pkgs_to_delete, $pkgs_to_stow) = get_config_file_options(); ($options, $pkgs_to_delete, $pkgs_to_stow) = get_config_file_options();
is($options->{dir}, "$TEST_DIR/stow", is($options->{dir}, "$ABS_TEST_DIR/stow",
"apply environment expansion on stowrc --dir"); "apply tilde expansion on \$HOME/.stowrc --dir");
is($options->{target}, "$TEST_DIR/stow", is($options->{target}, "$ABS_TEST_DIR/stow",
"apply environment expansion on stowrc --target"); "apply tilde expansion on \$HOME/.stowrc --target");
is_deeply($options->{ignore}, [qr(~/stow\z)], is_deeply($options->{ignore}, [qr(~/stow\z)],
"environment expansion not applied on --ignore"); "tilde expansion not applied on --ignore");
is_deeply($options->{defer}, [qr(\A~/stow)], is_deeply($options->{defer}, [qr(\A~/stow)],
"environment expansion not applied on --defer"); "tilde expansion not applied on --defer");
is_deeply($options->{override}, [qr(\A~/stow)], is_deeply($options->{override}, [qr(\A~/stow)],
"environment expansion not applied on --override"); "tilde expansion not applied on --override");
#
# Clean up files used for testing. # Clean up files used for testing.
# #
unlink $RC_FILE or die "Unable to clean up $RC_FILE.\n"; unlink $HOME_RC_FILE or die "Unable to clean up $HOME_RC_FILE.\n";
remove_dir($TEST_DIR); remove_dir($ABS_TEST_DIR);

View file

@ -36,19 +36,21 @@ use Stow::Util qw(parent canon_path);
use base qw(Exporter); use base qw(Exporter);
our @EXPORT = qw( our @EXPORT = qw(
$ABS_TEST_DIR
$TEST_DIR $TEST_DIR
$stderr $stderr
init_test_dirs init_test_dirs
cd cd
new_Stow new_compat_Stow new_Stow new_compat_Stow
make_path make_link make_invalid_link make_file make_path make_link make_invalid_link make_file
remove_dir remove_link remove_dir remove_file remove_link
cat_file cat_file
is_link is_dir_not_symlink is_nonexistent_path is_link is_dir_not_symlink is_nonexistent_path
capture_stderr uncapture_stderr capture_stderr uncapture_stderr
); );
our $TEST_DIR = 'tmp-testing-trees'; our $TEST_DIR = 'tmp-testing-trees';
our $ABS_TEST_DIR = File::Spec->rel2abs('tmp-testing-trees');
our $stderr; our $stderr;
my $tied_err; my $tied_err;
@ -64,13 +66,17 @@ sub uncapture_stderr {
} }
sub init_test_dirs { sub init_test_dirs {
for my $dir ("$TEST_DIR/target", "$TEST_DIR/stow") { # Create a run_from/ subdirectory for tests which want to run
-d $dir and remove_tree($dir); # from a separate directory outside the Stow directory or
make_path($dir); # target directory.
for my $dir ("target", "stow", "run_from") {
my $path = "$TEST_DIR/$dir";
-d $path and remove_tree($path);
make_path($path);
} }
# Don't let user's ~/.stow-global-ignore affect test results # Don't let user's ~/.stow-global-ignore affect test results
$ENV{HOME} = $TEST_DIR; $ENV{HOME} = $ABS_TEST_DIR;
} }
sub new_Stow { sub new_Stow {