Test suite
authorEric Biggers <ebiggers3@gmail.com>
Tue, 14 Aug 2012 00:20:28 +0000 (19:20 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 14 Aug 2012 00:23:57 +0000 (19:23 -0500)
This commit introduces a primitive test suite for wimlib.  It consists of a
shell script that runs some tests on the 'imagex' program.  Run it with `make
check'; only works with in-tree builds.

As a result of writing the test suite I also fixed two issues:
  mount.c: Allow opening empty files in read-only filesystem
  mount.c: Implement utimens() for WIM filesystem

51 files changed:
Makefile.am
src/mount.c
src/timestamp.h
src/wim.c
tests/dir/comp.c [new symlink]
tests/dir/comp.h [new symlink]
tests/dir/decomp.c [new symlink]
tests/dir/decomp.h [new symlink]
tests/dir/dentry.c [new symlink]
tests/dir/dentry.h [new symlink]
tests/dir/endianness.h [new symlink]
tests/dir/extract.c [new symlink]
tests/dir/header.c [new symlink]
tests/dir/integrity.c [new symlink]
tests/dir/io.h [new symlink]
tests/dir/join.c [new symlink]
tests/dir/lookup_table.c [new symlink]
tests/dir/lookup_table.h [new symlink]
tests/dir/lz.c [new symlink]
tests/dir/lzx-common.c [new symlink]
tests/dir/lzx-comp.c [new symlink]
tests/dir/lzx-decomp.c [new symlink]
tests/dir/lzx.h [new symlink]
tests/dir/modify.c [new symlink]
tests/dir/mount.c [new symlink]
tests/dir/resource.c [new symlink]
tests/dir/security.c [new symlink]
tests/dir/security.h [new symlink]
tests/dir/sha1.c [new symlink]
tests/dir/sha1.h [new symlink]
tests/dir/split.c [new symlink]
tests/dir/subdir/empty_file [new file with mode: 0644]
tests/dir/subdir/identical_file1 [new file with mode: 0644]
tests/dir/subdir/identical_file2 [new file with mode: 0644]
tests/dir/subdir/short_file [new file with mode: 0644]
tests/dir/subdir/zeroes [new file with mode: 0644]
tests/dir/timestamp.h [new symlink]
tests/dir/util.c [new symlink]
tests/dir/util.h [new symlink]
tests/dir/wim.c [new symlink]
tests/dir/wimlib.h [new symlink]
tests/dir/wimlib_internal.h [new symlink]
tests/dir/write.c [new symlink]
tests/dir/xml.c [new symlink]
tests/dir/xml.h [new symlink]
tests/dir/xpress-comp.c [new symlink]
tests/dir/xpress-decomp.c [new symlink]
tests/dir/xpress.h [new symlink]
tests/dir2/imagex.c [new symlink]
tests/dir2/mkwinpeimg [new symlink]
tests/test-imagex [new file with mode: 0755]

index 5f5b12d..58d2367 100644 (file)
@@ -84,7 +84,9 @@ EXTRA_DIST =                  \
        COPYING.LIB             \
        build-aux/strip_fPIC.sh \
        debian                  \
-       programs/install.cmd
+       programs/install.cmd    \
+       tests/dir               \
+       tests/dir2
 
 pkgconfigdir   = @pkgconfigdir@
 pkgconfig_DATA = wimlib.pc
@@ -108,3 +110,7 @@ man1_MANS =                 \
        doc/mkwinpeimg.1
 
 $(man1_MANS): config.status
+
+dist_check_SCRIPTS = tests/test-imagex
+TESTS = $(dist_check_SCRIPTS)
+
index 53a7f36..f3043c2 100644 (file)
@@ -32,6 +32,7 @@
 #include "sha1.h"
 #include "lookup_table.h"
 #include "xml.h"
+#include "timestamp.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/wait.h>
@@ -118,7 +119,11 @@ static int remove_file_or_directory(const char *fpath, const struct stat *sb,
  */
 static inline int delete_staging_dir()
 {
-       return nftw(staging_dir_name, remove_file_or_directory, 10, FTW_DEPTH);
+       int ret;
+       
+       ret = nftw(staging_dir_name, remove_file_or_directory,10, FTW_DEPTH);
+       staging_dir_name = NULL;
+       return ret;
 }
 
 /* Name and message queue descriptors for message queues between the filesystem
@@ -630,10 +635,14 @@ static int wimfs_open(const char *path, struct fuse_file_info *fi)
                }
        } else {
                /* no lookup table entry, so the file must be empty.  Create a
-                * lookup table entry for the file. */
+                * lookup table entry for the file, unless it's a read-only
+                * filesystem.  */
                char *tmpfile_name;
                int fd;
 
+               if (!staging_dir_name) /* Read-only filesystem */
+                       return 0;
+
                lte = new_lookup_table_entry();
                if (!lte)
                        return -ENOMEM;
@@ -981,6 +990,20 @@ static int wimfs_unlink(const char *path)
        return 0;
 }
 
+static int wimfs_utimens(const char *path, const struct timespec tv[2])
+{
+       struct dentry *dentry = get_dentry(w, path);
+       if (!dentry)
+               return -ENOENT;
+       time_t last_access_t = (tv[0].tv_nsec == UTIME_NOW) ? 
+                               time(NULL) : tv[0].tv_sec;
+       dentry->last_access_time = unix_timestamp_to_ms(last_access_t);
+       time_t last_mod_t = (tv[1].tv_nsec == UTIME_NOW) ?  
+                               time(NULL) : tv[1].tv_sec;
+       dentry->last_write_time = unix_timestamp_to_ms(last_mod_t);
+       return 0;
+}
+
 /* Writes to a file in the WIM filesystem. */
 static int wimfs_write(const char *path, const char *buf, size_t size, 
                                off_t offset, struct fuse_file_info *fi)
@@ -1054,6 +1077,7 @@ static struct fuse_operations wimfs_oper = {
        .rmdir    = wimfs_rmdir,
        .truncate = wimfs_truncate,
        .unlink   = wimfs_unlink,
+       .utimens  = wimfs_utimens,
        .write    = wimfs_write,
 };
 
index 819047d..5ad0b35 100644 (file)
 #define intervals_1601_to_1970 (years_1601_to_1970 * intervals_per_year \
                                + leap_years_1601_to_1970 * intervals_per_day)
 
+static inline u64 unix_timestamp_to_ms(time_t t)
+{
+       return (u64)intervals_1601_to_1970 + t * intervals_per_second;
+}
 /* 
  * Returns the number of 100-nanosecond intervals that have elapsed since
  * 12:00 A.M., January 1, 1601 UTC.
  */
 static inline u64 get_timestamp()
 {
-       return (u64)intervals_1601_to_1970 + (u64)time(NULL) * intervals_per_second;
+       return unix_timestamp_to_ms(time(NULL));
 }
 
 /* Converts a timestamp as used in the WIM file to a UNIX timestamp as used in
index 268b381..7328878 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -81,14 +81,14 @@ int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *))
                i = image;
                end = image;
        }
-       do {
+       for (; i <= end; i++) {
                ret = wimlib_select_image(w, i);
                if (ret != 0)
                        return ret;
                ret = visitor(w);
                if (ret != 0)
                        return ret;
-       } while (i++ != end);
+       }
        return 0;
 }
 
diff --git a/tests/dir/comp.c b/tests/dir/comp.c
new file mode 120000 (symlink)
index 0000000..1678379
--- /dev/null
@@ -0,0 +1 @@
+../../src/comp.c
\ No newline at end of file
diff --git a/tests/dir/comp.h b/tests/dir/comp.h
new file mode 120000 (symlink)
index 0000000..b259940
--- /dev/null
@@ -0,0 +1 @@
+../../src/comp.h
\ No newline at end of file
diff --git a/tests/dir/decomp.c b/tests/dir/decomp.c
new file mode 120000 (symlink)
index 0000000..cc67a22
--- /dev/null
@@ -0,0 +1 @@
+../../src/decomp.c
\ No newline at end of file
diff --git a/tests/dir/decomp.h b/tests/dir/decomp.h
new file mode 120000 (symlink)
index 0000000..22a2226
--- /dev/null
@@ -0,0 +1 @@
+../../src/decomp.h
\ No newline at end of file
diff --git a/tests/dir/dentry.c b/tests/dir/dentry.c
new file mode 120000 (symlink)
index 0000000..d864209
--- /dev/null
@@ -0,0 +1 @@
+../../src/dentry.c
\ No newline at end of file
diff --git a/tests/dir/dentry.h b/tests/dir/dentry.h
new file mode 120000 (symlink)
index 0000000..10cc735
--- /dev/null
@@ -0,0 +1 @@
+../../src/dentry.h
\ No newline at end of file
diff --git a/tests/dir/endianness.h b/tests/dir/endianness.h
new file mode 120000 (symlink)
index 0000000..48fd8d3
--- /dev/null
@@ -0,0 +1 @@
+../../src/endianness.h
\ No newline at end of file
diff --git a/tests/dir/extract.c b/tests/dir/extract.c
new file mode 120000 (symlink)
index 0000000..44480bc
--- /dev/null
@@ -0,0 +1 @@
+../../src/extract.c
\ No newline at end of file
diff --git a/tests/dir/header.c b/tests/dir/header.c
new file mode 120000 (symlink)
index 0000000..0a3f05e
--- /dev/null
@@ -0,0 +1 @@
+../../src/header.c
\ No newline at end of file
diff --git a/tests/dir/integrity.c b/tests/dir/integrity.c
new file mode 120000 (symlink)
index 0000000..997d473
--- /dev/null
@@ -0,0 +1 @@
+../../src/integrity.c
\ No newline at end of file
diff --git a/tests/dir/io.h b/tests/dir/io.h
new file mode 120000 (symlink)
index 0000000..32882db
--- /dev/null
@@ -0,0 +1 @@
+../../src/io.h
\ No newline at end of file
diff --git a/tests/dir/join.c b/tests/dir/join.c
new file mode 120000 (symlink)
index 0000000..dcffc6c
--- /dev/null
@@ -0,0 +1 @@
+../../src/join.c
\ No newline at end of file
diff --git a/tests/dir/lookup_table.c b/tests/dir/lookup_table.c
new file mode 120000 (symlink)
index 0000000..a685a89
--- /dev/null
@@ -0,0 +1 @@
+../../src/lookup_table.c
\ No newline at end of file
diff --git a/tests/dir/lookup_table.h b/tests/dir/lookup_table.h
new file mode 120000 (symlink)
index 0000000..fd64815
--- /dev/null
@@ -0,0 +1 @@
+../../src/lookup_table.h
\ No newline at end of file
diff --git a/tests/dir/lz.c b/tests/dir/lz.c
new file mode 120000 (symlink)
index 0000000..0a3c850
--- /dev/null
@@ -0,0 +1 @@
+../../src/lz.c
\ No newline at end of file
diff --git a/tests/dir/lzx-common.c b/tests/dir/lzx-common.c
new file mode 120000 (symlink)
index 0000000..cd78231
--- /dev/null
@@ -0,0 +1 @@
+../../src/lzx-common.c
\ No newline at end of file
diff --git a/tests/dir/lzx-comp.c b/tests/dir/lzx-comp.c
new file mode 120000 (symlink)
index 0000000..a0c4e9e
--- /dev/null
@@ -0,0 +1 @@
+../../src/lzx-comp.c
\ No newline at end of file
diff --git a/tests/dir/lzx-decomp.c b/tests/dir/lzx-decomp.c
new file mode 120000 (symlink)
index 0000000..2235acf
--- /dev/null
@@ -0,0 +1 @@
+../../src/lzx-decomp.c
\ No newline at end of file
diff --git a/tests/dir/lzx.h b/tests/dir/lzx.h
new file mode 120000 (symlink)
index 0000000..2b55c6b
--- /dev/null
@@ -0,0 +1 @@
+../../src/lzx.h
\ No newline at end of file
diff --git a/tests/dir/modify.c b/tests/dir/modify.c
new file mode 120000 (symlink)
index 0000000..007b89e
--- /dev/null
@@ -0,0 +1 @@
+../../src/modify.c
\ No newline at end of file
diff --git a/tests/dir/mount.c b/tests/dir/mount.c
new file mode 120000 (symlink)
index 0000000..d1ee2fc
--- /dev/null
@@ -0,0 +1 @@
+../../src/mount.c
\ No newline at end of file
diff --git a/tests/dir/resource.c b/tests/dir/resource.c
new file mode 120000 (symlink)
index 0000000..02de13c
--- /dev/null
@@ -0,0 +1 @@
+../../src/resource.c
\ No newline at end of file
diff --git a/tests/dir/security.c b/tests/dir/security.c
new file mode 120000 (symlink)
index 0000000..55e2465
--- /dev/null
@@ -0,0 +1 @@
+../../src/security.c
\ No newline at end of file
diff --git a/tests/dir/security.h b/tests/dir/security.h
new file mode 120000 (symlink)
index 0000000..fa9a3d7
--- /dev/null
@@ -0,0 +1 @@
+../../src/security.h
\ No newline at end of file
diff --git a/tests/dir/sha1.c b/tests/dir/sha1.c
new file mode 120000 (symlink)
index 0000000..bf0a00b
--- /dev/null
@@ -0,0 +1 @@
+../../src/sha1.c
\ No newline at end of file
diff --git a/tests/dir/sha1.h b/tests/dir/sha1.h
new file mode 120000 (symlink)
index 0000000..4902ee8
--- /dev/null
@@ -0,0 +1 @@
+../../src/sha1.h
\ No newline at end of file
diff --git a/tests/dir/split.c b/tests/dir/split.c
new file mode 120000 (symlink)
index 0000000..c8b6759
--- /dev/null
@@ -0,0 +1 @@
+../../src/split.c
\ No newline at end of file
diff --git a/tests/dir/subdir/empty_file b/tests/dir/subdir/empty_file
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/dir/subdir/identical_file1 b/tests/dir/subdir/identical_file1
new file mode 100644 (file)
index 0000000..ce01362
--- /dev/null
@@ -0,0 +1 @@
+hello
diff --git a/tests/dir/subdir/identical_file2 b/tests/dir/subdir/identical_file2
new file mode 100644 (file)
index 0000000..ce01362
--- /dev/null
@@ -0,0 +1 @@
+hello
diff --git a/tests/dir/subdir/short_file b/tests/dir/subdir/short_file
new file mode 100644 (file)
index 0000000..56a6051
--- /dev/null
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/tests/dir/subdir/zeroes b/tests/dir/subdir/zeroes
new file mode 100644 (file)
index 0000000..a64a5a9
Binary files /dev/null and b/tests/dir/subdir/zeroes differ
diff --git a/tests/dir/timestamp.h b/tests/dir/timestamp.h
new file mode 120000 (symlink)
index 0000000..499c216
--- /dev/null
@@ -0,0 +1 @@
+../../src/timestamp.h
\ No newline at end of file
diff --git a/tests/dir/util.c b/tests/dir/util.c
new file mode 120000 (symlink)
index 0000000..87f5cc3
--- /dev/null
@@ -0,0 +1 @@
+../../src/util.c
\ No newline at end of file
diff --git a/tests/dir/util.h b/tests/dir/util.h
new file mode 120000 (symlink)
index 0000000..82c8f13
--- /dev/null
@@ -0,0 +1 @@
+../../src/util.h
\ No newline at end of file
diff --git a/tests/dir/wim.c b/tests/dir/wim.c
new file mode 120000 (symlink)
index 0000000..742ee97
--- /dev/null
@@ -0,0 +1 @@
+../../src/wim.c
\ No newline at end of file
diff --git a/tests/dir/wimlib.h b/tests/dir/wimlib.h
new file mode 120000 (symlink)
index 0000000..50fea46
--- /dev/null
@@ -0,0 +1 @@
+../../src/wimlib.h
\ No newline at end of file
diff --git a/tests/dir/wimlib_internal.h b/tests/dir/wimlib_internal.h
new file mode 120000 (symlink)
index 0000000..d8b284f
--- /dev/null
@@ -0,0 +1 @@
+../../src/wimlib_internal.h
\ No newline at end of file
diff --git a/tests/dir/write.c b/tests/dir/write.c
new file mode 120000 (symlink)
index 0000000..b7406c5
--- /dev/null
@@ -0,0 +1 @@
+../../src/write.c
\ No newline at end of file
diff --git a/tests/dir/xml.c b/tests/dir/xml.c
new file mode 120000 (symlink)
index 0000000..b8a30e8
--- /dev/null
@@ -0,0 +1 @@
+../../src/xml.c
\ No newline at end of file
diff --git a/tests/dir/xml.h b/tests/dir/xml.h
new file mode 120000 (symlink)
index 0000000..240aa39
--- /dev/null
@@ -0,0 +1 @@
+../../src/xml.h
\ No newline at end of file
diff --git a/tests/dir/xpress-comp.c b/tests/dir/xpress-comp.c
new file mode 120000 (symlink)
index 0000000..2027648
--- /dev/null
@@ -0,0 +1 @@
+../../src/xpress-comp.c
\ No newline at end of file
diff --git a/tests/dir/xpress-decomp.c b/tests/dir/xpress-decomp.c
new file mode 120000 (symlink)
index 0000000..3a60d8f
--- /dev/null
@@ -0,0 +1 @@
+../../src/xpress-decomp.c
\ No newline at end of file
diff --git a/tests/dir/xpress.h b/tests/dir/xpress.h
new file mode 120000 (symlink)
index 0000000..14c0399
--- /dev/null
@@ -0,0 +1 @@
+../../src/xpress.h
\ No newline at end of file
diff --git a/tests/dir2/imagex.c b/tests/dir2/imagex.c
new file mode 120000 (symlink)
index 0000000..9da744b
--- /dev/null
@@ -0,0 +1 @@
+../../programs/imagex.c
\ No newline at end of file
diff --git a/tests/dir2/mkwinpeimg b/tests/dir2/mkwinpeimg
new file mode 120000 (symlink)
index 0000000..80b4805
--- /dev/null
@@ -0,0 +1 @@
+../../programs/mkwinpeimg
\ No newline at end of file
diff --git a/tests/test-imagex b/tests/test-imagex
new file mode 100755 (executable)
index 0000000..94a3851
--- /dev/null
@@ -0,0 +1,321 @@
+#!/bin/sh
+
+# This script does some sanity testing of the 'imagex' program.  It by no means
+# tests every aspect of wimlib comprehensively.
+
+# Assume an in-tree build.
+set -e
+cd tests
+
+imagex() {
+       echo "imagex $@"
+       ../imagex $@
+}
+#diff() {
+       #echo "diff $@"
+       #/usr/bin/env diff $@
+#}
+
+#dd() {
+       #echo "dd $@"
+       #/usr/bin/env dd $@
+#}
+#stat() {
+       #echo "stat $@" 1>&2
+       #/usr/bin/env stat $@
+#}
+#cmp() {
+       #echo "cmp $@"
+       #/usr/bin/env cmp $@
+#}
+
+
+cleanup() {
+       if [ -d tmp ] && mountpoint tmp; then
+               fusermount -u tmp > /dev/null;
+       fi
+       rm -rf tmp* *.wim *.swm dir3
+}
+trap cleanup exit
+
+# Capturing and applying WIM with None, LZX, and XPRESS compression
+
+echo "Testing capture and application of uncompressed WIM"
+imagex capture dir dir.wim
+imagex apply dir.wim tmp
+test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "None";
+diff -q -r dir tmp
+rm -rf dir.wim tmp
+
+echo "Testing capture and application of LZX-compressed WIM"
+imagex capture dir dir.wim --compress=maximum
+imagex apply dir.wim tmp
+test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "LZX";
+diff -q -r dir tmp
+rm -rf dir.wim tmp
+
+echo "Testing capture and application of XPRESS-compressed WIM"
+imagex capture dir dir.wim --compress=fast
+imagex apply dir.wim tmp
+test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "XPRESS";
+diff -q -r dir tmp
+rm -rf dir.wim tmp
+
+# Capturing and modifying name, description, and bootable flag
+
+echo "Testing capture of WIM with default name and description"
+imagex capture dir dir.wim
+test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "dir";
+test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "";
+rm -rf dir.wim tmp
+
+echo "Testing capture of WIM with default boot flag"
+imagex capture dir dir.wim
+test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0";
+echo "Testing changing image bootable flag"
+imagex info dir.wim 1 --boot
+test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1";
+echo "Testing changing image bootable flag"
+imagex info dir.wim 0 --boot
+test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0";
+echo "Testing changing image bootable flag to invalid image (this should generate errors)"
+! imagex info dir.wim 2 --boot 
+test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0";
+rm -rf dir.wim tmp
+
+echo "Testing capture of WIM with name and description"
+imagex capture dir dir.wim "myname" "mydesc"
+test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "myname";
+test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "mydesc";
+echo "Testing printing WIM lookup table"
+imagex info --lookup-table dir.wim
+echo "Testing printing WIM header"
+imagex info --header dir.wim
+echo "Testing printing WIM XML info"
+imagex info --xml dir.wim
+echo "Testing extracting WIM XML info"
+imagex info --extract-xml=dir.xml dir.wim
+echo "Testing printing WIM metadata"
+imagex info --metadata dir.wim
+rm -rf dir.wim tmp dir.xml
+
+echo "Testing capture of bootable WIM"
+imagex capture dir dir.wim --boot
+test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1";
+rm -rf dir.wim tmp
+
+# Integrity table
+
+echo "Testing capture of WIM with integrity table"
+imagex capture dir dir.wim --check
+test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
+imagex apply --check dir.wim tmp
+diff -q -r dir tmp
+rm -rf dir.wim tmp
+
+# Appending and deleting images
+
+echo "Testing appending WIM image"
+imagex capture dir dir.wim
+imagex append dir2 dir.wim
+test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2;
+echo "Testing appending WIM image with existing name (this should generate errors)"
+! imagex append dir2 dir.wim
+echo "Testing appending WIM image with new name"
+imagex append dir2 dir.wim "newname"
+echo "Testing appending WIM image with integrity check"
+imagex append dir2 dir.wim "newname2" --check
+test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
+echo "Testing appending WIM image with no integrity check"
+imagex append dir2 dir.wim "newname3"
+test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "no";
+test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 5;
+echo "Testing deleting first WIM image"
+imagex delete dir.wim 1
+test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 4;
+echo "Testing deleting last WIM image"
+imagex delete dir.wim 4
+test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3;
+echo "Testing deleting invalid WIM image (this should generate errors)"
+! imagex delete dir.wim 4
+test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3;
+echo "Testing deleting all WIM images"
+imagex delete dir.wim all
+test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 0;
+echo "Testing appending directory to empty WIM and making it bootable"
+imagex append dir dir.wim "myname" "mydesc" --check --boot
+test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
+test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1";
+echo "Testing appending non-directory (should generate errors)"
+! imagex append dir.wim dir.wim
+echo "Testing appending non-existent file (should generate errors)"
+! imagex append SOME_NONEXISTENT_FILE dir.wim
+echo "Testing appending directory containing unreadable file (should generate errors)"
+mkdir -p dir3
+touch dir3/file
+chmod -r dir3/file
+! imagex append dir3 dir.wim
+rm -rf dir3 dir.wim
+
+# Applying multiple images, applying with hardlinks/symlinks
+
+imagex capture dir dir.wim
+imagex append dir dir.wim "myname"
+echo "Testing application of multiple images"
+imagex apply dir.wim all tmp
+diff -q -r tmp/dir tmp/myname
+test `stat -c %h tmp/dir/lz.c` = 1;
+test `stat -c %h tmp/myname/lz.c` = 1;
+test `stat -c %i tmp/myname/lz.c` != `stat -c %i tmp/dir/lz.c`;
+rm -rf tmp
+echo "Testing application of multiple images with hardlinks"
+imagex apply dir.wim all tmp --hardlink
+diff -q -r tmp/dir tmp/myname
+test `stat -c %h tmp/dir/lz.c` = 2;
+test `stat -c %h tmp/myname/lz.c` = 2;
+test `stat -c %i tmp/myname/lz.c` = `stat -c %i tmp/dir/lz.c`;
+rm -rf tmp
+echo "Testing application of single image containing identical files"
+imagex apply dir.wim 1 tmp
+test `stat -c %h tmp/subdir/identical_file1` = 1;
+test `stat -c %h tmp/subdir/identical_file2` = 1;
+test `stat -c %i tmp/subdir/identical_file1` != `stat -c %i tmp/subdir/identical_file2`;
+! readlink tmp/subdir/identical_file1 && ! readlink tmp/subdir/identical_file2
+rm -rf tmp
+
+echo "Testing application of single image containing identical files with hardlinks"
+imagex apply dir.wim 1 tmp --hardlink
+test `stat -c %h tmp/subdir/identical_file1` = 2;
+test `stat -c %h tmp/subdir/identical_file2` = 2;
+test `stat -c %i tmp/subdir/identical_file1` = `stat -c %i tmp/subdir/identical_file2`;
+! readlink tmp/subdir/identical_file1 && ! readlink tmp/subdir/identical_file2
+rm -rf tmp
+
+echo "Testing application of single image containing identical files with symlinks"
+imagex apply dir.wim 1 tmp --symlink
+test `stat -c %h tmp/subdir/identical_file1` = 1;
+test `stat -c %h tmp/subdir/identical_file2` = 1;
+test `stat -c %i tmp/subdir/identical_file1` != `stat -c %i tmp/subdir/identical_file2`;
+readlink tmp/subdir/identical_file1 > /dev/null || \
+               readlink tmp/subdir/identical_file2 > /dev/null
+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"
+       imagex capture dir dir.wim $flag
+       mkdir tmp
+       imagex mount dir.wim dir tmp
+       echo "Testing extracting file from mounted read-only WIM"
+       cp tmp/lz.c lz.c
+       diff -q dir/lz.c lz.c
+       diff -q tmp/lz.c dir/lz.c
+       rm -f lz.c
+       echo "Testing modifying mounted read-only WIM (should fail)"
+       ! rm tmp/lz.c
+       ! touch tmp/newfile
+       ! echo 3 > tmp/newfile
+       echo "Testing diff of mounted read-only WIM with original directory"
+       diff -q -r tmp dir
+       echo "Testing unmount of read-only filesystem"
+       imagex unmount tmp
+       echo "Testing unmount of read-only filesystem with --commit given"
+       imagex mount dir.wim dir tmp
+       imagex unmount tmp --commit
+       rm -rf tmp dir.wim
+done
+
+# imagex mountrw
+for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
+       echo "Using flag $flag"
+       echo "Testing mounting WIM read-write"
+       imagex capture dir dir.wim $flag
+       mkdir tmp
+       imagex mountrw dir.wim dir tmp
+       echo "Testing unmounting WIM unmodified"
+       imagex unmount tmp
+       echo "Testing unmounting WIM unmodified with --commit and --check"
+       imagex mountrw dir.wim dir tmp
+       imagex unmount tmp --commit --check
+       echo "Testing removing file from mounted WIM"
+       imagex mountrw dir.wim dir tmp
+       rm tmp/lz.c
+       test ! -e tmp/lz.c
+       echo "Testing making directory in mounted WIM"
+       mkdir tmp/newdir
+       test -d tmp/newdir
+       echo "Testing making new empty file in mounted WIM"
+       touch tmp/newdir/empty_file
+       test -e tmp/newdir/empty_file
+       test `stat -c %s tmp/newdir/empty_file` = 0;
+       echo "Testing making new non-empty file in mounted WIM"
+       dd if=/dev/zero of=tmp/newdir/zeroes1 bs=1 count=4096
+       dd if=/dev/zero of=tmp/newdir/zeroes2 bs=4096 count=1
+       cmp tmp/newdir/zeroes1 tmp/newdir/zeroes2
+       echo "Unmounting WIM with changes committed and --check"
+       imagex unmount tmp --commit --check
+       test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
+       rm -rf tmp
+       imagex apply dir.wim tmp
+       cmp tmp/newdir/zeroes1 tmp/newdir/zeroes2
+       test `stat -c %s tmp/newdir/empty_file` = 0;
+       test `stat -c %s tmp/newdir/zeroes1` = 4096;
+       rm -rf tmp dir.wim
+done
+
+# imagex split, imagex join
+
+echo "Creating random files to test WIM splitting on"
+mkdir tmp
+for i in `seq 1 100`; do
+       dd if=/dev/urandom of=tmp/file$i bs=4096 count=10 &> /dev/null
+done
+for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
+       echo "Using flag $flag"
+       imagex capture tmp tmp.wim $flag
+       echo "Splitting WIM into 1 MiB chunks"
+       imagex split tmp.wim tmp.swm 1
+       echo "Verifying the split WIMs (some errors expected)"
+       test "`imagex info tmp.swm | grep 'Part Number' | awk '{print $3}'`" = "1/4"
+       imagex dir tmp.swm > /dev/null
+       test -e tmp2.swm && ! imagex dir tmp2.swm
+       ! imagex info tmp.swm --boot 0 # Unsupported, should fail
+       echo "Joining the split WIMs and applying the result"
+       imagex join tmp2.wim tmp*.wim
+       imagex apply tmp2.wim tmp2
+       imagex apply tmp.wim tmp3
+       diff -q -r tmp tmp2
+       diff -q -r tmp tmp3
+       rm -f *.wim *.swm
+       rm -rf tmp2 tmp3
+done
+rm -rf tmp
+
+# imagex export
+echo "Testing export of single image to new WIM"
+imagex capture dir dir.wim
+imagex append dir2 dir.wim
+imagex export dir.wim dir new.wim
+test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" = 1;
+echo "Testing export of single image to existing WIM"
+imagex export dir.wim dir2 new.wim
+test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" = 2;
+echo "Testing export of single image to existing WIM using wrong compression type"
+! imagex export dir.wim dir2 new.wim newname --compress=maximum
+rm -f new.wim
+echo "Testing export of multiple images to new WIM"
+imagex export dir.wim all new.wim
+test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" = 2;
+imagex capture dir2 new.wim newname
+echo "Testing export of multiple images to existing WIM"
+imagex export dir.wim all new.wim
+echo "Testing export of multiple images to existing WIM with --boot"
+imagex capture dir2 new.wim newname
+imagex info dir.wim --boot 1
+imagex export dir.wim all new.wim --boot
+echo "Testing export of multiple images to existing WIM with --boot, but no bootable image (errors expected)"
+imagex capture dir2 new.wim newname
+imagex info dir.wim --boot 0
+! imagex export dir.wim all new.wim --boot