1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
#!/usr/bin/perl -w
use strict;
use warnings;
use Test2::Bundle::Extended;
use Test2::Tools::Explain;
use Test2::Plugin::NoWarnings;
use Test::MockFile qw< nostrict >;
use Overload::FileCheck qw/:check/;
use Errno qw/ELOOP/;
use Cwd ();
# Assures testers don't mess up with our hard coded perms expectations.
umask 022;
note "_abs_path_to_file";
my $cwd = Cwd::getcwd();
is( Test::MockFile::_abs_path_to_file("0"), "$cwd/0", "no / prefix makes prepends path on it" );
is( Test::MockFile::_abs_path_to_file(), undef, "undef is undef" );
my @abs_path = (
[ '/lib' => '/lib' ],
[ '/lib/' => '/lib' ],
[ '/abc/.' => '/abc' ],
[ '/abc/./' => '/abc' ],
[ '/abc/./././.' => '/abc' ],
[ '/from/here/or-not/..' => '/from/here' ],
[ '/../../..' => '/' ],
[ '/one/two/three/four/../../..' => '/one' ],
[ '/a.b.c.d' => '/a.b.c.d' ],
);
foreach my $t (@abs_path) {
my ( $path, $normalized_path ) = @$t;
is( Test::MockFile::_abs_path_to_file($path), $normalized_path, "_abs_path_to_file( '$path' ) = '$normalized_path'" );
}
note "_fh_to_file";
my @mocked_files;
push @mocked_files, Test::MockFile->file( '/foo/bar', "" );
push @mocked_files, Test::MockFile->file( '/bar/foo', "" );
open( my $fh, "<", "/foo/bar" ) or die;
open( my $fh2, "<", "/bar/foo" ) or die;
is( Test::MockFile::_fh_to_file(), undef, "_fh_to_file()" );
is( Test::MockFile::_fh_to_file(0), undef, "_fh_to_file(0)" );
is( Test::MockFile::_fh_to_file(''), undef, "_fh_to_file('')" );
is( Test::MockFile::_fh_to_file(' '), undef, "_fh_to_file(' ')" );
is( Test::MockFile::_fh_to_file('/etc/passwd'), undef, "_fh_to_file('/etc/passwd')" );
is( Test::MockFile::_fh_to_file($fh), '/foo/bar', "_fh_to_file(\$fh)" );
is( Test::MockFile::_fh_to_file($fh2), '/bar/foo', "_fh_to_file(\$fh2)" );
close $fh;
close $fh2;
is( Test::MockFile::_fh_to_file($fh), undef, "_fh_to_file(\$fh) when closed." );
note "_find_file_or_fh";
push @mocked_files, Test::MockFile->symlink( '/foo/bar', '/abc' );
is( Test::MockFile::_find_file_or_fh('/abc'), '/abc', "_find_file_or_fh('/abc')" );
is( Test::MockFile::_find_file_or_fh( '/abc', 1 ), '/foo/bar', "_find_file_or_fh('/abc', 1) - follow" );
push @mocked_files, Test::MockFile->symlink( '/not/a/file', '/broken_link' );
is( Test::MockFile::_find_file_or_fh( '/broken_link', 1 ), Test::MockFile::BROKEN_SYMLINK(), "_find_file_or_fh('/broken_link', 1) is undef when /broken_link is mocked." );
push @mocked_files, Test::MockFile->symlink( '/aaa', '/bbb' );
push @mocked_files, Test::MockFile->symlink( '/bbb', '/aaa' );
is( Test::MockFile::_find_file_or_fh( '/aaa', 1 ), Test::MockFile::CIRCULAR_SYMLINK(), "_find_file_or_fh('/aaaa', 1) - with circular links" );
is( $! + 0, ELOOP, '$! is ELOOP' );
note "_mock_stat";
is( Test::MockFile::_mock_stat( 'lstat', "/lib" ), FALLBACK_TO_REAL_OP(), "An unmocked file will return FALLBACK_TO_REAL_OP() to tell XS to handle it" );
like( dies { Test::MockFile::_mock_stat() }, qr/^_mock_stat called without a stat type at /, "no args fails cause we should have gotten a stat type." );
like( dies { Test::MockFile::_mock_stat( 'notastat', '' ) }, qr/^Unexpected stat type 'notastat' at /, "An unknown stat type fails cause this should never happen." );
is( Test::MockFile::_mock_stat( 'lstat', "" ), FALLBACK_TO_REAL_OP(), "empty string passes to XS" );
is( Test::MockFile::_mock_stat( 'stat', ' ' ), FALLBACK_TO_REAL_OP(), "A space string passes to XS" );
my $basic_stat_return = array {
item 0;
item 0;
item 0100644;
item 0;
item match qr/^[0-9]+$/;
item match qr/^[0-9\s]+$/;
item 0;
item 0;
item match qr/^[0-9]{3,}$/;
item match qr/^[0-9]{3,}$/;
item match qr/^[0-9]{3,}$/;
item 4096;
item 1;
};
is( Test::MockFile::_mock_stat( 'lstat', '/foo/bar' ), $basic_stat_return, "/foo/bar mock stat" );
is( Test::MockFile::_mock_stat( 'stat', '/aaa' ), [], "/aaa mock stat when looped." );
is( $! + 0, ELOOP, "Throws an ELOOP error" );
push @mocked_files, Test::MockFile->file('/foo/baz'); # Missing file but mocked.
is( Test::MockFile::_mock_stat( 'lstat', '/foo/baz' ), [], "/foo/baz mock stat when missing." );
my $symlink_lstat_return = array {
item 0;
item 0;
item 0127777;
item 0;
item match qr/^[0-9]+$/;
item match qr/^[0-9\s]+$/;
item 0;
item 1;
item match qr/^[0-9]{3,}$/;
item match qr/^[0-9]{3,}$/;
item match qr/^[0-9]{3,}$/;
item 4096;
item 1;
};
is( Test::MockFile::_mock_stat( 'lstat', '/broken_link' ), $symlink_lstat_return, "lstat on /broken_link returns the stat on the symlink itself." );
is( Test::MockFile::_mock_stat( 'stat', '/broken_link' ), [], "stat on /broken_link is an empty array since what it points to doesn't exist." );
{
my $exe = q[/tmp/custom.exe];
my $tmp = Test::MockFile->file( $exe, " ", { mode => 0700 } );
ok -x $exe, "mocked file is executable";
my (
$dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks
) = stat($exe);
is $uid, $>, 'default uid is current UID';
note "GID $gid";
is $gid, int $), 'default fid is current GID';
}
{
# make sure directories with trailing slash are not ignored by stat by accident
my $dir = Test::MockFile->dir('/quux');
mkdir $dir->path();
ok( -d ( $dir->path() ), 'Directory /quux exists' );
ok( -d ( $dir->path() . '/' ), 'Directory /quux/ also exists' );
}
done_testing();
exit;
|