From: Eric Biggers Date: Sun, 2 Sep 2012 05:14:58 +0000 (-0500) Subject: Test suite and mount updates X-Git-Tag: v1.0.1~4 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=54193a504d8dcf1e2dfae727c76cd1b44884518b Test suite and mount updates --- diff --git a/Makefile.am b/Makefile.am index f05e58dd..2e188386 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,6 +91,7 @@ EXTRA_DIST = \ build-aux/strip_fPIC.sh \ debian \ programs/install.cmd + tests/common_tests.sh pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = wimlib.pc @@ -115,8 +116,13 @@ man1_MANS = \ $(man1_MANS): config.status -check_PROGRAMS = tests/ntfs-cmp -tests_ntfs_cmp_SOURCES = tests/ntfs-cmp.c -dist_check_SCRIPTS = tests/test-imagex tests/test-imagex-ntfs +check_PROGRAMS = tests/tree-cmp +tests_tree_cmp_SOURCES = tests/tree-cmp.c + +dist_check_SCRIPTS = tests/test-imagex \ + tests/test-imagex-mount \ + tests/test-imagex-capture_and_apply \ + tests/test-imagex-ntfs + TESTS = $(dist_check_SCRIPTS) diff --git a/src/mount.c b/src/mount.c index 6f50a4e5..5b1e09e3 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1376,6 +1376,31 @@ static int wimfs_readlink(const char *path, char *buf, size_t buf_len) return ret; } +/* Creation time, write time, access time */ +static void +dentry_link_group_set_times(struct dentry *dentry, u64 times[3]) +{ + struct dentry *cur = dentry; + do { + if (times[0]) + dentry->creation_time = times[0]; + if (times[1]) + dentry->last_write_time = times[1]; + if (times[2]) + dentry->last_access_time = times[2]; + } while ((cur = container_of(dentry->link_group_list.next, + struct dentry, + link_group_list)) != dentry); +} + +static void +dentry_link_group_update_times(struct dentry *dentry) +{ + u64 now = get_wim_timestamp(); + u64 times[3] = {now, now, now}; + dentry_link_group_set_times(dentry, times); +} + /* Close a file. */ static int wimfs_release(const char *path, struct fuse_file_info *fi) { @@ -1388,12 +1413,6 @@ static int wimfs_release(const char *path, struct fuse_file_info *fi) return 0; } - if (flags_writable(fi->flags) && fd->dentry) { - u64 now = get_wim_timestamp(); - fd->dentry->last_access_time = now; - fd->dentry->last_write_time = now; - } - return close_wimlib_fd(fd); } @@ -1655,7 +1674,7 @@ static int wimfs_truncate(const char *path, off_t size) ret = extract_resource_to_staging_dir(dentry, stream_idx, <e, size); } - dentry_update_all_timestamps(dentry); + dentry_link_group_update_times(dentry); return ret; } @@ -1698,18 +1717,20 @@ static int wimfs_utimens(const char *path, const struct timespec tv[2]) struct dentry *dentry = get_dentry(w, path); if (!dentry) return -ENOENT; + u64 times[3] = {0, 0, 0}; if (tv[0].tv_nsec != UTIME_OMIT) { if (tv[0].tv_nsec == UTIME_NOW) - dentry->last_access_time = get_wim_timestamp(); + times[2] = get_wim_timestamp(); else - dentry->last_access_time = timespec_to_wim_timestamp(&tv[0]); + times[2] = timespec_to_wim_timestamp(&tv[0]); } if (tv[1].tv_nsec != UTIME_OMIT) { if (tv[1].tv_nsec == UTIME_NOW) - dentry->last_write_time = get_wim_timestamp(); + times[1] = get_wim_timestamp(); else - dentry->last_write_time = timespec_to_wim_timestamp(&tv[1]); + times[1] = timespec_to_wim_timestamp(&tv[1]); } + dentry_link_group_set_times(dentry, times); return 0; } @@ -1736,6 +1757,12 @@ static int wimfs_write(const char *path, const char *buf, size_t size, if (ret == -1) return -errno; + if (fd->dentry) { + u64 now = get_wim_timestamp(); + u64 times[3] = {0, now, now}; + dentry_link_group_set_times(fd->dentry, times); + } + return ret; } @@ -1936,6 +1963,7 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir, /* Read-only mount */ strcat(optstring, ",ro"); } + strcat(optstring, ",subtype=wimfs,attr_timeout=0"); argv[argc] = NULL; #ifdef ENABLE_DEBUG diff --git a/tests/common_tests.sh b/tests/common_tests.sh new file mode 100644 index 00000000..6e585a8a --- /dev/null +++ b/tests/common_tests.sh @@ -0,0 +1,71 @@ + +msg "nothing" +do_test "" + +msg "a single file" +do_test "echo 1 > file" + +msg "a single directory" +do_test "mkdir dir" + +msg "subdirectory with file" +do_test "mkdir dir; echo 1 > dir/file" + +msg "empty file" +do_test "echo -n > empty_file" + +msg "two empty files" +do_test "echo -n > empty_file_1; echo -n > empty_file_2" + +msg "hard link in same directory" +do_test "echo 1 > file; ln file link" + +msg "hard link between empty files" +do_test "echo -n > empty_file; ln empty_file link" + +msg "relative symbolic link" +do_test "echo 1 > file; ln -s file symlink" + +msg "absolute symbolic link" +do_test "echo 1 > file; ln -s /some/absolute/target symlink" + +msg "large file" +do_test "dd if=/dev/zero of=file bs=4096 count=10 &> /dev/null" + +msg "many nested directories" +do_test 'mkdir dir; mkdir dir/subdir; mkdir dir/subdir/subdir2; mkdir dir/subdir/subdir3' + +msg "identical files and symlinks in subdirectory" +do_test 'mkdir dir; + echo 888 > dir/file; + echo 888 > dir/idfile2; + ln -s ../dir dir/circle; ln -s file dir/filelink' + +msg "hard link group and identical files not hard linked" +do_test 'echo 888 > file; + echo 888 > file2; + ln file link; + ln file link2; + echo 888 > file3' + +msg "C source code of wimlib" +do_test 'cp $srcdir/src/*.{c,h} .' + +msg "tons of random stuff" +do_test 'echo -n 8 > file; + ln file hardlink; + ln -s hardlink symlink; + echo -n 8 > identical file; + dd if=/dev/urandom of=randomfile bs=4096 count=10 &>/dev/null; + mkdir dir; + mkdir anotherdir; + cp file anotherdir; + ln file anotherdir/anotherhardlink; + ln -s .. anotherdir/anothersymlink; + ln -s anothersymlink anotherdir/symlinktosymlink; + echo -n 33 > anotherfile; + echo -n > emptyfile; + mkdir dir/subdir; + ln file dir/subdir/file; + echo -n 8 > dir/subdir/file2; + ln dir/subdir/file dir/subdir/link;' diff --git a/tests/test-imagex b/tests/test-imagex index 36e02534..dc67da2a 100755 --- a/tests/test-imagex +++ b/tests/test-imagex @@ -10,13 +10,15 @@ cd tests imagex() { echo "imagex $@" - ../imagex $@ + ../imagex "$@" > /dev/null +} + +imagex_info() { + echo "imagex info $@" + ../imagex info "$@" } cleanup() { - if [ -d tmp ] && mountpoint tmp > /dev/null; then - fusermount -u tmp > /dev/null; - fi rm -rf dir* tmp* *.wim *.swm } trap cleanup exit @@ -55,8 +57,8 @@ for comp_type in None LZX XPRESS; do if ! imagex apply dir.wim tmp; then error "'imagex apply' failed" fi - if ! test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "$comp_type"; then - error "'imagex info' didn't report the compression type correctly" + if ! test "`imagex_info dir.wim | grep Compression | awk '{print $2}'`" = "$comp_type"; then + error "'imagex_info' didn't report the compression type correctly" fi if ! diff -q -r dir tmp; then error "Recursive diff of extracted directory with original failed" @@ -84,38 +86,38 @@ done echo "Testing capture of WIM with default name and description" imagex capture dir dir.wim -if ! test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "dir"; then +if ! test "`imagex_info dir.wim | grep Name | awk '{print $2}'`" = "dir"; then error "WIM name not set correctly" fi -if ! test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = ""; then +if ! test "`imagex_info dir.wim | grep Description | awk '{print $2}'`" = ""; then error "WIM description not set correctly" fi echo "Testing capture of WIM with default boot flag" imagex capture dir dir.wim -if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then +if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then error "WIM boot flag not set correctly" fi echo "Testing changing image bootable flag" -if ! imagex info dir.wim 1 --boot; then +if ! imagex_info dir.wim 1 --boot; then error "Failed to change bootable image" fi -if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then +if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then error "Bootable image not changed correctly" fi echo "Testing changing image bootable flag" -if ! imagex info dir.wim 0 --boot; then +if ! imagex_info dir.wim 0 --boot; then error "Failed to reset bootable image" fi -if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then +if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then error "Bootable image not reset correctly" fi echo "Testing changing image bootable flag to invalid image (this should generate errors)" -if imagex info dir.wim 2 --boot; then +if imagex_info dir.wim 2 --boot; then error "Succeeded in changing bootable image to invalid number" fi -if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then +if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then error "Boot flag was changed even though the change command was supposed to fail" fi rm -rf dir.wim tmp @@ -124,30 +126,30 @@ echo "Testing capture of WIM with name and description" if ! imagex capture dir dir.wim "myname" "mydesc"; then error "Failed to capture WIM with specified name and description" fi -if ! test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "myname"; then +if ! test "`imagex_info dir.wim | grep Name | awk '{print $2}'`" = "myname"; then error "WIM name not set correctly" fi -if ! test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "mydesc"; then +if ! test "`imagex_info dir.wim | grep Description | awk '{print $2}'`" = "mydesc"; then error "WIM name not set correctly" fi echo "Testing printing WIM lookup table" -if ! imagex info --lookup-table dir.wim > /dev/null; then +if ! imagex_info --lookup-table dir.wim > /dev/null; then error "Failed to print WIM lookup table" fi echo "Testing printing WIM header" -if ! imagex info --header dir.wim > /dev/null; then +if ! imagex_info --header dir.wim > /dev/null; then error "Failed to print WIM header" fi echo "Testing printing WIM XML info" -if ! imagex info --xml dir.wim > /dev/null; then +if ! imagex_info --xml dir.wim > /dev/null; then error "Failed to print WIM XML data" fi echo "Testing extracting WIM XML info" -if ! imagex info --extract-xml=dir.xml dir.wim; then +if ! imagex_info --extract-xml=dir.xml dir.wim; then error "Failed to extract WIM XML data" fi echo "Testing printing WIM metadata" -if ! imagex info --metadata dir.wim > /dev/null; then +if ! imagex_info --metadata dir.wim > /dev/null; then error "Failed to print WIM metadata" fi rm -rf dir.wim tmp dir.xml @@ -156,7 +158,7 @@ echo "Testing capture of bootable WIM" if ! imagex capture dir dir.wim --boot; then error "Failed to capture bootable WIM" fi -if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then +if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then error "Boot flag on bootable WIM not set correctly" fi rm -rf dir.wim tmp @@ -167,7 +169,7 @@ echo "Testing capture of WIM with integrity table" if ! imagex capture dir dir.wim --check; then error "Failed to capture WIM with integrity table" fi -if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then +if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then error "Integrity table on WIM not made" fi if ! imagex apply --check dir.wim tmp; then @@ -185,7 +187,7 @@ imagex capture dir dir.wim if ! imagex append dir2 dir.wim; then error "Appending WIM image failed" fi -if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2; then +if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2; then error "WIM image count not correct" fi @@ -201,56 +203,56 @@ echo "Testing appending WIM image with integrity check" if ! imagex append dir2 dir.wim "newname2" --check; then error "Appending WIM image failed" fi -if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then +if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then error "Integrity table not set correctly on image append" fi echo "Testing appending WIM image with no integrity check" if ! imagex append dir2 dir.wim "newname3"; then error "Appending WIM image failed" fi -if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "no"; then +if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "no"; then error "WIM integrity table not removed" fi # 5 images at this point -if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 5; then +if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 5; then error "WIM does not contain the expected 5 images" fi echo "Testing deleting first WIM image" if ! imagex delete dir.wim 1; then error "Failed to delete WIM image" fi -if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 4; then +if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 4; then error "WIM image not deleted correctly" fi echo "Testing deleting last WIM image" if ! imagex delete dir.wim 4; then error "Failed to delete WIM image" fi -if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then +if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then error "WIM image not deleted correctly" fi echo "Testing deleting invalid WIM image (this should generate errors)" if imagex delete dir.wim 4; then error "Expected to fail to delete non-existent WIM image" fi -if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then +if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then error "Image count changed even though we intentionally failed to delete an image" fi echo "Testing deleting all WIM images" if ! imagex delete dir.wim all; then error "Failed to delete all images from WIM" fi -if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 0; then +if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 0; then error "Couldn't delete all WIM images correctly" fi echo "Testing appending directory to empty WIM and making it bootable" if ! imagex append dir dir.wim "myname" "mydesc" --check --boot; then error "Couldn't append named, described, bootable image to empty WIM with integrity check" fi -if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then +if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then error "Integrity check not found" fi -if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then +if ! test "`imagex_info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then error "Bootable image not set correctly" fi echo "Testing appending non-directory (should generate errors)" @@ -369,135 +371,6 @@ if ! test -L tmp/subdir/hello -o -L tmp/subdir/hello2 -o -L tmp/subdir/hellolink fi rm -rf dir.wim tmp -# imagex mount - -for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do - echo "Using flag $flag" - echo "Testing mounting WIM read-only" - if ! imagex capture dir dir.wim $flag; then - error "Failed to capture WIM" - fi - mkdir tmp - if ! imagex mount dir.wim dir tmp; then - error "Failde to mount test WIM read-only" - fi - echo "Testing extracting file from mounted read-only WIM" - if ! cp tmp/lz.c lz.c; then - error "Failed to extract file from read-only mounted WIM" - fi - if ! diff -q dir/lz.c lz.c; then - error "Extracted file does not match copy in mounted WIM" - fi - if ! diff -q tmp/lz.c dir/lz.c; then - error "Extractef file does not match original" - fi - rm -f lz.c - echo "Testing modifying mounted read-only WIM (should fail)" - if rm tmp/lz.c; then - error "Removing file from read-only mounted WIM didn't fail" - fi - if touch tmp/newfile; then - error "Creating file on read-only mounted WIM didn't fail" - fi - if echo 3 > tmp/lz.c; then - error "Writing to file on read-only mounted WIM didn't fail" - fi - echo "Testing diff of mounted read-only WIM with original directory" - if ! diff -q -r tmp dir; then - error "Recursive diff of read-only mounted WIM with original directory failed" - fi - echo "Testing unmount of read-only filesystem" - if ! imagex unmount tmp; then - error "Unmounting read-only WIM failed" - fi - echo "Testing unmount of read-only filesystem with --commit given" - if ! imagex mount dir.wim dir tmp; then - error "Failed to re-mount WIM read-only" - fi - if ! imagex unmount tmp --commit; then - error "Failed to unmount read-only WIM with --commit flag (should be ignored)" - fi - rm -rf tmp dir.wim -done - -# imagex mountrw -echo "Testing mounting WIM read-write" -if ! imagex capture dir dir.wim; then - error "Failed to capture WIM" -fi -mkdir tmp -if ! imagex mountrw dir.wim dir tmp; then - error "Failed to mount test WIM read-write" -fi -echo "Testing unmounting WIM unmodified" -if ! imagex unmount tmp; then - error "Failed to unmount test WIM unmodified" -fi -echo "Testing unmounting WIM unmodified with --commit and --check" -if ! imagex mountrw dir.wim dir tmp; then - error "Failed to re-mount test WIM read-write" -fi -if ! imagex unmount tmp --commit --check; then - error "Failed to unmount read-write mounted WIM with changes commited (no changes made)" -fi -echo "Testing removing file from mounted WIM" -if ! imagex mountrw dir.wim dir tmp; then - error "Failed to re-mount test WIM read-write" -fi -if ! rm tmp/lz.c; then - error "Failed to remove file from read-write mounted WIM" -fi -if test -f tmp/lz.c; then - error "Removing file from read-write mounted WIM failed" -fi -echo "Testing making directory in mounted WIM" -if ! mkdir tmp/newdir; then - error "Failed to make directory in read-write mounted WIM" -fi -if ! test -d tmp/newdir; then - error "Making directory in read-write mounted WIM failed" -fi -echo "Testing making new empty file in mounted WIM" -if ! touch tmp/newdir/empty_file; then - error "Could not create new empty file in read-write mounted WIM" -fi -if ! test -f tmp/newdir/empty_file; then - error "New empty file not created correctly in read-write mounted WIM" -fi -if ! test "`stat -c %s tmp/newdir/empty_file`" = 0; then - error "New empty file in read-write mounted WIM is not empty" -fi -echo "Testing making new non-empty file in mounted WIM" -if ! dd if=/dev/zero of=tmp/newdir/zeroes1 bs=1 count=4096; then - error "Failed to make new non-empty file in mounted WIM" -fi -if ! dd if=/dev/zero of=tmp/newdir/zeroes2 bs=4096 count=1; then - error "Failed to make new non-empty file in mounted WIM" -fi -if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then - error "New files in mounted WIM not made correctly" -fi -echo "Unmounting WIM with changes committed and --check" -if ! imagex unmount tmp --commit --check; then - error "Failed to unmount read-write mounted WIM" -fi -if test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" != "yes"; then - error "Integrity information was not included" -fi -rm -rf tmp -if ! imagex apply dir.wim tmp; then - error "Failed to apply WIM we had previously mounted read-write" -fi -if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then - error "The new non-empty files we made in the read-write mounted WIM were not extracted correctly" -fi -if test `stat -c %s tmp/newdir/empty_file` != 0; then - error "The new empty file we made in the read-write mounted WIM was not extracted correctly" -fi -if test `stat -c %s tmp/newdir/zeroes1` != 4096; then - error "The new non-empty files we made in the read-write mounted WIM were not extracted correctly" -fi -rm -rf tmp dir.wim # imagex split, imagex join @@ -516,7 +389,7 @@ for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do error "Failed to split WIM" fi echo "Verifying the split WIMs (some errors expected)" - if test "`imagex info tmp.swm | grep 'Part Number' | awk '{print $3}'`" != "1/4"; then + if test "`imagex_info tmp.swm | grep 'Part Number' | awk '{print $3}'`" != "1/4"; then error "Part number of split WIM not correct" fi if ! imagex dir tmp.swm > /dev/null; then @@ -530,7 +403,7 @@ for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do fi # Unsupported, should fail - if imagex info tmp.swm --boot 0; then + if imagex_info tmp.swm --boot 0; then error "Should not have been able to change boot index of split WIM" fi echo "Joining the split WIMs and applying the result" @@ -562,14 +435,14 @@ fi if ! imagex export dir.wim dir new.wim; then error "Failed to export single image to new WIM" fi -if test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" != 1; then +if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 1; then error "Exporting single image to new WIM wasn't done correctly" fi echo "Testing export of single image to existing WIM" if ! imagex export dir.wim dir2 new.wim; then error "Failed to export single image to existing WIM" fi -if test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then +if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then error "Exporting single image to existing WIM wasn't done correctly" fi echo "Testing export of single image to existing WIM using wrong compression type" @@ -581,7 +454,7 @@ echo "Testing export of multiple images to new WIM" if ! imagex export dir.wim all new.wim; then error "Failed to export multiple images to new WIM" fi -if test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then +if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then error "Exporting multiple images to new WIM wasn't done correctly" fi if ! imagex capture dir2 new.wim newname; then @@ -595,7 +468,7 @@ echo "Testing export of multiple images to existing WIM with --boot" if ! imagex capture dir2 new.wim newname; then error "Failed to capture test WIM" fi -if ! imagex info dir.wim --boot 1; then +if ! imagex_info dir.wim --boot 1; then error "Failed to set boot index on test WIM" fi if ! imagex export dir.wim all new.wim --boot; then @@ -605,7 +478,7 @@ echo "Testing export of multiple images to existing WIM with --boot, but no boot if ! imagex capture dir2 new.wim newname; then error "Failed to capture test WIM" fi -if ! imagex info dir.wim --boot 0; then +if ! imagex_info dir.wim --boot 0; then error "Failed to clear boot index on test WIM" fi if imagex export dir.wim all new.wim --boot; then diff --git a/tests/test-imagex-capture_and_apply b/tests/test-imagex-capture_and_apply new file mode 100755 index 00000000..0a53aee0 --- /dev/null +++ b/tests/test-imagex-capture_and_apply @@ -0,0 +1,143 @@ +#!/bin/bash + +# Test capturing and applying a WIM image in the normal (non-NTFS) capture mode +# +# Add in some tests with WIM splitting, joining, and exporting as well. +# +# Test all three compression modes (None, XPRESS, and LZX). +# +# Also, test if the capture configuration file works correctly. + +set -e +srcdir=${srcdir:-.} +srcdir=`realpath $srcdir` +cd tests + +imagex() { + echo "imagex $@" + ../imagex "$@" > /dev/null +} + +imagex_info() { + echo "imagex info $@" + ../imagex info "$@" +} + +init() { + mkdir in.dir out.dir +} + +cleanup() { + rm -rf in.dir out.dir test*.wim test*.swm +} + +error() { + echo "****************************************************************" + echo " Test failure " + echo $* + echo "****************************************************************" + exit 1 +} + +wim_ctype() { + ../imagex info $1 | grep Compression | awk '{print $2}' +} + +do_tree_cmp() { + if ! ./tree-cmp in.dir out.dir; then + if [ -x /usr/bin/tree ]; then + echo "Dumping tree of applied image" + echo "(Note: compression type was $ctype)" + tree out.dir --inodes -F -s --noreport + error 'Information was lost or corrupted while capturing + and then applying a directory tree' + fi + fi +} + +image_name=0 +do_test() { + for ctype in None LZX XPRESS; do + + # Can we capture the WIM, apply it, and get the same result? + cd in.dir + eval "$1" + cd .. + if [ -x /usr/bin/tree -a "$ctype" = "None" ]; then + tree in.dir --inodes -F -s --noreport + fi + if ! imagex capture in.dir test.wim --compress=$ctype; then + error "Failed to capture directory tree into a WIM" + fi + if ! imagex apply test.wim 1 out.dir; then + error "Failed to apply WIM to directory" + fi + if [ `wim_ctype test.wim` != $ctype ]; then + error "'imagex info' didn't report the compression type on the captured WIM correctly" + fi + do_tree_cmp + rm -rf out.dir/* + + # Can we split the WIM, apply the split WIM, join the split WIM, + # and apply the joined WIM, and get the same results every time? + if ! imagex split test.wim test.swm 0.01M; then + error "Failed to split WIM" + fi + if ! imagex apply test.swm 1 out.dir --ref "test*.swm" ; then + error "Failed to apply split WIM" + fi + do_tree_cmp + rm -rf out.dir/* test.wim + if ! imagex join test.wim test*.swm; then + error "Failed to join split WIM" + fi + if ! imagex apply test.wim out.dir; then + error "Failed to apply joined WIM" + fi + do_tree_cmp + rm -rf out.dir/* + + # Can we export the image to another WIM, apply it, and get the + # same results? + (( image_name++ )) || true + if ! imagex export test.wim 1 test2.wim "$image_name"; then + error "Failed to export WIM image" + fi + + if ! imagex apply test2.wim "$image_name" out.dir; then + error "Failed to apply exported WIM image" + fi + do_tree_cmp + + rm -rf out.dir/* in.dir/* test.wim test*.swm + + done +} + +msg() { + echo "--------------------------------------------------------------------" + echo "Testing image capture and application of directory containing $1" + echo "--------------------------------------------------------------------" +} + +cleanup +init + +. common_tests.sh + +# Make sure exclusion list works +msg "Testing default capture configuration file" +touch in.dir/hiberfil.sys +mkdir -p "in.dir/System Volume Information/subdir" +imagex capture in.dir test.wim +imagex apply test.wim out.dir +if [ -e out.dir/hiberfil.sys -o -e "out.dir/System Volume Information" ]; then + error "Files were not excluded from capture as expected" +fi +rm -rf out.dir/* in.dir/* + +cleanup + +echo "**********************************************************" +echo " imagex capture/apply tests passed " +echo "**********************************************************" diff --git a/tests/test-imagex-mount b/tests/test-imagex-mount new file mode 100755 index 00000000..cd3317af --- /dev/null +++ b/tests/test-imagex-mount @@ -0,0 +1,275 @@ +#!/bin/sh + +# Test WIM mounting + +set -e +srcdir=${srcdir:-.} +srcdir=`realpath $srcdir` +cd tests + +imagex() { + echo "imagex $@" + ../imagex $@ > /dev/null +} + +imagex_info() { + echo "imagex info $@" + ../imagex info "$@" +} + +imagex_mountrw() { + echo "imagex mountrw $@" + ../imagex mountrw --debug "$@" &> mount.log & + while ! mountpoint $2 >& /dev/null; do + sleep 0.01; + done + return 0 +} + +cleanup() { + if mountpoint tmp &> /dev/null; then + fusermount -u tmp > /dev/null; + fi + if mountpoint tmp.mnt &> /dev/null; then + fusermount -u tmp.mnt > /dev/null; + fi + rm -rf dir* tmp* *.wim *.swm empty.wim tmp.orig tmp.mnt \ + tmp.apply mount.log +} +init() { + mkdir dir + cp $srcdir/src/*.c $srcdir/src/*.h dir + mkdir dir/subdir + echo 'hello' > dir/subdir/hello + echo 'hello' > dir/subdir/hello2 + ln dir/subdir/hello dir/subdir/hellolink + echo -n > dir/subdir/empty_file + ln -s hello dir/subdir/rel_symlink + + mkdir dir2 + echo 'testing' > dir2/file + dd if=/dev/zero of=dir2/zeroes bs=4096 count=5 + mkdir tmp.empty tmp.mnt tmp.apply tmp.orig + imagex capture tmp.empty empty.wim +} + +error() { + echo "**********************************************" + echo " Test failure " + echo $* + echo "**********************************************" + exit 1 +} + +cleanup +init + +# imagex mount + +for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do + echo "Using flag $flag" + echo "Testing mounting WIM read-only" + if ! imagex capture dir dir.wim $flag; then + error "Failed to capture WIM" + fi + mkdir tmp + if ! imagex mount dir.wim dir tmp; then + error "Failde to mount test WIM read-only" + fi + echo "Testing extracting file from mounted read-only WIM" + if ! cp tmp/lz.c lz.c; then + error "Failed to extract file from read-only mounted WIM" + fi + if ! diff -q dir/lz.c lz.c; then + error "Extracted file does not match copy in mounted WIM" + fi + if ! diff -q tmp/lz.c dir/lz.c; then + error "Extractef file does not match original" + fi + rm -f lz.c + echo "Testing modifying mounted read-only WIM (should fail)" + if rm tmp/lz.c; then + error "Removing file from read-only mounted WIM didn't fail" + fi + if touch tmp/newfile; then + error "Creating file on read-only mounted WIM didn't fail" + fi + if echo 3 > tmp/lz.c; then + error "Writing to file on read-only mounted WIM didn't fail" + fi + echo "Testing diff of mounted read-only WIM with original directory" + if ! diff -q -r tmp dir; then + error "Recursive diff of read-only mounted WIM with original directory failed" + fi + echo "Testing unmount of read-only filesystem" + if ! imagex unmount tmp; then + error "Unmounting read-only WIM failed" + fi + echo "Testing unmount of read-only filesystem with --commit given" + if ! imagex mount dir.wim dir tmp; then + error "Failed to re-mount WIM read-only" + fi + if ! imagex unmount tmp --commit; then + error "Failed to unmount read-only WIM with --commit flag (should be ignored)" + fi + rm -rf tmp dir.wim +done + +# imagex mountrw +echo "Testing mounting WIM read-write" +if ! imagex capture dir dir.wim; then + error "Failed to capture WIM" +fi +mkdir tmp +if ! imagex mountrw dir.wim dir tmp; then + error "Failed to mount test WIM read-write" +fi +echo "Testing unmounting WIM unmodified" +if ! imagex unmount tmp; then + error "Failed to unmount test WIM unmodified" +fi +echo "Testing unmounting WIM unmodified with --commit and --check" +if ! imagex mountrw dir.wim dir tmp; then + error "Failed to re-mount test WIM read-write" +fi +if ! imagex unmount tmp --commit --check; then + error "Failed to unmount read-write mounted WIM with changes commited (no changes made)" +fi +echo "Testing removing file from mounted WIM" +if ! imagex mountrw dir.wim dir tmp; then + error "Failed to re-mount test WIM read-write" +fi +if ! rm tmp/lz.c; then + error "Failed to remove file from read-write mounted WIM" +fi +if test -f tmp/lz.c; then + error "Removing file from read-write mounted WIM failed" +fi +echo "Testing making directory in mounted WIM" +if ! mkdir tmp/newdir; then + error "Failed to make directory in read-write mounted WIM" +fi +if ! test -d tmp/newdir; then + error "Making directory in read-write mounted WIM failed" +fi +echo "Testing making new empty file in mounted WIM" +if ! touch tmp/newdir/empty_file; then + error "Could not create new empty file in read-write mounted WIM" +fi +if ! test -f tmp/newdir/empty_file; then + error "New empty file not created correctly in read-write mounted WIM" +fi +if ! test "`stat -c %s tmp/newdir/empty_file`" = 0; then + error "New empty file in read-write mounted WIM is not empty" +fi +echo "Testing making new non-empty file in mounted WIM" +if ! dd if=/dev/zero of=tmp/newdir/zeroes1 bs=1 count=4096; then + error "Failed to make new non-empty file in mounted WIM" +fi +if ! dd if=/dev/zero of=tmp/newdir/zeroes2 bs=4096 count=1; then + error "Failed to make new non-empty file in mounted WIM" +fi +if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then + error "New files in mounted WIM not made correctly" +fi +echo "Unmounting WIM with changes committed and --check" +if ! imagex unmount tmp --commit --check; then + error "Failed to unmount read-write mounted WIM" +fi +if test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" != "yes"; then + error "Integrity information was not included" +fi +rm -rf tmp +if ! imagex apply dir.wim tmp; then + error "Failed to apply WIM we had previously mounted read-write" +fi +if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then + error "The new non-empty files we made in the read-write mounted WIM were not extracted correctly" +fi +if test `stat -c %s tmp/newdir/empty_file` != 0; then + error "The new empty file we made in the read-write mounted WIM was not extracted correctly" +fi +if test `stat -c %s tmp/newdir/zeroes1` != 4096; then + error "The new non-empty files we made in the read-write mounted WIM were not extracted correctly" +fi + +# Now do some tests using tar. +do_tree_cmp() { + if ! ./tree-cmp $1 $2; then + if [ -x /usr/bin/tree ]; then + echo "Dumping tree of applied image" + tree $2 --inodes -F -s --noreport + error 'Information was lost or corrupted while capturing + and then applying a directory tree' + fi + fi +} + +msg() { + echo "--------------------------------------------------------------------" + echo "Testing making $1 on read-write mounted WIM" + echo "--------------------------------------------------------------------" +} + +do_test() { + + # Create tree, tar it up, and untar it on an empty WIM image mounted + # read-write + + cp empty.wim test.wim + + cd tmp.orig + eval "$1" + if [ -x /usr/bin/tree ]; then + tree . --inodes -F -s --noreport + fi + tar cf ../test.tar . + cd .. + + if ! imagex_mountrw test.wim tmp.mnt; then + error "Failed to mount WIM read-write" + fi + + cd tmp.mnt + if ! tar xf ../test.tar; then + error "Failed to untar archive on read-write mounted WIM" + fi + cd .. + + # Diff the original tree with the mounted WIM + do_tree_cmp tmp.orig tmp.mnt + + # Clear the mounted WIM and do it again! (We need to test deleting + # stuff as well as creating stuff.) + if ! rm -rf tmp.mnt/*; then + error "Failed to clear mounted WIM" + fi + + cd tmp.mnt + if ! tar xf ../test.tar; then + error "Failed to untar archive on read-write mounted WIM" + fi + cd .. + + # Diff the original tree with the mounted WIM + do_tree_cmp tmp.orig tmp.mnt + + # Unmount the WIM, apply it, and diff the original tree with the applied + # tree + if ! imagex unmount tmp.mnt --commit; then + error "Failed to unmount WIM mounted read-write" + fi + if ! imagex apply test.wim tmp.apply; then + error "Failed to apply WIM we previously had mounted read-write" + fi + do_tree_cmp tmp.orig tmp.apply + rm -rf tmp.orig/* tmp.apply/* +} + +. common_tests.sh + +cleanup + +echo "**********************************************************" +echo " WIM mount tests passed " +echo "**********************************************************" diff --git a/tests/test-imagex-ntfs b/tests/test-imagex-ntfs index 3b4d5a14..cf8b6d1b 100755 --- a/tests/test-imagex-ntfs +++ b/tests/test-imagex-ntfs @@ -9,6 +9,7 @@ # remain mounted. set -e +srcdir=${srcdir:-.} srcdir=`realpath $srcdir` cd tests @@ -88,7 +89,7 @@ do_test() { if [ -x /usr/bin/tree ]; then tree in.mnt --inodes -F -s --noreport fi - if ! ./ntfs-cmp in.mnt out.mnt; then + if ! ./tree-cmp in.mnt out.mnt NTFS; then if [ -x /usr/bin/tree ]; then echo "Dumping tree of applied image" tree out.mnt --inodes -F -s --noreport @@ -100,7 +101,9 @@ do_test() { __do_unmount out.mnt } msg() { - echo "Testing image capture and application of $1" + echo "--------------------------------------------------------------------" + echo "Testing image capture and application of NTFS volume containing $1" + echo "--------------------------------------------------------------------" } cleanup diff --git a/tests/ntfs-cmp.c b/tests/tree-cmp.c similarity index 80% rename from tests/ntfs-cmp.c rename to tests/tree-cmp.c index 338dce56..a596962a 100644 --- a/tests/ntfs-cmp.c +++ b/tests/tree-cmp.c @@ -1,5 +1,16 @@ /* - * A program to compare two mounted NTFS filesystems. + * A program to compare directory trees + * + * There are two modes: + * - Normal mode for any filesystems. We compare file names, contents, + * sizes, modes, access times, and hard links. + * - NTFS mode for NTFS-3g mounted volumes. In this mode we need to + * compare various NTFS-specific attributes such as named data streams + * and DOS names. + * + * Both modes compare hard link groups between the two directory trees. If two + * files are hard linked together in one directory tree, exactly the same two + * files are expected to be hard linked together in the other directory tree. */ #include @@ -31,13 +42,14 @@ typedef uint64_t u64; #else #define DEBUG(format, ...) #endif +static bool ntfs_mode = false; static void difference(const char *format, ...) { va_list va; va_start(va, format); fflush(stdout); - fputs("ntfs-cmp: ", stderr); + fputs("tree-cmp: ", stderr); vfprintf(stderr, format, va); putc('\n', stderr); fflush(stderr); @@ -51,7 +63,7 @@ static void error(const char *format, ...) int err = errno; va_start(va, format); fflush(stdout); - fputs("ntfs-cmp: ", stderr); + fputs("tree-cmp: ", stderr); vfprintf(stderr, format, va); fprintf(stderr, ": %s\n", strerror(err)); va_end(va); @@ -266,8 +278,8 @@ static void special_cmp(const char *file1, const char *file2) } -/* Compares file1 on one NTFS volume to file2 on another NTFS volume. */ -static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len) +/* Recursively compares directory tree rooted at file1 to directory tree rooted at file2 */ +static void tree_cmp(char file1[], int file1_len, char file2[], int file2_len) { struct stat st1, st2; u64 ino_from, ino_to; @@ -283,27 +295,30 @@ static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len) insert_ino(ino_from, st2.st_ino); else if (ino_to != st2.st_ino) difference("Inode number on `%s' is wrong", file2); - if (st1.st_size != st2.st_size) - difference("Sizes of `%s' and `%s' are not the same", - file1, file2); - if (st1.st_mode != st2.st_mode) + if ((st1.st_mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) != + (st2.st_mode & ~(S_IRWXU | S_IRWXG | S_IRWXO))) difference("Modes of `%s' and `%s' are not the same", file1, file2); - if (st1.st_atime != st2.st_atime) + if (S_ISREG(st1.st_mode) && st1.st_size != st2.st_size) + difference("Sizes of `%s' and `%s' are not the same", + file1, file2); + if (ntfs_mode && st1.st_atime != st2.st_atime) difference("Access times of `%s' and `%s' are not the same", file1, file2); if (st1.st_mtime != st2.st_mtime) - difference("Modification times times of `%s' and `%s' are not the same", - file1, file2); + difference("Modification times of `%s' (%x) and `%s' (%x) are " + "not the same", + file1, st1.st_mtime, file2, st2.st_mtime); #if 0 if (st1.st_ctime != st2.st_ctime) difference("Status change times of `%s' and `%s' are not the same", file1, file2); #endif - if (st1.st_nlink != st2.st_nlink) - difference("Link count of `%s' and `%s' are not the same", - file1, file2); - if (strcmp(file1, root1)) + if ((ntfs_mode || S_ISREG(st1.st_mode)) && st1.st_nlink != st2.st_nlink) + difference("Link count of `%s' (%u) and `%s' (%u) " + "are not the same", + file1, st1.st_nlink, file2, st2.st_nlink); + if (ntfs_mode && strcmp(file1, root1) != 0) special_cmp(file1, file2); if (S_ISREG(st1.st_mode)) cmp(file1, file2, st1.st_size); @@ -343,7 +358,7 @@ static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len) { memcpy(file1 + file1_len + 1, name, name_len + 1); memcpy(file2 + file2_len + 1, name, name_len + 1); - ntfs_cmp(file1, file1_len + 1 + name_len, + tree_cmp(file1, file1_len + 1 + name_len, file2, file2_len + 1 + name_len); } @@ -354,21 +369,36 @@ static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len) free(namelist2); file1[file1_len] = '\0'; file2[file2_len] = '\0'; + } else if (!ntfs_mode && S_ISLNK(st1.st_mode)) { + char buf1[4096], buf2[sizeof(buf1)]; + ssize_t ret1, ret2; + ret1 = readlink(file1, buf1, sizeof(buf1)); + if (ret1 == -1) + error("Failed to get symlink target of `%s'", file1); + ret2 = readlink(file2, buf2, sizeof(buf2)); + if (ret2 == -1) + error("Failed to get symlink target of `%s'", file2); + if (ret1 != ret2 || memcmp(buf1, buf2, ret1)) + error("Symlink targets of `%s' and `%s' differ", + file1, file2); } } int main(int argc, char **argv) { - if (argc != 3) { - fprintf(stderr, "Usage: %s DIR1 DIR2", argv[0]); + if (argc != 3 && argc != 4) { + fprintf(stderr, "Usage: %s DIR1 DIR2 [NTFS]", argv[0]); return 2; } + if (argc > 3 && strcmp(argv[3], "NTFS") == 0) + ntfs_mode = true; + char dir1[4096]; char dir2[4096]; strcpy(dir1, argv[1]); strcpy(dir2, argv[2]); root1 = argv[1]; root2 = argv[2]; - ntfs_cmp(dir1, strlen(dir1), dir2, strlen(dir2)); + tree_cmp(dir1, strlen(dir1), dir2, strlen(dir2)); return 0; }