Fix sequential extraction, and include progress info
[wimlib] / tests / test-imagex
1 #!/usr/bin/env bash
2
3 # This script does some sanity testing of the 'imagex' program.  It by no means
4 # tests every aspect of wimlib comprehensively.
5
6 set -e
7 cd tests
8 srcdir="${srcdir:-.}/.."
9 srcdir="$(cd $srcdir; pwd)"
10
11 imagex() {
12         echo "imagex $@"
13         ../imagex "$@" > /dev/null
14 }
15
16 imagex_info() {
17         echo "imagex info $@"
18         ../imagex info "$@"
19 }
20
21 cleanup() {
22         fusermount -u tmp &> /dev/null || true
23         rm -rf dir* tmp* *.wim *.swm &> /dev/null || true
24 }
25 cleanup
26
27 # Make test directory
28 mkdir dir
29 cp $srcdir/src/*.c $srcdir/src/*.h dir
30 mkdir dir/subdir
31 echo 'hello' > dir/subdir/hello
32 echo 'hello' > dir/subdir/hello2
33 ln dir/subdir/hello dir/subdir/hellolink
34 echo -n > dir/subdir/empty_file
35 ln -s hello dir/subdir/rel_symlink
36
37 mkdir dir2
38 echo 'testing' > dir2/file
39 dd if=/dev/zero of=dir2/zeroes bs=4096 count=5
40
41 error() {
42         echo "**********************************************"
43         echo "                  Test failure                "
44         echo $*
45         echo "**********************************************"
46         exit 1
47 }
48
49 # Capturing and applying WIM with None, LZX, and XPRESS compression
50
51 for comp_type in None LZX XPRESS; do
52         echo "Testing capture and application of $comp_type-compressed WIM"
53         if ! imagex capture dir dir.wim --compress=$comp_type; then
54                 error "'imagex capture' failed"
55         fi
56         if ! imagex apply dir.wim tmp; then
57                 error "'imagex apply' failed"
58         fi
59         if ! test "`imagex_info dir.wim | grep Compression | awk '{print $2}'`" = "$comp_type"; then
60                 error "'imagex_info' didn't report the compression type correctly"
61         fi
62         if ! diff -q -r dir tmp; then
63                 error "Recursive diff of extracted directory with original failed"
64         fi
65         if ! test `stat -c %h tmp/subdir/hello` = 2; then
66                 error "Incorrect number of hard links in extracted file"
67         fi
68         if ! test `stat -c %i tmp/subdir/hello` != `stat -c %i tmp/subdir/hello2`; then
69                 error "Expected different inode numbers in files not hard-linked"
70         fi
71         if ! test "`stat -c %i tmp/subdir/hello`" = "`stat -c %i tmp/subdir/hellolink`"; then
72                 error "Expected same inode numbers in hard-linked files"
73         fi
74         if ! test -L tmp/subdir/rel_symlink; then
75                 error "Symlink not extracted correctly"
76         fi
77         if ! test "`readlink tmp/subdir/rel_symlink`" = "hello"; then
78                 error "Symlink target not correct"
79         fi
80
81         rm -rf dir.wim tmp
82 done
83
84 # Capturing and modifying name, description, and bootable flag
85
86 echo "Testing capture of WIM with default name and description"
87 imagex capture dir dir.wim
88 if ! test "`imagex_info dir.wim | grep Name | awk '{print $2}'`" = "dir"; then
89         error "WIM name not set correctly"
90 fi
91 if ! test "`imagex_info dir.wim | grep Description | awk '{print $2}'`" = ""; then
92         error "WIM description not set correctly"
93 fi
94
95 echo "Testing capture of WIM with default boot flag"
96 imagex capture dir dir.wim
97 if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
98         error "WIM boot flag not set correctly"
99 fi
100
101 echo "Testing changing image bootable flag"
102 if ! imagex_info dir.wim 1 --boot; then
103         error "Failed to change bootable image"
104 fi
105 if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
106         error "Bootable image not changed correctly"
107 fi
108 echo "Testing changing image bootable flag"
109 if ! imagex_info dir.wim 0 --boot; then
110         error "Failed to reset bootable image"
111 fi
112 if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
113         error "Bootable image not reset correctly"
114 fi
115 echo "Testing changing image bootable flag to invalid image (this should generate errors)"
116 if imagex_info dir.wim 2 --boot; then
117         error "Succeeded in changing bootable image to invalid number"
118 fi
119 if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
120         error "Boot flag was changed even though the change command was supposed to fail"
121 fi
122 rm -rf dir.wim tmp
123
124 echo "Testing capture of WIM with name and description"
125 if ! imagex capture dir dir.wim "myname" "mydesc"; then
126         error "Failed to capture WIM with specified name and description"
127 fi
128 if ! test "`imagex_info dir.wim | grep Name | awk '{print $2}'`" = "myname"; then
129         error "WIM name not set correctly"
130 fi
131 if ! test "`imagex_info dir.wim | grep Description | awk '{print $2}'`" = "mydesc"; then
132         error "WIM name not set correctly"
133 fi
134 echo "Testing printing WIM lookup table"
135 if ! imagex_info --lookup-table dir.wim > /dev/null; then
136         error "Failed to print WIM lookup table"
137 fi
138 echo "Testing printing WIM header"
139 if ! imagex_info --header dir.wim > /dev/null; then
140         error "Failed to print WIM header"
141 fi
142 echo "Testing printing WIM XML info"
143 if ! imagex_info --xml dir.wim > /dev/null; then
144         error "Failed to print WIM XML data"
145 fi
146 echo "Testing extracting WIM XML info"
147 if ! imagex_info --extract-xml=dir.xml dir.wim; then
148         error "Failed to extract WIM XML data"
149 fi
150 echo "Testing printing WIM metadata"
151 if ! imagex_info --metadata dir.wim > /dev/null; then
152         error "Failed to print WIM metadata"
153 fi
154 rm -rf dir.wim tmp dir.xml
155
156 echo "Testing capture of bootable WIM"
157 if ! imagex capture dir dir.wim --boot; then
158         error "Failed to capture bootable WIM"
159 fi
160 if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
161         error "Boot flag on bootable WIM not set correctly"
162 fi
163 rm -rf dir.wim tmp
164
165 # Integrity table
166
167 echo "Testing capture of WIM with integrity table"
168 if ! imagex capture dir dir.wim --check; then
169         error "Failed to capture WIM with integrity table"
170 fi
171 if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
172         error "Integrity table on WIM not made"
173 fi
174 if ! imagex apply --check dir.wim tmp; then
175         error "Integrity table on WIM not made correctly"
176 fi
177 if ! diff -q -r dir tmp; then
178         error "Recursive diff of applied WIM with original directory failed"
179 fi
180 rm -rf dir.wim tmp
181
182 # Appending and deleting images
183
184 echo "Testing appending WIM image"
185 imagex capture dir dir.wim
186 if ! imagex append dir2 dir.wim; then
187         error "Appending WIM image failed"
188 fi
189 if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2; then
190         error "WIM image count not correct"
191 fi
192
193 echo "Testing appending WIM image with existing name (this should generate errors)"
194 if imagex append dir2 dir.wim; then
195         error "Adding duplicate image name didn't fail"
196 fi
197 echo "Testing appending WIM image with new name"
198 if ! imagex append dir2 dir.wim "newname"; then
199         error "Appending WIM image failed"
200 fi
201 echo "Testing appending WIM image with integrity check"
202 if ! imagex append dir2 dir.wim "newname2" --check; then
203         error "Appending WIM image failed"
204 fi
205 if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
206         error "Integrity table not set correctly on image append"
207 fi
208 echo "Testing appending WIM image with no integrity check"
209 if ! imagex append dir2 dir.wim "newname3"; then
210         error "Appending WIM image failed"
211 fi
212 if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "no"; then
213         error "WIM integrity table not removed"
214 fi
215 # 5 images at this point
216 if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 5; then
217         error "WIM does not contain the expected 5 images"
218 fi
219 echo "Testing deleting first WIM image"
220 if ! imagex delete dir.wim 1; then
221         error "Failed to delete WIM image"
222 fi
223 if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 4; then
224         error "WIM image not deleted correctly"
225 fi
226 echo "Testing deleting last WIM image"
227 if ! imagex delete dir.wim 4; then
228         error "Failed to delete WIM image"
229 fi
230 if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then
231         error "WIM image not deleted correctly"
232 fi
233 echo "Testing deleting invalid WIM image (this should generate errors)"
234 if imagex delete dir.wim 4; then
235         error "Expected to fail to delete non-existent WIM image"
236 fi
237 if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then
238         error "Image count changed even though we intentionally failed to delete an image"
239 fi
240 echo "Testing deleting all WIM images"
241 if ! imagex delete dir.wim all; then
242         error "Failed to delete all images from WIM"
243 fi
244 if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 0; then
245         error "Couldn't delete all WIM images correctly"
246 fi
247 echo "Testing appending directory to empty WIM and making it bootable"
248 if ! imagex append dir dir.wim "myname" "mydesc" --check --boot; then
249         error "Couldn't append named, described, bootable image to empty WIM with integrity check"
250 fi
251 if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
252         error "Integrity check not found"
253 fi
254 if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
255         error "Bootable image not set correctly"
256 fi
257 echo "Testing appending non-directory (should generate errors)"
258 if imagex append dir.wim dir.wim; then
259         error "Incorrectly succeeded to append non-directory to WIM"
260 fi
261 echo "Testing appending non-existent file (should generate errors)"
262 if imagex append SOME_NONEXISTENT_FILE dir.wim; then
263         error "Incorrectly succeeded to append non-existent file to WIM"
264 fi
265 if [ `id -u` != 0 ]; then
266         echo "Testing appending directory containing unreadable file (should generate errors)"
267         mkdir -p dir3
268         echo 1 > dir3/file
269         chmod -r dir3/file
270         if imagex append dir3 dir.wim; then
271                 error "Incorrectly succeeded in capturing directory with unreadable file"
272         fi
273 fi
274 rm -rf dir3 dir.wim
275
276 # Applying multiple images, applying with hardlinks/symlinks
277
278 echo "Testing application of multiple images"
279 if ! imagex capture dir dir.wim; then
280         error "Failed to prepare test WIM"
281 fi
282 if ! imagex append dir dir.wim "myname"; then
283         error "Failed to append image to test WIM"
284 fi
285 if ! imagex apply dir.wim all tmp; then
286         error "Applying multiple images failed"
287 fi
288 if ! diff -q -r tmp/dir tmp/myname || ! diff -q -r dir tmp/dir; then
289         error "Recursive diff of applied WIM with original directory failed"
290 fi
291 if test "`stat -c %h tmp/dir/lz.c`" != 1; then
292         error "Incorrect link count on extracted file"
293 fi
294 if test "`stat -c %h tmp/myname/lz.c`" != 1; then
295         error "Incorrect link count on extracted file"
296 fi
297 if test "`stat -c %i tmp/myname/lz.c`" = "`stat -c %i tmp/dir/lz.c`"; then
298         error "Incorrect inode number"
299 fi
300 rm -rf tmp
301 echo "Testing application of multiple images with hardlinks"
302 if ! imagex apply dir.wim all tmp --hardlink; then
303         error "Failed to apply multiple images with cross-image hardlinks"
304 fi
305 if ! diff -q -r tmp/dir tmp/myname || ! diff -q -r dir tmp/dir; then
306         error "Recursive diff of applied WIM with original directory failed"
307 fi
308 if test "`stat -c %h tmp/dir/lz.c`" != 2; then
309         error "Incorrect link count on extracted file"
310 fi
311 if test "`stat -c %h tmp/myname/lz.c`" != 2; then
312         error "Incorrect link count on extracted file"
313 fi
314 if test "`stat -c %i tmp/myname/lz.c`" != "`stat -c %i tmp/dir/lz.c`"; then
315         error "Incorrect inode number"
316 fi
317 rm -rf tmp
318
319 echo "Testing application of single image containing identical files"
320 if ! imagex apply dir.wim 1 tmp; then
321         error "Failed to apply WIM"
322 fi
323 if test "`stat -c %h tmp/subdir/hello`" != 2; then
324         error "Incorrect link count on extracted file"
325 fi
326 if test "`stat -c %h tmp/subdir/hello2`" != 1; then
327         error "Incorrect link count on extracted file"
328 fi
329 if test "`stat -c %i tmp/subdir/hello`" = "`stat -c %i tmp/subdir/hello2`"; then
330         error "Inode numbers on non-hard-linked files are the same"
331 fi
332 if test "`stat -c %i tmp/subdir/hello`" != "`stat -c %i tmp/subdir/hellolink`"; then
333         error "Inode numbers on hard-linked files are different"
334 fi
335 rm -rf tmp
336
337 echo "Testing application of single image containing identical files with hardlinks"
338 if ! imagex apply dir.wim 1 tmp --hardlink; then
339         error "Failed to apply WIM"
340 fi
341 if test "`stat -c %h tmp/subdir/hello`" != 3; then
342         error "Incorrect link count on extracted file"
343 fi
344 if test "`stat -c %h tmp/subdir/hello2`" != 3; then
345         error "Incorrect link count on extracted file"
346 fi
347 if test "`stat -c %i tmp/subdir/hello`" != "`stat -c %i tmp/subdir/hello2`"; then
348         error "Hard link set does not share inode number"
349 fi
350 if test "`stat -c %i tmp/subdir/hello`" != "`stat -c %i tmp/subdir/hellolink`"; then
351         error "Hard link set does not share inode number"
352 fi
353 rm -rf tmp
354
355 echo "Testing application of single image containing identical files with symlinks"
356 if ! imagex apply dir.wim 1 tmp --symlink; then
357         error "Failed to apply WIM"
358 fi
359 if test "`stat -c %h tmp/subdir/hello`" != 1; then
360         error "Incorrect link count on extracted file"
361 fi
362 if test "`stat -c %h tmp/subdir/hello2`" != 1; then
363         error "Incorrect link count on extracted file"
364 fi
365 if test "`stat -c %i tmp/subdir/hello`" = "`stat -c %i tmp/subdir/hello2`"; then
366         error "Incorrect inode number"
367 fi
368 if ! test -L tmp/subdir/hello -o -L tmp/subdir/hello2 -o -L tmp/subdir/hellolink; then
369         error "Expected symlinks, but found non-symlinks"
370 fi
371 rm -rf dir.wim tmp
372
373
374 # imagex split, imagex join
375
376 echo "Creating random files to test WIM splitting on"
377 mkdir tmp
378 for i in `seq 1 100`; do
379         dd if=/dev/urandom of=tmp/file$i bs=4096 count=10 &> /dev/null
380 done
381 for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
382         echo "Using flag $flag"
383         if ! imagex capture tmp tmp.wim $flag; then
384                 error "Failed to capture test WIM"
385         fi
386         echo "Splitting WIM into 1 MiB chunks"
387         if ! imagex split tmp.wim tmp.swm 1; then
388                 error "Failed to split WIM"
389         fi
390         echo "Verifying the split WIMs (some errors expected)"
391         if test "`imagex_info tmp.swm | grep 'Part Number' | awk '{print $3}'`" != "1/4"; then
392                 error "Part number of split WIM not correct"
393         fi
394         if ! imagex dir tmp.swm > /dev/null; then
395                 error "Failed to list files in split WIM"
396         fi
397         if ! test -e tmp2.swm; then
398                 error "Could not find split-WIM part 2"
399         fi
400         if imagex dir tmp2.swm > /dev/null; then
401                 error "Listed files in part 2 of split WIM (this should have failed)"
402         fi
403
404         # Unsupported, should fail
405         if imagex_info tmp.swm --boot 0; then
406                 error "Should not have been able to change boot index of split WIM"
407         fi
408         echo "Joining the split WIMs and applying the result"
409         if ! imagex join tmp2.wim tmp*.wim; then
410                 error "Failed to join split WIMs"
411         fi
412         if ! imagex apply tmp2.wim tmp2; then
413                 error "Failed to apply joined split WIM"
414         fi
415         if ! imagex apply tmp.wim tmp3; then
416                 error "Failed to apply test WIM"
417         fi
418         if ! diff -q -r tmp tmp2 || ! diff -q -r tmp tmp3; then
419                 error "Recursive diff of applied joined split WIM with original directory failed"
420         fi
421         rm -f *.wim *.swm
422         rm -rf tmp2 tmp3
423 done
424 rm -rf tmp
425
426 # imagex export
427 echo "Testing export of single image to new WIM"
428 if ! imagex capture dir dir.wim; then
429         error "Failed to capture test WIM"
430 fi
431 if ! imagex append dir2 dir.wim; then
432         error "Failed to append image to test WIM"
433 fi
434 if ! imagex export dir.wim dir new.wim; then
435         error "Failed to export single image to new WIM"
436 fi
437 if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 1; then
438         error "Exporting single image to new WIM wasn't done correctly"
439 fi
440 echo "Testing export of single image to existing WIM"
441 if ! imagex export dir.wim dir2 new.wim; then
442         error "Failed to export single image to existing WIM"
443 fi
444 if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then
445         error "Exporting single image to existing WIM wasn't done correctly"
446 fi
447 echo "Testing export of single image to existing WIM using wrong compression type"
448 if imagex export dir.wim dir2 new.wim newname --compress=maximum; then
449         error "Successfully exported image using wrong compression type"
450 fi
451 rm -f new.wim
452 echo "Testing export of multiple images to new WIM"
453 if ! imagex export dir.wim all new.wim; then
454         error "Failed to export multiple images to new WIM"
455 fi
456 if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then
457         error "Exporting multiple images to new WIM wasn't done correctly"
458 fi
459 if ! imagex capture dir2 new.wim newname; then
460         error "Failed to capture test WIM"
461 fi
462 echo "Testing export of multiple images to existing WIM"
463 if ! imagex export dir.wim all new.wim; then
464         error "Failed to export multiple images to existing WIM"
465 fi
466 echo "Testing export of multiple images to existing WIM with --boot"
467 if ! imagex capture dir2 new.wim newname; then
468         error "Failed to capture test WIM"
469 fi
470 if ! imagex_info dir.wim --boot 1; then
471         error "Failed to set boot index on test WIM"
472 fi
473 if ! imagex export dir.wim all new.wim --boot; then
474         error "Failed to export multiple images to existing WIM with bootable image"
475 fi
476 echo "Testing export of multiple images to existing WIM with --boot, but no bootable image (errors expected)"
477 if ! imagex capture dir2 new.wim newname; then
478         error "Failed to capture test WIM"
479 fi
480 if ! imagex_info dir.wim --boot 0; then
481         error "Failed to clear boot index on test WIM"
482 fi
483 if imagex export dir.wim all new.wim --boot; then
484         error "Successfully exported multiple images with --boot but with no bootable images"
485 fi
486
487 # Test exporting an image to another WIM, then applying it.
488 # We try with 5 different combinations of compression types to make sure we go
489 # through all paths in the resource-handling code.
490 for i in `seq 1 3`; do
491         case $i in
492         1)
493                 cflag1="--compress=none";
494                 cflag2="--compress=none";
495                 ;;
496         2)
497                 cflag1="--compress=xpress";
498                 cflag2="--compress=xpress";
499                 ;;
500         3)
501                 cflag1="--compress=xpress"
502                 cflag2="--compress=lzx"
503                 ;;
504         4)
505                 cflag1="--compress=none"
506                 cflag2="--compress=xpress"
507                 ;;
508         5)
509                 cflag1="--compress=xpress"
510                 cflag2="--compress=none"
511                 ;;
512         esac
513         echo "Testing exporting then applying an image (\"$cflag1\" => \"$cflag2\")"
514         rm -rf dir.wim new.wim tmp tmp2
515         imagex capture dir dir.wim $cflag1
516         imagex capture dir2 dir2.wim $cflag2
517         imagex export dir.wim dir dir2.wim
518         imagex apply dir.wim dir tmp
519         if ! imagex apply dir2.wim dir tmp2; then
520                 error "Failed to apply image that was exported to a WIM"
521         fi
522         if ! diff -r tmp tmp2; then
523                 error "Image that was exported to a WIM was not applied correctly"
524         fi
525 done
526
527 echo "**********************************************************"
528 echo "                 Basic imagex tests passed                "
529 echo "**********************************************************"
530 cleanup