forked from n8gray/Backup-Bouncer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbbouncer
executable file
·317 lines (285 loc) · 9.09 KB
/
bbouncer
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#!/bin/bash
#set -x
scriptdir="`dirname $0`"
cd "$scriptdir"
utildir=`realpath "$scriptdir"`"/util"
export PATH="/usr/bin:/bin:/usr/sbin:/sbin:$utildir"
export printWidth=20
export Critical=0
export Important=1
export Exhaustive=2
export run_priority=$Exhaustive
usage () {
name=bbouncer
echo "Usage:
General form:
$name <verb> [-d] [-t test]* [-T set] [-c copier]* args
Flags:
-d Show results of sub-tests individually instead of just
showing the result of the overall test.
-t <test> Use the given test instead of the whole test suite. May
be specified multiple times. Example:
$name copy -t 95-devices /Volumes/Src /Volumes/Dst
-T <set> Use the given set of tests. <set> can be:
\"critical\": for tests whose failure will cause
problems for average users
\"important\": for tests whose failure may not cause
problems for many users, but which
may be important to power-users or may
qualify as critical in the future.
\"all\": for the everything + the kitchen sink
The default is \"all\".
-c <copier> Use the given copier instead of the whole copier suite.
May be specified multiple times. Example:
$name copy -c 10-rsync-apple /Volumes/Src /Volumes/Dst
Meanings of different verbs:
$name create-vol volname
Create and mount a disk image suitable for testing.
$name create [-t test]* dir
Populate dir with test files/directories.
$name verify [-d] [-t test]* [-T set] [-c copier]* srcdir dstdir
Test the validity of the files in dstdir, which should be
copies of those in srcdir. srcdir should contain a directory
created by '$name create srcdir'.
$name copy [-d] [-t test]* [-T set] [-c copier]* srcdir dstdir
For each copier, copy from srcdir to dstdir/copier-name,
then verify each copy. Note that -t only affects the *verify*
step, not the copy step.
$name compare [-t test]* [-T set] srcfile dstfile
Test the two files for equality based on all tests in the
test suite (or the tests given with -t).
$name clean [-t test]* [-T set] dir
Remove all test files from dir. For various reasons,
simply running 'rm -rf dir' will not always work.
Note that many operations require elevated privileges, so you may be
prompted for your password.
The typical usage will be something like:
1. Create files
$name create-vol Src
$name create-vol Dst
$name create /Volumes/Src
2. Run test suite (as root!)
$name copy -d /Volumes/Src /Volumes/Dst
# That filled /Volumes/Dst with a subdirectory for each copier.
# To verify the results from a single copy again:
$name verify -d /Volumes/Src /Volumes/Dst/10-rsync-apple
3. Or maybe you want to test a GUI copier
$name create-vol SDDst
# Use SuperDuper! to copy from /Volumes/Src to /Volumes/SDDst, then:
$name verify -d /Volumes/Src /Volumes/SDDst
"
exit 1
}
read-tests () {
local testfiles=`ls tests.d/*.test`
local tests=''
for f in $testfiles; do
local tst=`basename -s .test $f`
tests="$tests $tst"
done
echo $tests
}
read-copiers () {
local copyfiles=`ls copiers.d/*.cp`
local copiers=''
for f in $copyfiles; do
local cpf=`basename -s .cp $f`
copiers="$copiers $cpf"
done
echo $copiers
}
create-vol () {
hdiutil create -size 40m -fs 'Journaled HFS+' \
-volname $1 -type SPARSE ./$1
hdiutil attach -owners on ./$1.sparseimage
/usr/bin/which -s fsaclctl && sudo fsaclctl -p /Volumes/$1 -e
touch /Volumes/$1/bbouncer-vol
}
check-vol () {
if [ -e $1/bbouncer-vol ]; then
return 0
else
echo "$1 is not a bbouncer volume! Aborting." 1>&2
exit 1
fi
}
clean () {
[ ! -d "$1" ] && return 0
check-vol $1
for t in $tests; do
tnice=$t
printf "Cleaning: %${printWidth}s\n" "$tnice"
if [ -d "$1/$t" ]; then
bash util/test-runner tests.d/$t.test clean $1/$t || true
sudo rm -Rf "$1/$t" || true
fi
done
}
create () {
check-vol $1
clean $1
for t in $tests; do
tnice=$t
printf "Creating: %${printWidth}s ... " "$tnice"
mkdir $1/$t
bash util/test-runner tests.d/$t.test create $1/$t \
&& echo ok \
|| echo FAIL
done
}
verify () {
local src="$1"
local dst="$2"
if [ ! -d "$2" ]; then
echo "Copier dir '$2' does not exist"
return 1
fi
if [ -e "$dst/exit-code" ]; then
local code=`cat $dst/exit-code | awk '{print $1}'`
if [ ! "$code" = "0" ]; then
echo "This copier exited with error code $code"
fi
fi
if [ -e "$dst/log" ] && [ ! "`wc -c $dst/log | awk '{print $1}'`" = "0" ]; then
echo "This copier produced log output in:"
echo " $dst/log"
fi
for t in $tests; do
local tnice=${t:3}
if [ ! -d "$dst/$t" ]; then
echo "Test dir '$dst/$t' does not exist"
continue
fi
#printf "Verifying: %${printWidth}s ... " "$tnice"
bash util/test-runner tests.d/$t.test verify Verifying $tnice $dst/$t $src/$t
done
}
# Compare a single pair of files for all known properties.
compare () {
for t in $tests; do
tnice=${t:3}
#printf "Comparing: %${printWidth}s ... " "$tnice"
bash util/test-runner tests.d/$t.test compare Comparing $tnice $1 $2
done
}
copy () {
check-vol $1
check-vol $2
# Make sure there's no trailing /
local src="`dirname $1`/`basename $1`"
local dst="`dirname $2`/`basename $2`"
echo "src = $src"
echo "dst = $dst"
# This requires the actual mount point.
local srcDisk=`stat -f "%Sd" $src`
local dstDisk=`stat -f "%Sd" $dst`
echo Enabling owners on src/dst disks
sudo mount -uvo perm /dev/$srcDisk
sudo mount -uvo perm /dev/$dstDisk
echo -n Cleaning
# Always clean all tests -- we want to start fresh on a copy.
oldtests="$tests"
tests=`read-tests`
for c in $copiers; do
echo -n .
clean $dst/$c > /dev/null
sudo rm -Rf $dst/$c
done
tests="$oldtests"
echo
for c in $copiers; do
cnice=${c:3}
printf "Copying with: %${printWidth}s ... " "$cnice"
mkdir $dst/$c
bash util/copy-runner copiers.d/$c.cp $src $dst/$c
code=$?
echo $code > $dst/$c/exit-code
# Make sure the volume can be cleaned
touch $dst/$c/bbouncer-vol
[ "$code" = "0" ] && echo ok \
|| echo FAIL
done
for c2 in $copiers; do
cnice=${c2:3}
echo
echo "------------------ $cnice ------------------"
if [ -e $dst/$c2/skipped ]; then
echo " This copier was skipped"
else
local outfile=$dst/$c2/verify-output
echo "------------------ $cnice ------------------" > $outfile
verify $src $dst/$c2 | tee -a $outfile
fi
done
}
# Parse arguments
test-set () {
local tests
case $1 in
critical)
tests=`(cd tests.d; grep -l '##Critical##' *.test)`;;
important)
tests=`(cd tests.d; grep -l '##Critical##\|##Important##' *.test)`;;
*)
echo Unknown test set: $1 >&2;;
esac
for t in $tests; do
printf "%s " ${t/.test/}
done
}
[ "$#" -lt "2" ] && usage
verb=$1
shift
# Check for flags
tests=''
copiers=''
while [ "${1:0:1}" = "-" ]; do
opt=$1
shift
case $opt in
-d) export DETAIL=1;;
-t)
if [ ! -f "tests.d/$1.test" ]; then
echo "No such test: tests.d/$1.test"
exit 1
fi
tests="$tests $1"
shift
;;
-c)
if [ ! -f "copiers.d/$1.cp" ]; then
echo "No such copier: copiers.d/$1.cp"
exit 1
fi
copiers="$copiers $1"
shift
;;
-T)
prio="$1"
shift
case $prio in
critical) run_priority=$Critical ;;
important) run_priority=$Important ;;
all) run_priority=$Exhaustive ;;
*) usage ;;
esac
;;
*)
echo "Unkown flag: $opt"
exit 1
esac
done
[ -z "$tests" ] && tests="`read-tests`"
[ -z "$copiers" ] && copiers="`read-copiers`"
case $verb in
create|create-vol|clean)
$verb $1
;;
verify|copy|compare)
[ "$#" -lt "2" ] && usage
$verb $1 $2
;;
*)
usage
;;
esac