aa82441e4baee64a16d3e2f38afb601a45956d28
[xfstests-dev.git] / tests / generic / 001
1 #! /bin/bash
2 # FS QA Test No. 001
3 #
4 # Random file copier to produce chains of identical files so the head
5 # and the tail can be diff'd at the end of each iteration.
6 #
7 # Exercises creat, write and unlink for a variety of directory sizes, and
8 # checks for data corruption.
9 #
10 # run [config]
11 #
12 # config has one line per file with filename and byte size, else use
13 # the default one below.
14 #
15 #-----------------------------------------------------------------------
16 # Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
17 #
18 # This program is free software; you can redistribute it and/or
19 # modify it under the terms of the GNU General Public License as
20 # published by the Free Software Foundation.
21 #
22 # This program is distributed in the hope that it would be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 # GNU General Public License for more details.
26 #
27 # You should have received a copy of the GNU General Public License
28 # along with this program; if not, write the Free Software Foundation,
29 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30 #
31 #-----------------------------------------------------------------------
32 #
33
34 seq=`basename $0`
35 seqres=$RESULT_DIR/$seq
36 echo "QA output created by $seq"
37
38 # get standard environment, filters and checks
39 . ./common/rc
40 . ./common/filter
41
42 tmp=/tmp/$$
43 here=`pwd`
44 status=1
45 done_cleanup=false
46 trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
47
48 # real QA test starts here
49 _supported_fs generic
50 _supported_os IRIX Linux
51
52 verbose=true
53 verify=$here/verify_fill
54
55 if [ $# -eq 0 ]
56 then
57     # use the default config
58     #
59     cat <<End-of-File >$tmp.config
60 # pathname      size in bytes
61 #
62 small           10
63 big             102400
64 sub/small       10
65 sub/big         102400
66 #
67 sub/a           1
68 sub/b           2
69 sub/c           4
70 sub/d           8
71 sub/e           16
72 sub/f           32
73 sub/g           64
74 sub/h           128
75 sub/i           256
76 sub/j           512
77 sub/k           1024
78 sub/l           2048
79 sub/m           4096
80 sub/n           8192
81 #
82 sub/a00         100
83 sub/b00         200
84 sub/c00         400
85 sub/d00         800
86 sub/e00         1600
87 sub/f00         3200
88 sub/g00         6400
89 sub/h00         12800
90 sub/i00         25600
91 sub/j00         51200
92 sub/k00         102400
93 sub/l00         204800
94 sub/m00         409600
95 sub/n00         819200
96 #
97 sub/a000        1000
98 sub/e000        16000
99 sub/h000        128000
100 sub/k000        1024000
101 End-of-File
102 elif [ $# -eq 1 ]
103 then
104     if [ -f $1 ]
105     then
106         cp $1 $tmp.config
107     else
108         echo "Error: cannot open config \"$1\""
109         exit 1
110     fi
111 else
112     echo "Usage: run [config]"
113     exit 1
114 fi
115
116 ncopy=200               # number of file copies in the chain step
117 udf_fsize=20240         # number of sectors for UDF
118
119 _setup()
120 {
121     if mkdir -p $testdir/$$
122     then
123         :
124     else
125         echo "Error: cannot mkdir \"$testdir/$$\""
126         exit 1
127     fi
128     cd $testdir/$$
129
130     $verbose && echo -n "setup "
131     sed -e '/^#/d' $tmp.config \
132     | while read file nbytes
133     do
134         dir=`dirname $file`
135         if [ "$dir" != "." ]
136         then
137             if [ ! -d $dir ]
138             then
139                 if mkdir $dir
140                 then
141                     :
142                 else
143                     $verbose && echo
144                     echo "Error: cannot mkdir \"$dir\""
145                     exit 1
146                 fi
147             fi
148         fi
149         rm -f $file
150         if $here/src/fill $file $file $nbytes
151         then
152             :
153         else
154             $verbose && echo
155             echo "Error: cannot create \"$file\""
156             exit 1
157         fi
158         $verbose && echo -n "."
159     done
160     $verbose && echo
161 }
162
163 _mark_iteration()
164 {
165     $verbose && echo -n "mark_iteration "
166     sed -e '/^#/d' $tmp.config \
167     | while read file nbytes
168     do
169         if [ ! -f $file ]
170         then
171             $verbose && echo
172             echo "Error: $file vanished!"
173             touch $tmp.bad
174             continue
175         fi
176         sed -e "s/ [0-9][0-9]* / $1 /" <$file >$file.tmp
177         mv $file.tmp $file
178         $verbose && echo -n "."
179     done
180     $verbose && echo
181 }
182
183 # for each file, make a number of copies forming a chain like foo.0,
184 # foo.1, foo.2, ... foo.N
185 #
186 # files are chosen at random, so the lengths of the chains are different
187 #
188 # then rename foo.N to foo.last and remove all of the other files in
189 # the chain
190 #
191 _chain()
192 {
193     $AWK_PROG -v full_file=$seqres.full -v verify=$verify <$tmp.config '
194 BEGIN   { nfile = 0 }
195 /^\#/   { next }
196         { file[nfile] = $1
197           size[nfile] = $2
198           link[nfile] = 0
199           nfile++
200           total_size += $2
201         }
202 END     { srand('$iter')
203           for (i=0; i < '$ncopy'; i++) {
204             # choose a file at random, and add one copy to that chain
205             j = -1
206             while (j < 0 || j >= nfile)
207                 j = int(rand() * nfile)
208             if (link[j] == 0) {
209                 # previous should already exist and next one should not exist
210                 printf "if [ ! -f %s ]; then echo \"%s missing!\"; exit; fi\n",file[j],file[j]
211                 printf "if [ -f %s.0 ]; then echo \"%s.0 already present!\"; exit; fi\n",file[j],file[j]
212                 printf "cp %s %s.0 || exit 1\n",file[j],file[j]
213                 printf "ls -i %s.0\n", file[j] >full_file;
214                 total_size += size[j]
215                 printf "# total size = %d\n", total_size 
216             }
217             else {
218                 # previous should already exist and next one should not exist
219                 printf "if [ ! -f %s.%d ]; then echo \"%s.%d missing!\"; exit; fi\n",file[j],link[j]-1,file[j],link[j]-1
220                 printf "if [ -f %s.%d ]; then echo \"%s.%d already present!\"; exit; fi\n",file[j],link[j],file[j],link[j]
221                 printf "cp %s.%d %s.%d || exit 1\n",file[j],link[j]-1,file[j],link[j]
222                 printf "ls -i %s.%d\n", file[j], link[j] >full_file;
223                 total_size += size[j]
224                 printf "# total size = %d\n", total_size 
225             }
226             link[j]++
227           }
228           # close all the chains, 
229           # if have at least one copy then move the last copy to "file[j].last"
230           # and remove all of the other files except the head of the chain
231           for (j=0; j<nfile; j++) {
232             if (link[j] > 0) {
233                 printf "mv %s.%d %s.last\n",file[j],link[j]-1,file[j]
234                 printf "ls -i %s.last\n", file[j] >full_file;
235             }
236             for (i=0; i<link[j]-1; i++) {
237                 printf "rm -f %s.%d\n",file[j],i
238             }
239           }
240         }' \
241         | tee -a $seqres.full | sh
242 }
243
244 _check()
245 {
246     rm -f $tmp.bad
247     $verbose && echo -n "check "
248     sed -e '/^#/d' $tmp.config \
249     | while read file nbytes
250     do
251         # the file is never removed so it should exist
252         if [ ! -f $file ]
253         then
254             $verbose && echo
255             echo "Error: $file vanished!"
256             touch $tmp.bad
257             continue
258         fi
259         # checks that the file and its last copy are the same
260         if [ -f $file.last ]
261         then
262             if cmp $file $file.last >/dev/null 2>&1
263             then
264                 $verbose && echo -n "."
265             else
266                 $verbose && echo
267                 echo "Error: corruption for $file ..."
268                 diff -c $file $file.last
269                 touch $tmp.bad
270             fi
271         else
272             $verbose && echo -n "."
273         fi
274     done
275     $verbose && echo
276 }
277
278 _cleanup()
279 {
280     # cleanup
281     #
282     if $done_cleanup
283     then
284         :
285     elif [ $status -eq 0 ]
286     then
287         $verbose && echo "cleanup"
288         cd /
289         rm -rf $testdir/$$
290         _cleanup_testdir
291         done_cleanup=true
292     fi
293 }
294
295 rm -f $seqres.full
296 status=0
297 _cleanup
298 status=1
299 done_cleanup=false
300
301 _setup_testdir
302 _setup
303
304 # do the test
305 #
306 for iter in 1 2 3 4 5
307 do
308     echo -n "iter $iter chain ... "
309     echo "iter $iter" >> $seqres.full
310     _chain
311     _check
312     if [ -f $tmp.bad ]
313     then
314         echo "Fatal error: test abandoned without changes"
315         exit 1
316     fi
317 done
318
319 status=0
320 exit