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