btrfs-progs: tests: add quotes around variables in common
[platform/upstream/btrfs-progs.git] / tests / common
1 #!/bin/bash
2 #
3 # Common routines for all tests
4 #
5
6 # assert that argument is not empty and is an existing path (file or directory)
7 _assert_path()
8 {
9         local path
10
11         path="$1"
12         if [ -z "$path" ]; then
13                 echo "ASSERTION FAIL: $path is not valid"
14                 exit 1
15         fi
16
17         if [ -f "$path" -o -d "$path" -o -b "$path" ]; then
18                 return 0
19         fi
20         echo "ASSERTION FAIL: $path is not valid"
21         exit 1
22 }
23
24 _fail()
25 {
26         echo "$*" | tee -a "$RESULTS"
27         exit 1
28 }
29
30 # log a message to the results file
31 _log()
32 {
33         echo "$*" | tee -a "$RESULTS"
34 }
35
36 _not_run()
37 {
38         echo "    [NOTRUN] $*"
39         exit 0
40 }
41
42 run_check()
43 {
44         echo "############### $@" >> "$RESULTS" 2>&1
45         if [ "$TEST_LOG" = 'tty' ]; then echo "CMD: $@" > /dev/tty; fi
46         if [ "$1" = 'root_helper' ]; then
47                 "$@" >> "$RESULTS" 2>&1 || _fail "failed: $@"
48         else
49                 $INSTRUMENT "$@" >> "$RESULTS" 2>&1 || _fail "failed: $@"
50         fi
51 }
52
53 # same as run_check but the stderr+stdout output is duplicated on stdout and
54 # can be processed further
55 run_check_stdout()
56 {
57         echo "############### $@" >> "$RESULTS" 2>&1
58         if [ "$TEST_LOG" = 'tty' ]; then echo "CMD(stdout): $@" > /dev/tty; fi
59         if [ "$1" = 'root_helper' ]; then
60                 "$@" 2>&1 | tee -a "$RESULTS" || _fail "failed: $@"
61         else
62                 $INSTRUMENT "$@" 2>&1 | tee -a "$RESULTS" || _fail "failed: $@"
63         fi
64 }
65
66 # same as run_check but does not fail the test, output is logged
67 run_mayfail()
68 {
69         local ret
70
71         echo "############### $@" >> "$RESULTS" 2>&1
72         if [ "$TEST_LOG" = 'tty' ]; then echo "CMD(mayfail): $@" > /dev/tty; fi
73         if [ "$1" = 'root_helper' ]; then
74                 "$@" >> $RESULTS 2>&1
75         else
76                 $INSTRUMENT "$@" >> "$RESULTS" 2>&1
77         fi
78         ret=$?
79         if [ $ret != 0 ]; then
80                 echo "failed (ignored, ret=$ret): $@" >> "$RESULTS"
81                 if [ $ret == 139 ]; then
82                         _fail "mayfail: returned code 139 (SEGFAULT), not ignored"
83                 elif [ $ret == 134 ]; then
84                         _fail "mayfail: returned code 134 (SIGABRT), not ignored"
85                 fi
86                 return $ret
87         fi
88 }
89
90 # first argument is error message to print if it fails, otherwise
91 # same as run_check but expects the command to fail, output is logged
92 run_mustfail()
93 {
94         local msg
95
96         msg="$1"
97         shift
98
99         echo "############### $@" >> "$RESULTS" 2>&1
100         if [ "$TEST_LOG" = 'tty' ]; then echo "CMD(mustfail): $@" > /dev/tty; fi
101         if [ "$1" = 'root_helper' ]; then
102                 "$@" >> "$RESULTS" 2>&1
103         else
104                 $INSTRUMENT "$@" >> "$RESULTS" 2>&1
105         fi
106         if [ $? != 0 ]; then
107                 echo "failed (expected): $@" >> "$RESULTS"
108                 return 0
109         else
110                 echo "succeeded (unexpected!): $@" >> "$RESULTS"
111                 _fail "unexpected success: $msg"
112                 return 1
113         fi
114 }
115
116 check_prereq()
117 {
118         if ! [ -f "$TOP/$1" ]; then
119                 _fail "Failed prerequisites: $1";
120         fi
121 }
122
123 check_global_prereq()
124 {
125         which $1 &> /dev/null
126         if [ $? -ne 0 ]; then
127                 _fail "Failed system wide prerequisities: $1";
128         fi
129 }
130
131 check_image()
132 {
133         local image
134
135         image=$1
136         echo "testing image $(basename $image)" >> "$RESULTS"
137         $TOP/btrfs check "$image" >> "$RESULTS" 2>&1
138         [ $? -eq 0 ] && _fail "btrfs check should have detected corruption"
139
140         run_check $TOP/btrfs check --repair "$image"
141         run_check $TOP/btrfs check "$image"
142 }
143
144 # Extract a usable image from packed formats
145 # - raw btrfs filesystem images, suffix .raw
146 # - dtto compressed by XZ, suffix .raw.xz
147 # - meta-dump images with suffix .img
148 # - dtto compressed by XZ, suffix .img.xz
149 # - compressed send stream, .stream.xz
150 extract_image()
151 {
152         local image
153         local cleanme
154
155         image="$1"
156         case "$image" in
157         *.img)
158                 rm -f "$image.restored"
159                 : ;;
160         *.img.xz)
161                 xz --decompress --keep "$image" || \
162                         _fail "failed to decompress image $image" >&2
163                 image=${image%%.xz}
164                 rm -f "$image.restored"
165                 cleanme=$image
166                 ;;
167         *.raw)
168                 cp --sparse=auto "$image" "$image.restored"
169                 ;;
170         *.raw.xz)
171                 xz --decompress --keep "$image" || \
172                         _fail "failed to decompress image $image" >&2
173                 image=${image%%.xz}
174                 mv "$image" "$image.restored"
175                 ;;
176         *.stream.xz)
177                 xz --decompress --keep "$image" || \
178                         _fail "failed to decompress file $image" >&2
179                 image=${image%%.xz}
180                 mv "$image" "$image.restored"
181                 ;;
182         esac
183
184         if ! [ -f "$image.restored" ]; then
185                 echo "restoring image $(basename $image)" >> "$RESULTS"
186                 "$TOP/btrfs-image" -r "$image" "$image.restored" \
187                         &>> "$RESULTS" \
188                         || _fail "failed to restore image $image" >&2
189         fi
190
191         [ -f "$cleanme" ] && rm -f "$cleanme"
192
193         echo "$image.restored"
194 }
195
196 # Process all image dumps in a given directory
197 check_all_images()
198 {
199         local dir
200         local extracted
201
202         dir="$1"
203         for image in $(find "$dir" \( -iname '*.img' -o \
204                                 -iname '*.img.xz' -o    \
205                                 -iname '*.raw' -o       \
206                                 -iname '*.raw.xz' \) | sort)
207         do
208                 extracted=$(extract_image "$image")
209                 check_image "$extracted"
210                 rm -f "$extracted"
211         done
212 }
213
214 # some tests need to mount the recovered image and do verifications call
215 # 'setup_root_helper' and then check for have_root_helper == 1 if the test
216 # needs to fail otherwise; using sudo by default for now
217 SUDO_HELPER=
218 NEED_SUDO_VALIDATE=unknown
219 export SUDO_HELPER
220 export NEED_SUDO_VALIDATE
221 root_helper()
222 {
223         if [ $UID -eq 0 ]; then
224                 "$@"
225         else
226                 if [ "$NEED_SUDO_VALIDATE" = 'yes' ]; then
227                         sudo -v -n &>/dev/null || \
228                                 _not_run "Need to validate sudo credentials"
229                         sudo -n "$@"
230                 elif [ "$NEED_SUDO_VALIDATE" = 'no' ]; then
231                         sudo -n /bin/true &> /dev/null || \
232                                 _not_run "Need to validate sudo user settings"
233                         sudo -n "$@"
234                 else
235                         # should not happen
236                         _not_run "Need to validate root privileges"
237                 fi
238         fi
239 }
240
241 setup_root_helper()
242 {
243         if [ $UID -eq 0 -o -n "$SUDO_HELPER" ]; then
244                 return
245         fi
246
247         # Test for old sudo or special settings, which make sudo -v fail even
248         # if user setting is NOPASSWD
249         sudo -n /bin/true &>/dev/null && NEED_SUDO_VALIDATE=no
250
251         # Newer sudo or default sudo setting
252         sudo -v -n &>/dev/null && NEED_SUDO_VALIDATE=yes
253
254         if [ "$NEED_SUDO_VALIDATE" = 'unknown' ]; then
255                 _not_run "Need to validate root privileges"
256         fi
257         SUDO_HELPER=root_helper
258 }
259
260 prepare_test_dev()
261 {
262         # num[K/M/G/T...]
263         local size="$1"
264
265         [[ "$TEST_DEV" ]] && return
266         [[ "$size" ]] || size='2G'
267
268         echo "\$TEST_DEV not given, use $TOP/test/test.img as fallback" >> \
269                 "$RESULTS"
270         TEST_DEV="$TOP/tests/test.img"
271
272         truncate -s "$size" "$TEST_DEV" || _not_run "create file for loop device failed"
273 }
274
275 run_check_mount_test_dev()
276 {
277         setup_root_helper
278
279         local loop_opt
280         if [[ -b "$TEST_DEV" ]]; then
281                 loop_opt=""
282         elif [[ -f "$TEST_DEV" ]]; then
283                 loop_opt="-o loop"
284         else
285                 _fail "Invalid \$TEST_DEV: $TEST_DEV"
286         fi
287
288         [[ -d "$TEST_MNT" ]] || {
289                 _fail "Invalid \$TEST_MNT: $TEST_MNT"
290         }
291
292         run_check $SUDO_HELPER mount $loop_opt "$@" "$TEST_DEV" "$TEST_MNT"
293 }
294
295 run_check_umount_test_dev()
296 {
297         setup_root_helper
298         run_check $SUDO_HELPER umount "$@" "$TEST_DEV"
299 }
300
301 check_kernel_support()
302 {
303         if ! grep -iq 'btrfs' /proc/filesystems; then
304                 echo "WARNING: btrfs filesystem not listed in /proc/filesystems, some tests might fail"
305                 return 1
306         fi
307         return 0
308 }
309
310 init_env()
311 {
312         TEST_MNT="${TEST_MNT:-$TOP/tests/mnt}"
313         export TEST_MNT
314         mkdir -p "$TEST_MNT" || { echo "Failed mkdir -p $TEST_MNT"; exit 1; }
315
316 }
317 init_env