shadow_copy2: Add test cases to cover shadow:format
[amitay/samba.git] / source3 / script / tests / test_shadow_copy.sh
1 #!/bin/bash
2 #
3 # Blackbox test for shadow_copy2 VFS.
4 #
5
6 if [ $# -lt 7 ]; then
7 cat <<EOF
8 Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT
9 EOF
10 exit 1;
11 fi
12
13 SERVER=${1}
14 SERVER_IP=${2}
15 DOMAIN=${3}
16 USERNAME=${4}
17 PASSWORD=${5}
18 WORKDIR=${6}
19 SMBCLIENT=${7}
20 shift 7
21 SMBCLIENT="$VALGRIND ${SMBCLIENT}"
22 ADDARGS="$*"
23
24 incdir=`dirname $0`/../../../testprogs/blackbox
25 . $incdir/subunit.sh
26
27 SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30'
28 SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30'
29 SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30'
30 SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30'
31 SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30'
32 SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30'
33 SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30'
34 SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30'
35 SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30'
36 SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30'
37 SNAPSHOTS[10]='@GMT-2010-11-11'
38 SNAPSHOTS[11]='@GMT-2011.11.11-11.40.30'
39 SNAPSHOTS[12]='snap@GMT-2012.11.11-11.40.30'
40 SNAPSHOTS[13]='@GMT-2013.11.11-11_40_33-snap'
41 SNAPSHOTS[14]='@GMT-2014.11.11-11.40.30'
42 SNAPSHOTS[15]='daily@GMT-2015.11.11-11.40.30'
43
44 # build a hierarchy of files, symlinks, and directories
45 build_files()
46 {
47     local rootdir
48     local prefix
49     local version
50     local destdir
51     rootdir=$1
52     prefix=$2
53     version=$3
54     if [ -n "$prefix" ] ; then
55         destdir=$rootdir/$prefix
56     else
57         destdir=$rootdir
58     fi
59
60     mkdir -p $destdir
61     if [ "$version" = "latest" ] ; then
62         #non-snapshot files
63         # for non-snapshot version, create legit files
64         # so that wide-link checks focus on snapshot files
65         touch $destdir/foo
66         mkdir -p $destdir/bar
67         touch $destdir/bar/baz
68         touch $destdir/bar/lfoo
69         touch $destdir/bar/letcpasswd
70         touch $destdir/bar/loutside
71     elif [ "$version" = "fullsnap" ] ; then
72         #snapshot files
73         touch $destdir/foo
74         mkdir -p $destdir/bar
75         touch $destdir/bar/baz
76         ln -fs ../foo $destdir/bar/lfoo
77         ln -fs /etc/passwd $destdir/bar/letcpasswd
78         ln -fs ../../outside $destdir/bar/loutside
79         touch `dirname $destdir`/outside
80     else #subshare snapshot - at bar
81         touch $destdir/baz
82         ln -fs ../foo $destdir/lfoo
83         ln -fs /etc/passwd $destdir/letcpasswd
84         ln -fs ../../outside $destdir/loutside
85         touch `dirname $destdir`/../outside
86     fi
87
88 }
89
90 # build a snapshots directory
91 build_snapshots()
92 {
93     local where     #where to build snapshots
94     local prefix    #prefix from snapshot dir to share root
95     local start     #timestamp index of first snapshot
96     local end       #timestamp index of last snapshot
97     local sub       #creat a snapshot of subtree of share
98     local snapdir
99     local snapname
100     local i
101     local version
102
103     where=$1
104     prefix=$2
105     start=$3
106     end=$4
107     sub=$5
108
109     snapdir=$where/.snapshots
110     mkdir -p $snapdir
111
112     version="fullsnap"
113     if [ "$sub" = "1" ] ; then
114         version="subsnap"
115         prefix=""
116
117         # a valid link target for an inner symlink -
118         # the link is not broken yet should be blocked
119         # by wide link checks
120         touch $snapdir/foo
121     fi
122
123     for i in `seq $start $end` ; do
124         snapname=${SNAPSHOTS[$i]}
125         mkdir $snapdir/$snapname
126         build_files $snapdir/$snapname "$prefix" $version
127     done
128 }
129
130 # Test listing previous versions of a file
131 test_count_versions()
132 {
133     local share
134     local path
135     local expected_count
136     local versions
137
138     share=$1
139     path=$2
140     expected_count=$3
141     versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l`
142     if [ "$versions" = "$expected_count" ] ; then
143         true
144     else
145         echo "expected $expected_count versions of $path, got $versions"
146         false
147     fi
148 }
149
150 # Test fetching a previous version of a file
151 test_fetch_snap_file()
152 {
153     local share
154     local path
155     local snapidx
156
157     share=$1
158     path=$2
159     snapidx=$3
160     $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \
161         -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo"
162 }
163
164 test_shadow_copy_fixed()
165 {
166     local share     #share to contact
167     local where     #where to place snapshots
168     local prefix    #prefix to files inside snapshot
169     local msg
170     local allow_wl
171     local ncopies_allowd
172     local ncopies_blocked
173
174     share=$1
175     where=$2
176     prefix=$3
177     msg=$4
178     allow_wl=$5
179
180     ncopies_allowed=4
181     ncopies_blocked=1
182     if [ -n "$allow_wl" ] ; then
183         ncopies_blocked=4
184     fi
185
186     #delete snapshots from previous tests
187     find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
188     build_snapshots $WORKDIR/$where "$prefix" 0 2
189
190     testit "$msg - regular file" \
191         test_count_versions $share foo $ncopies_allowed || \
192         failed=`expr $failed + 1`
193
194     testit "$msg - regular file in subdir" \
195         test_count_versions $share bar/baz $ncopies_allowed || \
196         failed=`expr $failed + 1`
197
198     testit "$msg - local symlink" \
199         test_count_versions $share bar/lfoo $ncopies_allowed || \
200         failed=`expr $failed + 1`
201
202     testit "$msg - abs symlink outside" \
203         test_count_versions $share bar/letcpasswd $ncopies_blocked || \
204         failed=`expr $failed + 1`
205
206     testit "$msg - rel symlink outside" \
207         test_count_versions $share bar/loutside $ncopies_blocked || \
208         failed=`expr $failed + 1`
209 }
210
211 test_shadow_copy_everywhere()
212 {
213     local share     #share to contact
214
215     share=$1
216
217     #delete snapshots from previous tests
218     find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
219     build_snapshots "$WORKDIR/mount" "base/share" 0 0
220     build_snapshots "$WORKDIR/mount/base" "share" 1 2
221     build_snapshots "$WORKDIR/mount/base/share" "" 3 5
222     build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1
223
224     testit "snapshots in each dir - regular file" \
225         test_count_versions $share foo 4 || \
226         failed=`expr $failed + 1`
227
228     testit "snapshots in each dir - regular file in subdir" \
229         test_count_versions $share bar/baz 5 || \
230         failed=`expr $failed + 1`
231
232     testit "snapshots in each dir - local symlink (but outside snapshot)" \
233         test_count_versions $share bar/lfoo 1 || \
234         failed=`expr $failed + 1`
235
236     testit "snapshots in each dir - abs symlink outside" \
237         test_count_versions $share bar/letcpasswd 1 || \
238         failed=`expr $failed + 1`
239
240     testit "snapshots in each dir - rel symlink outside" \
241         test_count_versions $share bar/loutside 1 || \
242         failed=`expr $failed + 1`
243
244     #the previous versions of the file bar/lfoo points to are outside its
245     #snapshot, and are not reachable. However, but previous versions
246     #taken at different, non-overlapping times higher up the
247     #hierarchy are still reachable.
248     testit "fetch a previous version of a regular file" \
249         test_fetch_snap_file $share "bar/baz" 6 || \
250         failed=`expr $failed + 1`
251
252     testit_expect_failure "fetch a (non-existent) previous version of a symlink" \
253         test_fetch_snap_file $share "bar/lfoo" 6 || \
254         failed=`expr $failed + 1`
255
256     testit "fetch a previous version of a symlink via browsing (1)" \
257         test_fetch_snap_file $share "bar/lfoo" 0 || \
258         failed=`expr $failed + 1`
259
260     testit "fetch a previous version of a symlink via browsing (2)" \
261         test_fetch_snap_file $share "bar/lfoo" 1 || \
262         failed=`expr $failed + 1`
263
264     testit "fetch a previous version of a symlink via browsing (3)" \
265         test_fetch_snap_file $share "bar/lfoo" 3 || \
266         failed=`expr $failed + 1`
267
268 }
269
270 test_shadow_copy_format()
271 {
272     local share     #share to contact
273     local where     #where to place snapshots
274     local prefix    #prefix to files inside snapshot
275     local ncopies_allowd
276     local msg
277
278     share=$1
279     where=$2
280     prefix=$3
281     ncopies_allowed=$4
282     msg=$5
283
284     #delete snapshots from previous tests
285     find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
286     build_snapshots $WORKDIR/$where "$prefix" 10 15
287
288     testit "$msg - regular file" \
289         test_count_versions $share foo $ncopies_allowed || \
290         failed=`expr $failed + 1`
291 }
292
293 #build "latest" files
294 build_files $WORKDIR/mount base/share "latest"
295
296 failed=0
297
298 # a test with wide links allowed - also to verify that what's later
299 # being blocked is a result of server security measures and not
300 # a testing artifact.
301 test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1
302
303 # tests for a fixed snapshot location
304 test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume"
305 test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume"
306 test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point"
307 test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside"
308 test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume"
309 test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside"
310 test_shadow_copy_fixed shadow8 . share "logical snapshot layout"
311
312 # tests for snapshot everywhere - one snapshot location
313 test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots"
314 test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots"
315 test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots"
316
317 # a test for snapshots everywhere - multiple snapshot locations
318 test_shadow_copy_everywhere shadow7
319
320 # tests for testing snapshot selection via shadow:format
321 test_shadow_copy_format shadow_fmt0 mount/base share 3 "basic shadow:format test"
322 test_shadow_copy_format shadow_fmt1 mount/base share 2 "shadow:format with only date"
323 test_shadow_copy_format shadow_fmt2 mount/base share 2 "shadow:format with some prefix"
324 test_shadow_copy_format shadow_fmt3 mount/base share 2 "shadow:format with modified format"
325
326 exit $failed