2023-06-26 16:45:39 +03:00
#!/usr/bin/env bash
2015-10-29 23:24:30 +03:00
#
# Blackbox test for shadow_copy2 VFS.
#
if [ $# -lt 7 ] ; then
cat <<EOF
2016-08-16 07:19:04 +03:00
Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT PARAMS
2015-10-29 23:24:30 +03:00
EOF
exit 1;
fi
SERVER = ${ 1 }
SERVER_IP = ${ 2 }
DOMAIN = ${ 3 }
USERNAME = ${ 4 }
PASSWORD = ${ 5 }
WORKDIR = ${ 6 }
SMBCLIENT = ${ 7 }
shift 7
ADDARGS = " $* "
2016-08-16 07:19:04 +03:00
SMBCLIENT = " $VALGRIND ${ SMBCLIENT } ${ ADDARGS } "
2015-10-29 23:24:30 +03:00
incdir = ` dirname $0 ` /../../../testprogs/blackbox
. $incdir /subunit.sh
SNAPSHOTS[ 0] = '@GMT-2015.10.31-19.40.30'
SNAPSHOTS[ 1] = '@GMT-2016.10.31-19.40.30'
SNAPSHOTS[ 2] = '@GMT-2017.10.31-19.40.30'
SNAPSHOTS[ 3] = '@GMT-2018.10.31-19.40.30'
SNAPSHOTS[ 4] = '@GMT-2019.10.31-19.40.30'
SNAPSHOTS[ 5] = '@GMT-2020.10.31-19.40.30'
SNAPSHOTS[ 6] = '@GMT-2021.10.31-19.40.30'
SNAPSHOTS[ 7] = '@GMT-2022.10.31-19.40.30'
SNAPSHOTS[ 8] = '@GMT-2023.10.31-19.40.30'
SNAPSHOTS[ 9] = '@GMT-2024.10.31-19.40.30'
2016-07-12 12:33:29 +03:00
SNAPSHOTS[ 10] = '@GMT-2010-11-11'
SNAPSHOTS[ 11] = '@GMT-2011.11.11-11.40.30'
SNAPSHOTS[ 12] = 'snap@GMT-2012.11.11-11.40.30'
SNAPSHOTS[ 13] = '@GMT-2013.11.11-11_40_33-snap'
SNAPSHOTS[ 14] = '@GMT-2014.11.11-11.40.30'
SNAPSHOTS[ 15] = 'daily@GMT-2015.11.11-11.40.30'
2016-07-13 19:15:27 +03:00
SNAPSHOTS[ 16] = 'snap_GMT-2016.11.11-11.40.30'
SNAPSHOTS[ 17] = 'sysp_GMT-2017.11.11-11.40.30'
SNAPSHOTS[ 18] = 'monthly@GMT-2018.11.11-11.40.30'
SNAPSHOTS[ 19] = 'straps_GMT-2019.11.11-11.40.33'
2015-10-29 23:24:30 +03:00
# build a hierarchy of files, symlinks, and directories
build_files( )
{
local rootdir
local prefix
local version
local destdir
2016-08-23 11:33:52 +03:00
local content
2015-10-29 23:24:30 +03:00
rootdir = $1
prefix = $2
version = $3
2016-08-23 11:33:52 +03:00
content = $4
2015-10-29 23:24:30 +03:00
if [ -n " $prefix " ] ; then
destdir = $rootdir /$prefix
else
destdir = $rootdir
fi
mkdir -p $destdir
if [ " $version " = "latest" ] ; then
#non-snapshot files
# for non-snapshot version, create legit files
# so that wide-link checks focus on snapshot files
2016-08-23 11:33:52 +03:00
echo " $content " > $destdir /foo
2015-10-29 23:24:30 +03:00
mkdir -p $destdir /bar
2016-08-23 11:33:52 +03:00
echo " $content " > $destdir /bar/baz
echo " $content " > $destdir /bar/lfoo
echo " $content " > $destdir /bar/letcpasswd
echo " $content " > $destdir /bar/loutside
2015-10-29 23:24:30 +03:00
elif [ " $version " = "fullsnap" ] ; then
#snapshot files
2016-08-23 11:33:52 +03:00
echo " $content " > $destdir /foo
2015-10-29 23:24:30 +03:00
mkdir -p $destdir /bar
2016-08-23 11:33:52 +03:00
echo " $content " > $destdir /bar/baz
2015-10-29 23:24:30 +03:00
ln -fs ../foo $destdir /bar/lfoo
ln -fs /etc/passwd $destdir /bar/letcpasswd
ln -fs ../../outside $destdir /bar/loutside
2016-08-23 11:33:52 +03:00
echo " $content " > ` dirname $destdir ` /outside
2015-10-29 23:24:30 +03:00
else #subshare snapshot - at bar
2016-08-23 11:33:52 +03:00
echo " $content " > $destdir /baz
2015-10-29 23:24:30 +03:00
ln -fs ../foo $destdir /lfoo
ln -fs /etc/passwd $destdir /letcpasswd
ln -fs ../../outside $destdir /loutside
2016-08-23 11:33:52 +03:00
echo " $content " > ` dirname $destdir ` /../outside
2015-10-29 23:24:30 +03:00
fi
}
# build a snapshots directory
build_snapshots( )
{
local where #where to build snapshots
local prefix #prefix from snapshot dir to share root
local start #timestamp index of first snapshot
local end #timestamp index of last snapshot
local sub #creat a snapshot of subtree of share
local snapdir
local snapname
local i
local version
where = $1
prefix = $2
start = $3
end = $4
sub = $5
snapdir = $where /.snapshots
mkdir -p $snapdir
version = "fullsnap"
if [ " $sub " = "1" ] ; then
version = "subsnap"
prefix = ""
# a valid link target for an inner symlink -
# the link is not broken yet should be blocked
# by wide link checks
touch $snapdir /foo
fi
for i in ` seq $start $end ` ; do
snapname = ${ SNAPSHOTS [ $i ] }
mkdir $snapdir /$snapname
2016-08-23 11:33:52 +03:00
build_files $snapdir /$snapname " $prefix " $version " $snapname "
2015-10-29 23:24:30 +03:00
done
}
# Test listing previous versions of a file
test_count_versions( )
{
local share
local path
local expected_count
2016-08-23 14:03:30 +03:00
local skip_content
2015-10-29 23:24:30 +03:00
local versions
2016-08-23 14:03:30 +03:00
local tstamps
local tstamp
local content
2016-08-23 14:29:39 +03:00
local is_dir
2015-10-29 23:24:30 +03:00
share = $1
path = $2
expected_count = $3
2016-08-23 14:03:30 +03:00
skip_content = $4
2015-10-29 23:24:30 +03:00
versions = ` $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " allinfo $path " | grep "^create_time:" | wc -l`
2016-08-23 14:03:30 +03:00
if [ " $versions " != " $expected_count " ] ; then
2015-10-29 23:24:30 +03:00
echo " expected $expected_count versions of $path , got $versions "
2016-08-23 14:03:30 +03:00
return 1
2015-10-29 23:24:30 +03:00
fi
2016-08-23 14:03:30 +03:00
2016-08-23 14:29:39 +03:00
is_dir = 0
$SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " allinfo $path " | grep "^attributes:.*D" && is_dir = 1
if [ $is_dir = 1 ] ; then
skip_content = 1
fi
2016-08-23 14:03:30 +03:00
#readable snapshots
tstamps = ` $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " allinfo $path " | awk '/^@GMT-/ {snapshot=$1} /^create_time:/ {printf "%s\n", snapshot}' `
for tstamp in $tstamps ; do
2016-08-23 14:29:39 +03:00
if [ $is_dir = 0 ] ;
then
if ! $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " get $tstamp \\ $path $WORKDIR /foo " ; then
echo " Failed getting \\\\ $SERVER \\ $share \\ $tstamp \\ $path "
return 1
fi
else
if ! $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " ls $tstamp \\ $path \\* " ; then
echo " Failed listing \\\\ $SERVER \\ $share \\ $tstamp \\ $path "
return 1
fi
2016-08-23 14:03:30 +03:00
fi
2016-08-23 14:29:39 +03:00
2016-08-23 14:03:30 +03:00
#also check the content, but not for wide links
if [ " x $skip_content " != "x1" ] ; then
content = ` cat $WORKDIR /foo`
if [ " $content " != " $tstamp " ] ; then
echo " incorrect content of \\\\ $SERVER \\ $share \\ $tstamp \\ $path expected [ $tstamp ] got [ $content ] "
return 1
fi
fi
done
#non-readable snapshots
tstamps = ` $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " allinfo $path " | \
awk '/^@GMT-/ {if (snapshot!=""){printf "%s\n", snapshot} ; snapshot=$1} /^create_time:/ {snapshot=""} END {if (snapshot!=""){printf "%s\n", snapshot}}' `
for tstamp in $tstamps ; do
2016-08-23 14:29:39 +03:00
if [ $is_dir = 0 ] ;
then
if $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " get $tstamp \\ $path $WORKDIR /foo " ; then
echo " Unexpected success getting \\\\ $SERVER \\ $share \\ $tstamp \\ $path "
return 1
fi
else
if $SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP -c " ls $tstamp \\ $path \\* " ; then
echo " Unexpected success listing \\\\ $SERVER \\ $share \\ $tstamp \\ $path "
return 1
fi
2016-08-23 14:03:30 +03:00
fi
done
2015-10-29 23:24:30 +03:00
}
# Test fetching a previous version of a file
test_fetch_snap_file( )
{
local share
local path
local snapidx
share = $1
path = $2
snapidx = $3
$SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP \
-c " get ${ SNAPSHOTS [ $snapidx ] } / $path $WORKDIR /foo "
}
2017-07-07 14:12:19 +03:00
# Test fetching a previous version of a file
test_fetch_snap_dir( )
{
local share
local path
local snapidx
share = $1
path = $2
snapidx = $3
# This first command is not strictly needed, but it causes the snapshots to
# appear in a network trace which helps debugging...
$SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP \
-c " allinfo $path "
$SMBCLIENT -U$USERNAME %$PASSWORD " // $SERVER / $share " -I $SERVER_IP \
-c " ls ${ SNAPSHOTS [ $snapidx ] } / $path /* "
}
2015-10-29 23:24:30 +03:00
test_shadow_copy_fixed( )
{
local share #share to contact
local where #where to place snapshots
local prefix #prefix to files inside snapshot
local msg
local allow_wl
local ncopies_allowd
local ncopies_blocked
share = $1
where = $2
prefix = $3
msg = $4
allow_wl = $5
ncopies_allowed = 4
ncopies_blocked = 1
if [ -n " $allow_wl " ] ; then
ncopies_blocked = 4
fi
#delete snapshots from previous tests
find $WORKDIR -name ".snapshots" -exec rm -rf { } \; 1>/dev/null 2>& 1
build_snapshots $WORKDIR /$where " $prefix " 0 2
testit " $msg - regular file " \
test_count_versions $share foo $ncopies_allowed || \
failed = ` expr $failed + 1`
testit " $msg - regular file in subdir " \
test_count_versions $share bar/baz $ncopies_allowed || \
failed = ` expr $failed + 1`
2024-01-16 13:42:43 +03:00
testit " $msg - regular file in case insensitive subdir " \
test_count_versions $share bar/bAz $ncopies_allowed || \
failed = ` expr $failed + 1`
2015-10-29 23:24:30 +03:00
testit " $msg - local symlink " \
test_count_versions $share bar/lfoo $ncopies_allowed || \
failed = ` expr $failed + 1`
testit " $msg - abs symlink outside " \
2016-08-23 14:03:30 +03:00
test_count_versions $share bar/letcpasswd $ncopies_blocked 1 || \
2015-10-29 23:24:30 +03:00
failed = ` expr $failed + 1`
testit " $msg - rel symlink outside " \
2016-08-23 14:03:30 +03:00
test_count_versions $share bar/loutside $ncopies_blocked 1 || \
2015-10-29 23:24:30 +03:00
failed = ` expr $failed + 1`
2016-08-23 14:29:39 +03:00
testit " $msg - list directory " \
test_count_versions $share bar $ncopies_allowed || \
failed = ` expr $failed + 1`
2015-10-29 23:24:30 +03:00
}
test_shadow_copy_everywhere( )
{
local share #share to contact
share = $1
#delete snapshots from previous tests
find $WORKDIR -name ".snapshots" -exec rm -rf { } \; 1>/dev/null 2>& 1
build_snapshots " $WORKDIR /mount " "base/share" 0 0
build_snapshots " $WORKDIR /mount/base " "share" 1 2
build_snapshots " $WORKDIR /mount/base/share " "" 3 5
build_snapshots " $WORKDIR /mount/base/share/bar " "" 6 9 1
testit "snapshots in each dir - regular file" \
test_count_versions $share foo 4 || \
failed = ` expr $failed + 1`
testit "snapshots in each dir - regular file in subdir" \
test_count_versions $share bar/baz 5 || \
failed = ` expr $failed + 1`
testit "snapshots in each dir - local symlink (but outside snapshot)" \
test_count_versions $share bar/lfoo 1 || \
failed = ` expr $failed + 1`
testit "snapshots in each dir - abs symlink outside" \
test_count_versions $share bar/letcpasswd 1 || \
failed = ` expr $failed + 1`
testit "snapshots in each dir - rel symlink outside" \
test_count_versions $share bar/loutside 1 || \
failed = ` expr $failed + 1`
#the previous versions of the file bar/lfoo points to are outside its
#snapshot, and are not reachable. However, but previous versions
#taken at different, non-overlapping times higher up the
#hierarchy are still reachable.
testit "fetch a previous version of a regular file" \
test_fetch_snap_file $share "bar/baz" 6 || \
failed = ` expr $failed + 1`
2020-04-21 14:06:03 +03:00
testit "fetch a previous version of a regular file via non-canonical parent path" \
test_fetch_snap_file $share "BAR/baz" 6 || \
failed = ` expr $failed + 1`
testit "fetch a previous version of a regular file via non-canonical basepath" \
test_fetch_snap_file $share "bar/BAZ" 6 || \
failed = ` expr $failed + 1`
testit "fetch a previous version of a regular file via non-canonical path" \
test_fetch_snap_file $share "BAR/BAZ" 6 || \
failed = ` expr $failed + 1`
2015-10-29 23:24:30 +03:00
testit_expect_failure "fetch a (non-existent) previous version of a symlink" \
test_fetch_snap_file $share "bar/lfoo" 6 || \
failed = ` expr $failed + 1`
testit "fetch a previous version of a symlink via browsing (1)" \
test_fetch_snap_file $share "bar/lfoo" 0 || \
failed = ` expr $failed + 1`
testit "fetch a previous version of a symlink via browsing (2)" \
test_fetch_snap_file $share "bar/lfoo" 1 || \
failed = ` expr $failed + 1`
testit "fetch a previous version of a symlink via browsing (3)" \
test_fetch_snap_file $share "bar/lfoo" 3 || \
failed = ` expr $failed + 1`
2017-07-07 14:12:19 +03:00
testit "list a previous version directory" \
test_fetch_snap_dir $share "bar" 6 || \
failed = ` expr $failed + 1`
2015-10-29 23:24:30 +03:00
}
2016-07-12 12:33:29 +03:00
test_shadow_copy_format( )
{
local share #share to contact
local where #where to place snapshots
local prefix #prefix to files inside snapshot
local ncopies_allowd
local msg
share = $1
where = $2
prefix = $3
ncopies_allowed = $4
msg = $5
#delete snapshots from previous tests
find $WORKDIR -name ".snapshots" -exec rm -rf { } \; 1>/dev/null 2>& 1
2016-07-13 19:15:27 +03:00
build_snapshots $WORKDIR /$where " $prefix " 10 19
2016-07-12 12:33:29 +03:00
testit " $msg - regular file " \
2016-08-23 14:03:30 +03:00
test_count_versions $share foo $ncopies_allowed 1 || \
2016-07-12 12:33:29 +03:00
failed = ` expr $failed + 1`
}
2023-12-28 16:20:11 +03:00
# Test fetching a file where there's no current version of it
test_missing_basedir( )
{
local share
local where
local prefix
local snapidx
share = $1
where = $2
prefix = $3
snapidx = $4
#delete snapshots from previous tests
find $WORKDIR -name ".snapshots" -exec rm -rf { } \; 1>/dev/null 2>& 1
build_snapshots $WORKDIR /$where " $prefix " " $snapidx " " $snapidx "
( cd " $WORKDIR / $where " /share; mv bar _bar)
testit "fetch a file without a latest version" \
test_fetch_snap_file " $share " "bar/baz" " $snapidx " || \
failed = ` expr $failed + 1`
( cd " $WORKDIR / $where " /share; mv _bar bar)
}
2015-10-29 23:24:30 +03:00
#build "latest" files
2016-08-23 11:33:52 +03:00
build_files $WORKDIR /mount base/share "latest" "latest"
2015-10-29 23:24:30 +03:00
failed = 0
# a test with wide links allowed - also to verify that what's later
# being blocked is a result of server security measures and not
# a testing artifact.
test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1
# tests for a fixed snapshot location
test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume"
test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume"
test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point"
test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside"
test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume"
test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside"
2015-11-03 12:15:52 +03:00
test_shadow_copy_fixed shadow8 . share "logical snapshot layout"
2015-10-29 23:24:30 +03:00
# tests for snapshot everywhere - one snapshot location
test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots"
test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots"
test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots"
# a test for snapshots everywhere - multiple snapshot locations
test_shadow_copy_everywhere shadow7
2016-07-12 12:33:29 +03:00
# tests for testing snapshot selection via shadow:format
test_shadow_copy_format shadow_fmt0 mount/base share 3 "basic shadow:format test"
test_shadow_copy_format shadow_fmt1 mount/base share 2 "shadow:format with only date"
test_shadow_copy_format shadow_fmt2 mount/base share 2 "shadow:format with some prefix"
test_shadow_copy_format shadow_fmt3 mount/base share 2 "shadow:format with modified format"
2016-07-13 19:15:27 +03:00
test_shadow_copy_format shadow_fmt4 mount/base share 3 "shadow:format with snapprefix"
test_shadow_copy_format shadow_fmt5 mount/base share 6 "shadow:format with delimiter"
2023-12-28 16:20:11 +03:00
test_missing_basedir shadow3 "mount/base" "share" 6
2016-07-12 12:33:29 +03:00
2015-10-29 23:24:30 +03:00
exit $failed