s4:torture:basic: use assert in the second loop in delayed_write_update1
[obnox/samba/samba-obnox.git] / source4 / torture / basic / delaywrite.c
index 53018f30b5e9bf5a285bdee5d7c199ce60d11de4..edb3dc9a917b9aa5bf86058f290b5df033be0dc7 100644 (file)
@@ -29,6 +29,7 @@
 #include "system/filesys.h"
 #include "libcli/libcli.h"
 #include "torture/util.h"
+#include "torture/basic/proto.h"
 
 #define BASEDIR "\\delaywrite"
 
@@ -42,83 +43,68 @@ static bool test_delayed_write_update(struct torture_context *tctx, struct smbcl
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
-       if (fnum1 == -1) {
-               torture_comment(tctx, "Failed to open %s\n", fname);
-               return false;
-       }
+       torture_assert_int_not_equal(tctx, fnum1, -1, talloc_asprintf(tctx,
+                                    "Failed to open %s", fname));
 
        finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        finfo1.basic_info.in.file.fnum = fnum1;
        finfo2 = finfo1;
 
        status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
-       
-       torture_comment(tctx, "Initial write time %s\n", 
-              nt_time_string(tctx, finfo1.basic_info.out.write_time));
-
-       /* 3 second delay to ensure we get past any 2 second time
-          granularity (older systems may have that) */
-       msleep(3 * msec);
+       torture_comment(tctx, "Initial write time %s\n",
+                       nt_time_string(tctx, finfo1.basic_info.out.write_time));
 
        written =  smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
-
-       if (written != 1) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n", 
-                      (int)written, __location__);
-               return false;
-       }
+       torture_assert_int_equal(tctx, written, 1,
+                                "unexpected number of bytes written");
 
        start = timeval_current();
-       end = timeval_add(&start, (120*sec), 0);
+       end = timeval_add(&start, (120 * sec), 0);
        while (!timeval_expired(&end)) {
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-                       ret = false;
-                       break;
-               }
-               torture_comment(tctx, "write time %s\n", 
-                      nt_time_string(tctx, finfo2.basic_info.out.write_time));
-               if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
+
+               torture_comment(tctx, "write time %s\n",
+                       nt_time_string(tctx, finfo2.basic_info.out.write_time));
+
+               if (finfo1.basic_info.out.write_time !=
+                   finfo2.basic_info.out.write_time)
+               {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (2 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "Server updated write_time after %.2f seconds"
-                                               "(1 sec == %.2f)(wrong!)\n",
-                                               diff, sec);
-                               ret = false;
-                               break;
-                       }
 
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                       torture_assert(tctx,
+                                      diff >= (used_delay / (double)1000000),
+                                      talloc_asprintf(tctx,
+                                       "Server updated write_time after %.2f "
+                                       "seconds (expected >= %.2f)\n",
+                                       diff, used_delay/(double)1000000));
+
+                       torture_comment(tctx, "Server updated write_time after %.2f seconds (correct)\n",
+                                       diff);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
-       }
-       
-       if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
-               ret = false;
+               smb_msleep(1 * msec);
        }
 
+       torture_assert_u64_not_equal(tctx,
+                                    finfo2.basic_info.out.write_time,
+                                    finfo1.basic_info.out.write_time,
+                                    "Server did not update write time within "
+                                    "120 seconds");
 
        if (fnum1 != -1)
                smbcli_close(cli->tree, fnum1);
@@ -138,28 +124,26 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
        char buf[2048];
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update1\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
-       if (fnum1 == -1) {
-               torture_comment(tctx, "Failed to open %s\n", fname);
-               return false;
-       }
+       torture_assert_int_not_equal(tctx, fnum1, -1, talloc_asprintf(tctx,
+                                    "Failed to open %s", fname));
 
        memset(buf, 'x', 2048);
        written =  smbcli_write(cli->tree, fnum1, 0, buf, 0, 2048);
 
        /* 3 second delay to ensure we get past any 2 second time
           granularity (older systems may have that) */
-       msleep(3 * msec);
+       smb_msleep(3 * msec);
 
        finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
        finfo1.all_info.in.file.fnum = fnum1;
@@ -170,49 +154,43 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
 
        status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-       torture_comment(tctx, "Initial write time %s\n", 
-              nt_time_string(tctx, finfo1.all_info.out.write_time));
+       torture_assert_u64_equal(tctx, finfo1.all_info.out.size, 2048,
+                                "file size not as expected after write(2048)");
+
+       torture_comment(tctx, "Initial write time %s\n",
+                       nt_time_string(tctx, finfo1.all_info.out.write_time));
+
+       /* 3 second delay to ensure we get past any 2 second time
+          granularity (older systems may have that) */
+       smb_msleep(3 * msec);
 
        /* Do a zero length SMBwrite call to truncate. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 1024, 0);
-
-       if (written != 0) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
-                      (int)written, __location__);
-               return false;
-       }
+       torture_assert_int_equal(tctx, written, 0,
+                                "unexpected number of bytes written");
 
        start = timeval_current();
-       end = timeval_add(&start, (120*sec), 0);
+       end = timeval_add(&start, (120 * sec), 0);
        while (!timeval_expired(&end)) {
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo2.all_info.out.size != 1024) {
-                       DEBUG(0, ("file not truncated\n"));
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo2.all_info.out.size, 1024,
+                                        "file not truncated to expected size "
+                                        "(1024)");
 
                torture_comment(tctx, "write time %s\n",
-                      nt_time_string(tctx, finfo2.all_info.out.write_time));
+                       nt_time_string(tctx, finfo2.all_info.out.write_time));
                if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "After SMBwrite truncate "
+                       if (diff > (0.25 * (used_delay / (double)1000000))) {
+                               torture_result(tctx, TORTURE_FAIL, "After SMBwrite truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
+                                       "(write time update dealy == %.2f)(wrong!)\n",
+                                              diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
@@ -220,79 +198,76 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
                        torture_comment(tctx, "After SMBwrite truncate "
                                        "server updated write_time after %.2f seconds"
                                        "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
-       if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
-               ret = false;
-       }
+       torture_assert_u64_not_equal(tctx,
+                                    finfo2.all_info.out.write_time,
+                                    finfo1.all_info.out.write_time,
+                                    "Server did not update write time");
+
+       fflush(stdout);
+       smb_msleep(2 * msec);
 
        /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
-
-       if (written != 1) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
-                      (int)written, __location__);
-               return false;
-       }
+       torture_assert_int_equal(tctx, written, 1,
+                                "unexpected number of bytes written");
 
        start = timeval_current();
        end = timeval_add(&start, (10*sec), 0);
        while (!timeval_expired(&end)) {
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo3.all_info.out.size != 1024) {
-                       DEBUG(0, ("file not truncated\n"));
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo3.all_info.out.size, 1024,
+                                        "file not truncated to expected size "
+                                        "(1024)");
 
                torture_comment(tctx, "write time %s\n",
-                      nt_time_string(tctx, finfo3.all_info.out.write_time));
-               if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-                       double diff = timeval_elapsed(&start);
+                       nt_time_string(tctx, finfo3.all_info.out.write_time));
+
+               torture_assert_u64_equal(tctx,
+                                        finfo3.all_info.out.write_time,
+                                        finfo2.all_info.out.write_time,
+                                        talloc_asprintf(tctx,
+                                               "Server updated write time "
+                                               "after %.2f seconds (wrong!)",
+                                               timeval_elapsed(&start)));
 
-                       torture_comment(tctx, "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
-                       break;
-               }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
-       if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_comment(tctx, "Server updated write time (wrong!)\n");
-               ret = false;
-       }
+       torture_comment(tctx, "Server did not update write time within 10 "
+                       "seconds. Good!\n");
+
+       fflush(stdout);
+       smb_msleep(2 * msec);
 
        /* the close should trigger an write time update */
        smbcli_close(cli->tree, fnum1);
        fnum1 = -1;
 
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("pathinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
-       if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time on close (wrong!)\n");
-               ret = false;
-       } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
-               torture_comment(tctx, "Server updated write time on close (correct)\n");
-       }
+       torture_assert_u64_not_equal(tctx,
+                                    pinfo4.all_info.out.write_time,
+                                    finfo3.all_info.out.write_time,
+                                    "Server did not update write time on "
+                                    "close (wrong!)");
+       torture_assert(tctx,
+               pinfo4.all_info.out.write_time > finfo3.all_info.out.write_time,
+               "Server updated write time on close, but to an earlier point "
+               "in time");
+
+       torture_comment(tctx, "Server updated write time on close (correct)\n");
 
        if (fnum1 != -1)
                smbcli_close(cli->tree, fnum1);
@@ -315,19 +290,19 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
        char buf[2048];
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update1a\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
        if (fnum1 == -1) {
-               torture_comment(tctx, "Failed to open %s\n", fname);
+               torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
                return false;
        }
 
@@ -336,7 +311,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
 
        /* 3 second delay to ensure we get past any 2 second time
           granularity (older systems may have that) */
-       msleep(3 * msec);
+       smb_msleep(3 * msec);
 
        finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
        finfo1.all_info.in.file.fnum = fnum1;
@@ -347,10 +322,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
 
        status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
        torture_comment(tctx, "Initial write time %s\n", 
               nt_time_string(tctx, finfo1.all_info.out.write_time));
@@ -359,7 +331,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 10240, 0);
 
        if (written != 0) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
+               torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)",
                       (int)written, __location__);
                return false;
        }
@@ -370,13 +342,16 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
+                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s", 
+                                                  nt_errstr(status));
                        ret = false;
                        break;
                }
 
                if (finfo2.all_info.out.size != 10240) {
-                       DEBUG(0, ("file not truncated\n"));
+                       torture_result(tctx, TORTURE_FAIL, 
+                                                  "file not truncated, size = %u (should be 10240)",
+                               (unsigned int)finfo2.all_info.out.size);
                        ret = false;
                        break;
                }
@@ -385,38 +360,39 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
                       nt_time_string(tctx, finfo2.all_info.out.write_time));
                if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "After SMBwrite truncate "
+                       if (diff > (0.25 * (used_delay / (double)1000000))) {
+                               torture_result(tctx, TORTURE_FAIL, "After SMBwrite truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(wrong!)\n",
+                                       diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
 
                        torture_comment(tctx, "After SMBwrite truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(correct)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
        if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, 
+                                          "Server did not update write time (wrong!)");
                ret = false;
        }
 
+       fflush(stdout);
+       smb_msleep(2 * msec);
+
        /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
 
-       if (written != 1) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
-                      (int)written, __location__);
-               return false;
-       }
+       torture_assert_int_equal(tctx, written, 1, 
+                                                        "unexpected number of bytes written");
 
        start = timeval_current();
        end = timeval_add(&start, (10*sec), 0);
@@ -424,13 +400,16 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
+                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s\n", 
+                                                  nt_errstr(status));
                        ret = false;
                        break;
                }
 
                if (finfo3.all_info.out.size != 10240) {
-                       DEBUG(0, ("file not truncated\n"));
+                       torture_result(tctx, TORTURE_FAIL, 
+                                                  "file not truncated, size = %u (should be 10240)",
+                                                  (unsigned int)finfo3.all_info.out.size);
                        ret = false;
                        break;
                }
@@ -440,17 +419,18 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
                if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
 
-                       torture_comment(tctx, "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "server updated write_time after %.2f seconds"
+                                       "(write time update delay == %.2f)(correct)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
        if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_comment(tctx, "Server updated write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, 
+                                          "Server updated write time (wrong!)");
                ret = false;
        }
 
@@ -459,13 +439,11 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
        fnum1 = -1;
 
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("pathinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
        if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time on close (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, 
+                                          "Server did not update write time on close (wrong!)");
                ret = false;
        } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
                torture_comment(tctx, "Server updated write time on close (correct)\n");
@@ -492,19 +470,19 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
        char buf[2048];
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update1b\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
        if (fnum1 == -1) {
-               torture_comment(tctx, "Failed to open %s\n", fname);
+               torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
                return false;
        }
 
@@ -513,7 +491,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
 
        /* 3 second delay to ensure we get past any 2 second time
           granularity (older systems may have that) */
-       msleep(3 * msec);
+       smb_msleep(3 * msec);
 
        finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
        finfo1.all_info.in.file.fnum = fnum1;
@@ -524,10 +502,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
 
        status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
        torture_comment(tctx, "Initial write time %s\n",
               nt_time_string(tctx, finfo1.all_info.out.write_time));
@@ -535,11 +510,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
        /* Do a SET_END_OF_FILE_INFO call to truncate. */
        status = smbcli_ftruncate(cli->tree, fnum1, (uint64_t)10240);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               torture_comment(tctx, "SET_END_OF_FILE failed (%s)\n",
-                      nt_errstr(status));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "SET_END_OF_FILE failed");
 
        start = timeval_current();
        end = timeval_add(&start, (120*sec), 0);
@@ -553,7 +524,9 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
                }
 
                if (finfo2.all_info.out.size != 10240) {
-                       DEBUG(0, ("file not truncated\n"));
+                       torture_result(tctx, TORTURE_FAIL,
+                                                  "file not truncated (size = %u, should be 10240)",
+                                                  (unsigned int)finfo2.all_info.out.size );
                        ret = false;
                        break;
                }
@@ -562,38 +535,40 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
                       nt_time_string(tctx, finfo2.all_info.out.write_time));
                if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "After SET_END_OF_FILE truncate "
+                       if (diff > (0.25 * (used_delay / (double)1000000))) {
+                               torture_result(tctx, TORTURE_FAIL, 
+                                       "After SET_END_OF_FILE truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(wrong!)",
+                                       diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
 
                        torture_comment(tctx, "After SET_END_OF_FILE truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(correct)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
        if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL,
+                                          "Server did not update write time (wrong!)");
                ret = false;
        }
 
+       fflush(stdout);
+       smb_msleep(2 * msec);
+
        /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
 
-       if (written != 1) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
-                      (int)written, __location__);
-               return false;
-       }
+       torture_assert_int_equal(tctx, written, 1, 
+                                                        "unexpected number of bytes written");
 
        start = timeval_current();
        end = timeval_add(&start, (10*sec), 0);
@@ -601,13 +576,15 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
+                       torture_result(tctx, TORTURE_FAIL,
+                                                  "fileinfo failed: %s", nt_errstr(status));
                        ret = false;
                        break;
                }
 
                if (finfo3.all_info.out.size != 10240) {
-                       DEBUG(0, ("file not truncated\n"));
+                       DEBUG(0, ("file not truncated (size = %u, should be 10240)\n",
+                               (unsigned int)finfo3.all_info.out.size ));
                        ret = false;
                        break;
                }
@@ -618,16 +595,16 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
                        double diff = timeval_elapsed(&start);
 
                        torture_comment(tctx, "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(correct)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
        if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_comment(tctx, "Server updated write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server updated write time (wrong!)\n");
                ret = false;
        }
 
@@ -636,13 +613,10 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
        fnum1 = -1;
 
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("pathinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
        if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time on close (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server did not update write time on close (wrong!)\n");
                ret = false;
        } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
                torture_comment(tctx, "Server updated write time on close (correct)\n");
@@ -669,19 +643,19 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
        char buf[2048];
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update1c\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
        if (fnum1 == -1) {
-               torture_comment(tctx, "Failed to open %s\n", fname);
+               torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
                return false;
        }
 
@@ -690,7 +664,7 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
 
        /* 3 second delay to ensure we get past any 2 second time
           granularity (older systems may have that) */
-       msleep(3 * msec);
+       smb_msleep(3 * msec);
 
        finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
        finfo1.all_info.in.file.fnum = fnum1;
@@ -701,10 +675,7 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
 
        status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
        torture_comment(tctx, "Initial write time %s\n",
               nt_time_string(tctx, finfo1.all_info.out.write_time));
@@ -714,13 +685,10 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
        parms.allocation_info.in.file.fnum = fnum1;
        parms.allocation_info.in.alloc_size = 0;
 
-        status = smb_raw_setfileinfo(cli->tree, &parms);
+       status = smb_raw_setfileinfo(cli->tree, &parms);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               torture_comment(tctx, "RAW_SFILEINFO_ALLOCATION_INFO failed (%s)\n",
-                      nt_errstr(status));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, 
+                                                          "RAW_SFILEINFO_ALLOCATION_INFO failed");
 
        start = timeval_current();
        end = timeval_add(&start, (120*sec), 0);
@@ -728,13 +696,16 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
+                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s", 
+                                                  nt_errstr(status));
                        ret = false;
                        break;
                }
 
                if (finfo2.all_info.out.size != 0) {
-                       DEBUG(0, ("file not truncated\n"));
+                       torture_result(tctx, TORTURE_FAIL, 
+                                                  "file not truncated (size = %u, should be 10240)",
+                               (unsigned int)finfo2.all_info.out.size);
                        ret = false;
                        break;
                }
@@ -743,38 +714,38 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
                       nt_time_string(tctx, finfo2.all_info.out.write_time));
                if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "After SET_ALLOCATION_INFO truncate "
+                       if (diff > (0.25 * (used_delay / (double)1000000))) {
+                               torture_result(tctx, TORTURE_FAIL, "After SET_ALLOCATION_INFO truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(wrong!)\n",
+                                       diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
 
                        torture_comment(tctx, "After SET_ALLOCATION_INFO truncate "
                                        "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(correct)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
        if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, 
+                                          "Server did not update write time (wrong!)");
                ret = false;
        }
 
+       fflush(stdout);
+       smb_msleep(2 * msec);
+
        /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
-
-       if (written != 1) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
-                      (int)written, __location__);
-               return false;
-       }
+       torture_assert_int_equal(tctx, written, 1, 
+                                                        "Unexpected number of bytes written");
 
        start = timeval_current();
        end = timeval_add(&start, (10*sec), 0);
@@ -782,13 +753,14 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
+                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s", 
+                                                  nt_errstr(status));
                        ret = false;
                        break;
                }
 
                if (finfo3.all_info.out.size != 1) {
-                       DEBUG(0, ("file not expanded\n"));
+                       torture_result(tctx, TORTURE_FAIL, "file not expanded");
                        ret = false;
                        break;
                }
@@ -799,16 +771,17 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
                        double diff = timeval_elapsed(&start);
 
                        torture_comment(tctx, "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f)(wrong)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
 
        if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_comment(tctx, "Server updated write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, 
+                                          "Server updated write time (wrong!)");
                ret = false;
        }
 
@@ -817,13 +790,10 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
        fnum1 = -1;
 
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("pathinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
        if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time on close (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server did not update write time on close (wrong!)\n");
                ret = false;
        } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
                torture_comment(tctx, "Server updated write time on close (correct)\n");
@@ -853,15 +823,15 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
        union smb_flush flsh;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update2\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
        if (fnum1 == -1) {
@@ -875,17 +845,14 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
 
        status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
 
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
-               return false;
-       }
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
        
        torture_comment(tctx, "Initial write time %s\n", 
               nt_time_string(tctx, finfo1.basic_info.out.write_time));
 
        /* 3 second delay to ensure we get past any 2 second time
           granularity (older systems may have that) */
-       msleep(3 * msec);
+       smb_msleep(3 * msec);
 
        {
                /* Try using setfileinfo instead of write to update write time. */
@@ -908,10 +875,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
 
                status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("sfileinfo failed: %s\n", nt_errstr(status)));
-                       return false;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "sfileinfo failed");
        }
 
        finfo2.basic_info.in.file.path = fname;
@@ -928,7 +892,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
                torture_comment(tctx, "Server updated write_time (correct)\n");
        } else {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server did not update write time (wrong!)\n");
                ret = false;
        }
 
@@ -954,7 +918,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        written =  smbcli_write(cli->tree, fnum1, 0, "0123456789", 1, 10);
 
        if (written != 10) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n", 
+               torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)\n",
                       (int)written, __location__);
                return false;
        }
@@ -988,23 +952,26 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
                       nt_time_string(tctx, finfo2.basic_info.out.write_time));
                if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds"
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds"
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
        
        if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
                torture_comment(tctx, "Server did not update write time (correct)\n");
        }
 
+       fflush(stdout);
+       smb_msleep(2 * msec);
+
        fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
        if (fnum2 == -1) {
-               torture_comment(tctx, "Failed to open %s\n", fname);
+               torture_result(tctx, TORTURE_FAIL, "Failed to open %s\n", fname);
                return false;
        }
        
@@ -1013,7 +980,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        written =  smbcli_write(cli->tree, fnum2, 0, "0123456789", 11, 10);
 
        if (written != 10) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n", 
+               torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)\n",
                       (int)written, __location__);
                return false;
        }
@@ -1027,7 +994,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        torture_comment(tctx, "write time %s\n", 
               nt_time_string(tctx, finfo2.basic_info.out.write_time));
        if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
-               torture_comment(tctx, "Server updated write_time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server updated write_time (wrong!)\n");
                ret = false;
        }
 
@@ -1040,7 +1007,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        written =  smbcli_write(cli->tree, fnum2, 0, "0123456789", 21, 10);
 
        if (written != 10) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n", 
+               torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)\n",
                       (int)written, __location__);
                return false;
        }
@@ -1057,7 +1024,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        torture_comment(tctx, "write time %s\n", 
               nt_time_string(tctx, finfo2.basic_info.out.write_time));
        if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
-               torture_comment(tctx, "Server updated write_time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server updated write_time (wrong!)\n");
                ret = false;
        }
 
@@ -1077,14 +1044,14 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
                       nt_time_string(tctx, finfo2.basic_info.out.write_time));
                if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
                fflush(stdout);
-               msleep(1 * msec);
+               smb_msleep(1 * msec);
        }
        
        if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
@@ -1116,13 +1083,13 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        torture_comment(tctx, "Second open initial write time %s\n", 
               nt_time_string(tctx, finfo1.basic_info.out.write_time));
 
-       msleep(10 * msec);
+       smb_msleep(10 * msec);
        torture_comment(tctx, "Doing a 10 byte write to extend the file to see if this changes the last write time.\n");
 
        written =  smbcli_write(cli->tree, fnum1, 0, "0123456789", 31, 10);
 
        if (written != 10) {
-               torture_comment(tctx, "write failed - wrote %d bytes (%s)\n", 
+               torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)\n",
                       (int)written, __location__);
                return false;
        }
@@ -1139,7 +1106,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
        torture_comment(tctx, "write time %s\n", 
               nt_time_string(tctx, finfo2.basic_info.out.write_time));
        if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
-               torture_comment(tctx, "Server updated write_time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server updated write_time (wrong!)\n");
                ret = false;
        }
 
@@ -1158,25 +1125,25 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
                       nt_time_string(tctx, finfo2.basic_info.out.write_time));
                if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (2 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "Server updated write_time after %.2f seconds"
-                                               "(1sec == %.2f) (wrong!)\n",
-                                               diff, sec);
+                       if (diff < (used_delay / (double)1000000)) {
+                               torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds"
+                                               "(expected > %.2f) (wrong!)\n",
+                                               diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
 
                        torture_comment(tctx, "Server updated write_time after %.2f seconds"
-                                       "(1sec == %.2f) (correct)\n",
-                                       diff, sec);
+                                       "(correct)\n",
+                                       diff);
                        break;
                }
                fflush(stdout);
-               msleep(1*msec);
+               smb_msleep(1*msec);
        }
        
        if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
-               torture_comment(tctx, "Server did not update write time (wrong!)\n");
+               torture_result(tctx, TORTURE_FAIL, "Server did not update write time (wrong!)\n");
                ret = false;
        }
 
@@ -1214,14 +1181,14 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
        int fnum2;
        bool ret = true;
        ssize_t written;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_finfo_after_write\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
        if (fnum1 == -1) {
@@ -1241,7 +1208,7 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
                goto done;
        }
 
-       msleep(1 * msec);
+       smb_msleep(1 * msec);
 
        written =  smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
 
@@ -1258,42 +1225,42 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
                ret = false;
                goto done;
        }
-       
+
        written =  smbcli_write(cli2->tree, fnum2, 0, "x", 0, 1);
-       
+
        if (written != 1) {
                torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", 
                       (int)written);
                ret = false;
                goto done;
        }
-       
+
        finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        finfo2.basic_info.in.file.path = fname;
-       
+
        status = smb_raw_pathinfo(cli2->tree, tctx, &finfo2);
-       
+
        if (!NT_STATUS_IS_OK(status)) {
                torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", 
                          nt_errstr(status));
                ret = false;
                goto done;
        }
-       
+
        if (finfo1.basic_info.out.create_time !=
            finfo2.basic_info.out.create_time) {
                torture_result(tctx, TORTURE_FAIL, __location__": create_time changed");
                ret = false;
                goto done;
        }
-       
+
        if (finfo1.basic_info.out.access_time !=
            finfo2.basic_info.out.access_time) {
                torture_result(tctx, TORTURE_FAIL, __location__": access_time changed");
                ret = false;
                goto done;
        }
-       
+
        if (finfo1.basic_info.out.write_time !=
            finfo2.basic_info.out.write_time) {
                torture_result(tctx, TORTURE_FAIL, __location__": write_time changed:\n"
@@ -1303,19 +1270,19 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
                ret = false;
                goto done;
        }
-       
+
        if (finfo1.basic_info.out.change_time !=
            finfo2.basic_info.out.change_time) {
                torture_result(tctx, TORTURE_FAIL, __location__": change_time changed");
                ret = false;
                goto done;
        }
-       
+
        /* One of the two following calls updates the qpathinfo. */
-       
+
        /* If you had skipped the smbcli_write on fnum2, it would
         * *not* have updated the stat on disk */
-       
+
        smbcli_close(cli2->tree, fnum2);
        cli2 = NULL;
 
@@ -1401,6 +1368,19 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
                        nt_time_string(tctx, finfo.basic_info.out.access_time), \
                        nt_time_string(tctx, finfo.basic_info.out.write_time)); \
 } while (0)
+#define GET_INFO_FILE2(finfo) do { \
+       NTSTATUS _status; \
+       _status = smb_raw_fileinfo(cli2->tree, tctx, &finfo); \
+       if (!NT_STATUS_IS_OK(_status)) { \
+               ret = false; \
+               torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", \
+                              nt_errstr(_status)); \
+               goto done; \
+       } \
+       torture_comment(tctx, "fileinfo: Access(%s) Write(%s)\n", \
+                       nt_time_string(tctx, finfo.basic_info.out.access_time), \
+                       nt_time_string(tctx, finfo.basic_info.out.write_time)); \
+} while (0)
 #define GET_INFO_PATH(pinfo) do { \
        NTSTATUS _status; \
        _status = smb_raw_pathinfo(cli2->tree, tctx, &pinfo); \
@@ -1441,26 +1421,46 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
 #define SET_INFO_FILE(finfo, wrtime) \
        SET_INFO_FILE_EX(finfo, wrtime, cli->tree, fnum1)
 
+#define SET_INFO_FILE_NS(finfo, wrtime, ns, tree, tfnum) do { \
+       NTSTATUS _status; \
+       union smb_setfileinfo sfinfo; \
+       sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFO; \
+       sfinfo.basic_info.in.file.fnum = tfnum; \
+       sfinfo.basic_info.in.create_time = 0; \
+       sfinfo.basic_info.in.access_time = 0; \
+       unix_to_nt_time(&sfinfo.basic_info.in.write_time, (wrtime)); \
+       sfinfo.basic_info.in.write_time += (ns); \
+       sfinfo.basic_info.in.change_time = 0; \
+       sfinfo.basic_info.in.attrib = finfo1.basic_info.out.attrib; \
+       _status = smb_raw_setfileinfo(tree, &sfinfo); \
+       if (!NT_STATUS_IS_OK(_status)) { \
+               torture_result(tctx, TORTURE_FAIL, __location__": setfileinfo failed: %s", \
+                              nt_errstr(_status)); \
+               ret = false; \
+               goto done; \
+       } \
+} while (0)
+
 static bool test_delayed_write_update3(struct torture_context *tctx,
                                       struct smbcli_state *cli,
                                       struct smbcli_state *cli2)
 {
-       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
-       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
-       const char *fname = BASEDIR "\\torture_file.txt";
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4;
+       const char *fname = BASEDIR "\\torture_file3.txt";
        int fnum1 = -1;
        bool ret = true;
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update3\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        torture_comment(tctx, "Open the file handle\n");
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
@@ -1475,14 +1475,12 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
        finfo1 = finfo0;
        finfo2 = finfo0;
        finfo3 = finfo0;
-       finfo4 = finfo0;
        pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        pinfo0.basic_info.in.file.path = fname;
        pinfo1 = pinfo0;
        pinfo2 = pinfo0;
        pinfo3 = pinfo0;
        pinfo4 = pinfo0;
-       pinfo5 = pinfo0;
 
        /* get the initial times */
        GET_INFO_BOTH(finfo0,pinfo0);
@@ -1508,20 +1506,20 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
 
                if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (2 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                               "(1sec == %.2f) (wrong!)\n",
-                                               diff, sec);
+                       if (diff < (used_delay / (double)1000000)) {
+                               torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                               "(write time update delay == %.2f) (wrong!)\n",
+                                               diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
 
                        torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (correct)\n",
-                                       diff, sec);
+                                       "(correct)\n",
+                                       diff);
                        break;
                }
-               msleep(0.5 * msec);
+               smb_msleep(0.5 * msec);
        }
 
        GET_INFO_BOTH(finfo1,pinfo1);
@@ -1544,13 +1542,13 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
 
                if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
        GET_INFO_BOTH(finfo2,pinfo2);
@@ -1560,7 +1558,7 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
        }
 
        /* sleep */
-       msleep(5 * msec);
+       smb_msleep(5 * msec);
 
        GET_INFO_BOTH(finfo3,pinfo3);
        COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -1589,26 +1587,32 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
        return ret;
 }
 
-static bool test_delayed_write_update3b(struct torture_context *tctx,
+/*
+ * Show that a truncate write always updates the write time even
+ * if an initial write has already updated the write time.
+ */
+
+static bool test_delayed_write_update3a(struct torture_context *tctx,
                                        struct smbcli_state *cli,
                                        struct smbcli_state *cli2)
 {
-       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
-       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
-       const char *fname = BASEDIR "\\torture_file.txt";
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4;
+       const char *fname = BASEDIR "\\torture_file3a.txt";
        int fnum1 = -1;
        bool ret = true;
        ssize_t written;
+       int i;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update3a\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        torture_comment(tctx, "Open the file handle\n");
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
@@ -1623,14 +1627,12 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
        finfo1 = finfo0;
        finfo2 = finfo0;
        finfo3 = finfo0;
-       finfo4 = finfo0;
        pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        pinfo0.basic_info.in.file.path = fname;
        pinfo1 = pinfo0;
        pinfo2 = pinfo0;
        pinfo3 = pinfo0;
        pinfo4 = pinfo0;
-       pinfo5 = pinfo0;
 
        /* get the initial times */
        GET_INFO_BOTH(finfo0,pinfo0);
@@ -1639,7 +1641,7 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
         * sleep some time, to demonstrate the handling of write times
         * doesn't depend on the time since the open
         */
-       msleep(5 * msec);
+       smb_msleep(5 * msec);
 
        /* get the initial times */
        GET_INFO_BOTH(finfo1,pinfo1);
@@ -1666,8 +1668,8 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
 
                if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (2 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "Server updated write_time after %.2f seconds "
+                       if (diff < (used_delay / (double)1000000)) {
+                               torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
                                                "(1sec == %.2f) (wrong!)\n",
                                                diff, sec);
                                ret = false;
@@ -1675,16 +1677,40 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
                        }
 
                        torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (correct)\n",
-                                       diff, sec);
+                                       "(correct)\n",
+                                       diff);
                        break;
                }
-               msleep(0.5 * msec);
+               smb_msleep(0.5 * msec);
        }
 
        GET_INFO_BOTH(finfo1,pinfo1);
        COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
 
+       smb_msleep(3 * msec);
+
+       /*
+        * demonstrate that a truncate write always
+        * updates the write time immediately
+        */
+       for (i=0; i < 3; i++) {
+               smb_msleep(2 * msec);
+               /* do a write */
+               torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
+               written = smbcli_smbwrite(cli->tree, fnum1, "x", 10240, 0);
+               if (written != 0) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo2,pinfo2);
+               COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
+               finfo1 = finfo2;
+       }
+
+       smb_msleep(3 * msec);
+
        /* sure any further write doesn't update the write time */
        start = timeval_current();
        end = timeval_add(&start, 15 * sec, 0);
@@ -1702,13 +1728,13 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
 
                if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
        GET_INFO_BOTH(finfo2,pinfo2);
@@ -1718,24 +1744,50 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
        }
 
        /* sleep */
-       msleep(5 * msec);
+       smb_msleep(3 * msec);
+
+       /* get the initial times */
+       GET_INFO_BOTH(finfo1,pinfo1);
+       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo2);
+
+       /*
+        * demonstrate that a truncate write always
+        * updates the write time immediately
+        */
+       for (i=0; i < 3; i++) {
+               smb_msleep(2 * msec);
+               /* do a write */
+               torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
+               written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
+               if (written != 0) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo2,pinfo2);
+               COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
+               finfo1 = finfo2;
+       }
+
+       /* sleep */
+       smb_msleep(3 * msec);
 
        GET_INFO_BOTH(finfo3,pinfo3);
        COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
 
        /*
-        * the close updates the write time to the time of the close
-        * and not to the time of the last write!
+        * the close doesn't update the write time
         */
        torture_comment(tctx, "Close the file handle\n");
        smbcli_close(cli->tree, fnum1);
        fnum1 = -1;
 
        GET_INFO_PATH(pinfo4);
-       COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
+       COMPARE_WRITE_TIME_EQUAL(pinfo4, pinfo3);
 
-       if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
-               torture_comment(tctx, "Server updated the write_time on close (correct)\n");
+       if (pinfo4.basic_info.out.write_time == pinfo3.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
        }
 
  done:
@@ -1747,26 +1799,31 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
        return ret;
 }
 
-static bool test_delayed_write_update4(struct torture_context *tctx,
-                                      struct smbcli_state *cli,
-                                      struct smbcli_state *cli2)
+/*
+ * Show a close after write updates the write timestamp to
+ * the close time, not the last write time.
+ */
+
+static bool test_delayed_write_update3b(struct torture_context *tctx,
+                                       struct smbcli_state *cli,
+                                       struct smbcli_state *cli2)
 {
-       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
-       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
-       const char *fname = BASEDIR "\\torture_file.txt";
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4;
+       const char *fname = BASEDIR "\\torture_file3b.txt";
        int fnum1 = -1;
        bool ret = true;
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update3b\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        torture_comment(tctx, "Open the file handle\n");
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
@@ -1781,60 +1838,61 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
        finfo1 = finfo0;
        finfo2 = finfo0;
        finfo3 = finfo0;
-       finfo4 = finfo0;
        pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        pinfo0.basic_info.in.file.path = fname;
        pinfo1 = pinfo0;
        pinfo2 = pinfo0;
        pinfo3 = pinfo0;
        pinfo4 = pinfo0;
-       pinfo5 = pinfo0;
 
        /* get the initial times */
        GET_INFO_BOTH(finfo0,pinfo0);
 
-       /* sleep a bit */
-       msleep(5 * msec);
-
-       /* do a write */
-       torture_comment(tctx, "Do a write on the file handle\n");
-       written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
-       if (written != 1) {
-               torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
-               ret = false;
-               goto done;
-       }
+       /*
+        * sleep some time, to demonstrate the handling of write times
+        * doesn't depend on the time since the open
+        */
+       smb_msleep(5 * msec);
 
+       /* get the initial times */
        GET_INFO_BOTH(finfo1,pinfo1);
-       COMPARE_WRITE_TIME_EQUAL(finfo1,finfo0);
+       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
 
        /*
         * make sure the write time is updated 2 seconds later
         * calcuated from the first write
-        * (but expect upto 3 seconds extra time for a busy server)
+        * (but expect upto 5 seconds extra time for a busy server)
         */
        start = timeval_current();
-       end = timeval_add(&start, 5 * sec, 0);
+       end = timeval_add(&start, 7 * sec, 0);
        while (!timeval_expired(&end)) {
-               /* get the times after the first write */
+               /* do a write */
+               torture_comment(tctx, "Do a write on the file handle\n");
+               written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+               if (written != 1) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
                GET_INFO_FILE(finfo1);
 
                if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (2 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
-                               torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                               "(1sec == %.2f) (wrong!)\n",
-                                               diff, sec);
+                       if (diff < (used_delay / (double)1000000)) {
+                               torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds"
+                                               "(expected > %.2f) (wrong!)\n",
+                                               diff, used_delay / (double)1000000);
                                ret = false;
                                break;
                        }
 
                        torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (correct)\n",
-                                       diff, sec);
+                                       "(write time update delay == %.2f) (correct)\n",
+                                       diff, used_delay / (double)1000000);
                        break;
                }
-               msleep(0.5 * msec);
+               smb_msleep(0.5 * msec);
        }
 
        GET_INFO_BOTH(finfo1,pinfo1);
@@ -1857,23 +1915,23 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
 
                if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
        GET_INFO_BOTH(finfo2,pinfo2);
        COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
        if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
-               torture_comment(tctx, "Server did not updatewrite_time (correct)\n");
+               torture_comment(tctx, "Server did not update write_time (correct)\n");
        }
 
        /* sleep */
-       msleep(5 * msec);
+       smb_msleep(5 * msec);
 
        GET_INFO_BOTH(finfo3,pinfo3);
        COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -1902,26 +1960,34 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
        return ret;
 }
 
-static bool test_delayed_write_update5(struct torture_context *tctx,
-                                      struct smbcli_state *cli,
-                                      struct smbcli_state *cli2)
+/*
+ * Check that a write after a truncate write doesn't update
+ * the timestamp, but a truncate write after a write does.
+ * Also prove that a close after a truncate write updates the
+ * timestamp to current, not the time of last write.
+ */
+
+static bool test_delayed_write_update3c(struct torture_context *tctx,
+                                       struct smbcli_state *cli,
+                                       struct smbcli_state *cli2)
 {
-       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
-       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6;
-       const char *fname = BASEDIR "\\torture_file.txt";
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4;
+       const char *fname = BASEDIR "\\torture_file3c.txt";
        int fnum1 = -1;
        bool ret = true;
        ssize_t written;
+       int i;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
+       torture_comment(tctx, "\nRunning test_delayed_write_update3c\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
 
        torture_comment(tctx, "Open the file handle\n");
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
@@ -1936,67 +2002,110 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
        finfo1 = finfo0;
        finfo2 = finfo0;
        finfo3 = finfo0;
-       finfo4 = finfo0;
-       finfo5 = finfo0;
        pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        pinfo0.basic_info.in.file.path = fname;
        pinfo1 = pinfo0;
        pinfo2 = pinfo0;
        pinfo3 = pinfo0;
        pinfo4 = pinfo0;
-       pinfo5 = pinfo0;
-       pinfo6 = pinfo0;
 
        /* get the initial times */
        GET_INFO_BOTH(finfo0,pinfo0);
 
-       /* do a write */
-       torture_comment(tctx, "Do a write on the file handle\n");
-       written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
-       if (written != 1) {
-               torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
-               ret = false;
-               goto done;
-       }
+       /*
+        * sleep some time, to demonstrate the handling of write times
+        * doesn't depend on the time since the open
+        */
+       smb_msleep(5 * msec);
 
+       /* get the initial times */
        GET_INFO_BOTH(finfo1,pinfo1);
        COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
 
-       torture_comment(tctx, "Set write time in the future on the file handle\n");
-       SET_INFO_FILE(finfo0, time(NULL) + 86400);
-       GET_INFO_BOTH(finfo2,pinfo2);
-       COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
-
-       torture_comment(tctx, "Set write time in the past on the file handle\n");
-       SET_INFO_FILE(finfo0, time(NULL) - 86400);
-       GET_INFO_BOTH(finfo2,pinfo2);
-       COMPARE_WRITE_TIME_LESS(finfo2, finfo1);
+       /*
+        * demonstrate that a truncate write always
+        * updates the write time immediately
+        */
+       for (i=0; i < 3; i++) {
+               smb_msleep(2 * msec);
+               /* do a write */
+               torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
+               written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
+               if (written != 0) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo2,pinfo2);
+               COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
+               finfo1 = finfo2;
+       }
 
-       /* make sure the 2 second delay from the first write are canceled */
        start = timeval_current();
-       end = timeval_add(&start, 15 * sec, 0);
+       end = timeval_add(&start, 7 * sec, 0);
        while (!timeval_expired(&end)) {
+               /* do a write */
+               torture_comment(tctx, "Do a write on the file handle\n");
+               written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+               if (written != 1) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_FILE(finfo2);
 
-               /* get the times after the first write */
-               GET_INFO_BOTH(finfo3,pinfo3);
-
-               if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
+               if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
-       GET_INFO_BOTH(finfo3,pinfo3);
-       COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
-       if (finfo3.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
+       if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
                torture_comment(tctx, "Server did not update write_time (correct)\n");
        }
 
+       /* sleep */
+       smb_msleep(5 * msec);
+
+       /* get the initial times */
+       GET_INFO_BOTH(finfo1,pinfo1);
+       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo2);
+
+       /*
+        * demonstrate that a truncate write always
+        * updates the write time immediately
+        */
+       for (i=0; i < 3; i++) {
+               smb_msleep(2 * msec);
+               /* do a write */
+               torture_comment(tctx, "Do a truncate write [%d] on the file handle\n", i);
+               written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
+               if (written != 0) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo2,pinfo2);
+               COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
+               finfo1 = finfo2;
+       }
+
+       /* sleep */
+       smb_msleep(5 * msec);
+
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
+
        /* sure any further write doesn't update the write time */
        start = timeval_current();
        end = timeval_add(&start, 15 * sec, 0);
@@ -2010,43 +2119,44 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
                        goto done;
                }
                /* get the times after the write */
-               GET_INFO_BOTH(finfo4,pinfo4);
+               GET_INFO_BOTH(finfo2,pinfo2);
 
-               if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
+               if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
-       GET_INFO_BOTH(finfo4,pinfo4);
-       COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
-       if (finfo4.basic_info.out.write_time == finfo3.basic_info.out.write_time) {
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
+       if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
                torture_comment(tctx, "Server did not update write_time (correct)\n");
        }
 
        /* sleep */
-       msleep(5 * msec);
+       smb_msleep(5 * msec);
 
-       GET_INFO_BOTH(finfo5,pinfo5);
-       COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
+       GET_INFO_BOTH(finfo3,pinfo3);
+       COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
 
        /*
-        * the close doesn't update the write time
+        * the close updates the write time to the time of the close
+        * and not to the time of the last write!
         */
        torture_comment(tctx, "Close the file handle\n");
        smbcli_close(cli->tree, fnum1);
        fnum1 = -1;
 
-       GET_INFO_PATH(pinfo6);
-       COMPARE_WRITE_TIME_EQUAL(pinfo6, pinfo5);
+       GET_INFO_PATH(pinfo4);
+       COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
 
-       if (pinfo6.basic_info.out.write_time == pinfo5.basic_info.out.write_time) {
-               torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
+       if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
+               torture_comment(tctx, "Server updated the write_time on close (correct)\n");
        }
 
  done:
@@ -2058,29 +2168,33 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
        return ret;
 }
 
-static bool test_delayed_write_update6(struct torture_context *tctx,
+/*
+ * Show only the first write updates the timestamp, and a close
+ * after writes updates to current (I think this is the same
+ * as test 3b. JRA).
+ */
+
+static bool test_delayed_write_update4(struct torture_context *tctx,
                                       struct smbcli_state *cli,
                                       struct smbcli_state *cli2)
 {
-       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
-       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6, pinfo7;
-       const char *fname = BASEDIR "\\torture_file.txt";
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4;
+       const char *fname = BASEDIR "\\torture_file4.txt";
        int fnum1 = -1;
-       int fnum2 = -1;
        bool ret = true;
        ssize_t written;
        struct timeval start;
        struct timeval end;
-       int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
        int normal_delay = 2000000;
        double sec = ((double)used_delay) / ((double)normal_delay);
        int msec = 1000 * sec;
-       bool first = true;
 
-       if (!torture_setup_dir(cli, BASEDIR)) {
-               return false;
-       }
-again:
+       torture_comment(tctx, "\nRunning test_delayed_write_update4\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+
        torture_comment(tctx, "Open the file handle\n");
        fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
        if (fnum1 == -1) {
@@ -2089,36 +2203,24 @@ again:
                goto done;
        }
 
-       if (fnum2 == -1) {
-               torture_comment(tctx, "Open the 2nd file handle on 2nd connection\n");
-               fnum2 = smbcli_open(cli2->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
-               if (fnum2 == -1) {
-                       ret = false;
-                       torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
-                       goto done;
-               }
-       }
-
        finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        finfo0.basic_info.in.file.fnum = fnum1;
        finfo1 = finfo0;
        finfo2 = finfo0;
        finfo3 = finfo0;
-       finfo4 = finfo0;
-       finfo5 = finfo0;
        pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
        pinfo0.basic_info.in.file.path = fname;
        pinfo1 = pinfo0;
        pinfo2 = pinfo0;
        pinfo3 = pinfo0;
        pinfo4 = pinfo0;
-       pinfo5 = pinfo0;
-       pinfo6 = pinfo0;
-       pinfo7 = pinfo0;
 
        /* get the initial times */
        GET_INFO_BOTH(finfo0,pinfo0);
 
+       /* sleep a bit */
+       smb_msleep(5 * msec);
+
        /* do a write */
        torture_comment(tctx, "Do a write on the file handle\n");
        written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
@@ -2129,7 +2231,502 @@ again:
        }
 
        GET_INFO_BOTH(finfo1,pinfo1);
-       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
+       COMPARE_WRITE_TIME_EQUAL(finfo1,finfo0);
+
+       /*
+        * make sure the write time is updated 2 seconds later
+        * calcuated from the first write
+        * (but expect upto 3 seconds extra time for a busy server)
+        */
+       start = timeval_current();
+       end = timeval_add(&start, 5 * sec, 0);
+       while (!timeval_expired(&end)) {
+               /* get the times after the first write */
+               GET_INFO_FILE(finfo1);
+
+               if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       if (diff < (used_delay / (double)1000000)) {
+                               torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds"
+                                               "(expected > %.2f) (wrong!)\n",
+                                               diff, used_delay / (double)1000000);
+                               ret = false;
+                               break;
+                       }
+
+                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
+                                       "(write time update delay == %.2f) (correct)\n",
+                                       diff, used_delay / (double)1000000);
+                       break;
+               }
+               smb_msleep(0.5 * msec);
+       }
+
+       GET_INFO_BOTH(finfo1,pinfo1);
+       COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
+
+       /* sure any further write doesn't update the write time */
+       start = timeval_current();
+       end = timeval_add(&start, 15 * sec, 0);
+       while (!timeval_expired(&end)) {
+               /* do a write */
+               torture_comment(tctx, "Do a write on the file handle\n");
+               written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+               if (written != 1) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo2,pinfo2);
+
+               if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
+       if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not updatewrite_time (correct)\n");
+       }
+
+       /* sleep */
+       smb_msleep(5 * msec);
+
+       GET_INFO_BOTH(finfo3,pinfo3);
+       COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
+
+       /*
+        * the close updates the write time to the time of the close
+        * and not to the time of the last write!
+        */
+       torture_comment(tctx, "Close the file handle\n");
+       smbcli_close(cli->tree, fnum1);
+       fnum1 = -1;
+
+       GET_INFO_PATH(pinfo4);
+       COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
+
+       if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
+               torture_comment(tctx, "Server updated the write_time on close (correct)\n");
+       }
+
+ done:
+       if (fnum1 != -1)
+               smbcli_close(cli->tree, fnum1);
+       smbcli_unlink(cli->tree, fname);
+       smbcli_deltree(cli->tree, BASEDIR);
+
+       return ret;
+}
+
+/*
+ * Show writes and closes have no effect on updating times once a SETWRITETIME is done.
+ */
+
+static bool test_delayed_write_update5(struct torture_context *tctx,
+                                      struct smbcli_state *cli,
+                                      struct smbcli_state *cli2)
+{
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6;
+       const char *fname = BASEDIR "\\torture_file5.txt";
+       int fnum1 = -1;
+       bool ret = true;
+       ssize_t written;
+       struct timeval start;
+       struct timeval end;
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       int normal_delay = 2000000;
+       double sec = ((double)used_delay) / ((double)normal_delay);
+       int msec = 1000 * sec;
+
+       torture_comment(tctx, "\nRunning test_delayed_write_update5\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+
+       torture_comment(tctx, "Open the file handle\n");
+       fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       if (fnum1 == -1) {
+               ret = false;
+               torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
+               goto done;
+       }
+
+       finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       finfo0.basic_info.in.file.fnum = fnum1;
+       finfo1 = finfo0;
+       finfo2 = finfo0;
+       finfo3 = finfo0;
+       finfo4 = finfo0;
+       finfo5 = finfo0;
+       pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       pinfo0.basic_info.in.file.path = fname;
+       pinfo1 = pinfo0;
+       pinfo2 = pinfo0;
+       pinfo3 = pinfo0;
+       pinfo4 = pinfo0;
+       pinfo5 = pinfo0;
+       pinfo6 = pinfo0;
+
+       /* get the initial times */
+       GET_INFO_BOTH(finfo0,pinfo0);
+
+       /* do a write */
+       torture_comment(tctx, "Do a write on the file handle\n");
+       written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+       if (written != 1) {
+               torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+               ret = false;
+               goto done;
+       }
+
+       GET_INFO_BOTH(finfo1,pinfo1);
+       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
+
+       torture_comment(tctx, "Set write time in the future on the file handle\n");
+       SET_INFO_FILE(finfo0, time(NULL) + 86400);
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
+
+       torture_comment(tctx, "Set write time in the past on the file handle\n");
+       SET_INFO_FILE(finfo0, time(NULL) - 86400);
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_LESS(finfo2, finfo1);
+
+       /* make sure the 2 second delay from the first write are canceled */
+       start = timeval_current();
+       end = timeval_add(&start, 15 * sec, 0);
+       while (!timeval_expired(&end)) {
+
+               /* get the times after the first write */
+               GET_INFO_BOTH(finfo3,pinfo3);
+
+               if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+       GET_INFO_BOTH(finfo3,pinfo3);
+       COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
+       if (finfo3.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update write_time (correct)\n");
+       }
+
+       /* sure any further write doesn't update the write time */
+       start = timeval_current();
+       end = timeval_add(&start, 15 * sec, 0);
+       while (!timeval_expired(&end)) {
+               /* do a write */
+               torture_comment(tctx, "Do a write on the file handle\n");
+               written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+               if (written != 1) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo4,pinfo4);
+
+               if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+       GET_INFO_BOTH(finfo4,pinfo4);
+       COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
+       if (finfo4.basic_info.out.write_time == finfo3.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update write_time (correct)\n");
+       }
+
+       /* sleep */
+       smb_msleep(5 * msec);
+
+       GET_INFO_BOTH(finfo5,pinfo5);
+       COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
+
+       /*
+        * the close doesn't update the write time
+        */
+       torture_comment(tctx, "Close the file handle\n");
+       smbcli_close(cli->tree, fnum1);
+       fnum1 = -1;
+
+       GET_INFO_PATH(pinfo6);
+       COMPARE_WRITE_TIME_EQUAL(pinfo6, pinfo5);
+
+       if (pinfo6.basic_info.out.write_time == pinfo5.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
+       }
+
+ done:
+       if (fnum1 != -1)
+               smbcli_close(cli->tree, fnum1);
+       smbcli_unlink(cli->tree, fname);
+       smbcli_deltree(cli->tree, BASEDIR);
+
+       return ret;
+}
+
+/*
+ * Show truncate writes and closes have no effect on updating times once a SETWRITETIME is done.
+ */
+
+static bool test_delayed_write_update5b(struct torture_context *tctx,
+                                       struct smbcli_state *cli,
+                                       struct smbcli_state *cli2)
+{
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6;
+       const char *fname = BASEDIR "\\torture_fileb.txt";
+       int fnum1 = -1;
+       bool ret = true;
+       ssize_t written;
+       struct timeval start;
+       struct timeval end;
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       int normal_delay = 2000000;
+       double sec = ((double)used_delay) / ((double)normal_delay);
+       int msec = 1000 * sec;
+
+       torture_comment(tctx, "\nRunning test_delayed_write_update5b\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+
+       torture_comment(tctx, "Open the file handle\n");
+       fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       if (fnum1 == -1) {
+               ret = false;
+               torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
+               goto done;
+       }
+
+       finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       finfo0.basic_info.in.file.fnum = fnum1;
+       finfo1 = finfo0;
+       finfo2 = finfo0;
+       finfo3 = finfo0;
+       finfo4 = finfo0;
+       finfo5 = finfo0;
+       pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       pinfo0.basic_info.in.file.path = fname;
+       pinfo1 = pinfo0;
+       pinfo2 = pinfo0;
+       pinfo3 = pinfo0;
+       pinfo4 = pinfo0;
+       pinfo5 = pinfo0;
+       pinfo6 = pinfo0;
+
+       /* get the initial times */
+       GET_INFO_BOTH(finfo0,pinfo0);
+
+       /* do a write */
+       torture_comment(tctx, "Do a write on the file handle\n");
+       written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+       if (written != 1) {
+               torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+               ret = false;
+               goto done;
+       }
+
+       GET_INFO_BOTH(finfo1,pinfo1);
+       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
+
+       torture_comment(tctx, "Set write time in the future on the file handle\n");
+       SET_INFO_FILE(finfo0, time(NULL) + 86400);
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
+
+       torture_comment(tctx, "Set write time in the past on the file handle\n");
+       SET_INFO_FILE(finfo0, time(NULL) - 86400);
+       GET_INFO_BOTH(finfo2,pinfo2);
+       COMPARE_WRITE_TIME_LESS(finfo2, finfo1);
+
+       /* make sure the 2 second delay from the first write are canceled */
+       start = timeval_current();
+       end = timeval_add(&start, 15 * sec, 0);
+       while (!timeval_expired(&end)) {
+
+               /* get the times after the first write */
+               GET_INFO_BOTH(finfo3,pinfo3);
+
+               if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+       GET_INFO_BOTH(finfo3,pinfo3);
+       COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
+       if (finfo3.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update write_time (correct)\n");
+       }
+
+       /* Do any further write (truncates) update the write time ? */
+       start = timeval_current();
+       end = timeval_add(&start, 15 * sec, 0);
+       while (!timeval_expired(&end)) {
+               /* do a write */
+               torture_comment(tctx, "Do a truncate write on the file handle\n");
+               written = smbcli_smbwrite(cli->tree, fnum1, "x", 1024, 0);
+               if (written != 0) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_BOTH(finfo4,pinfo4);
+
+               if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+       GET_INFO_BOTH(finfo4,pinfo4);
+       COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
+       if (finfo4.basic_info.out.write_time == finfo3.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update write_time (correct)\n");
+       }
+
+       /* sleep */
+       smb_msleep(5 * msec);
+
+       GET_INFO_BOTH(finfo5,pinfo5);
+       COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
+
+       /*
+        * the close doesn't update the write time
+        */
+       torture_comment(tctx, "Close the file handle\n");
+       smbcli_close(cli->tree, fnum1);
+       fnum1 = -1;
+
+       GET_INFO_PATH(pinfo6);
+       COMPARE_WRITE_TIME_EQUAL(pinfo6, pinfo5);
+
+       if (pinfo6.basic_info.out.write_time == pinfo5.basic_info.out.write_time) {
+               torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
+       }
+
+ done:
+       if (fnum1 != -1)
+               smbcli_close(cli->tree, fnum1);
+       smbcli_unlink(cli->tree, fname);
+       smbcli_deltree(cli->tree, BASEDIR);
+
+       return ret;
+}
+
+/*
+ * Open 2 handles on a file. Write one one and then set the
+ * WRITE TIME explicitly on the other. Ensure the write time
+ * update is cancelled. Ensure the write time is updated to
+ * the close time when the non-explicit set handle is closed.
+ *
+ */
+
+static bool test_delayed_write_update6(struct torture_context *tctx,
+                                      struct smbcli_state *cli,
+                                      struct smbcli_state *cli2)
+{
+       union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
+       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6, pinfo7;
+       const char *fname = BASEDIR "\\torture_file6.txt";
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool ret = true;
+       ssize_t written;
+       struct timeval start;
+       struct timeval end;
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       int normal_delay = 2000000;
+       double sec = ((double)used_delay) / ((double)normal_delay);
+       int msec = 1000 * sec;
+       bool first = true;
+
+       torture_comment(tctx, "\nRunning test_delayed_write_update6\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+again:
+       torture_comment(tctx, "Open the file handle\n");
+       fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       if (fnum1 == -1) {
+               ret = false;
+               torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
+               goto done;
+       }
+
+       if (fnum2 == -1) {
+               torture_comment(tctx, "Open the 2nd file handle on 2nd connection\n");
+               fnum2 = smbcli_open(cli2->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+               if (fnum2 == -1) {
+                       ret = false;
+                       torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
+                       goto done;
+               }
+       }
+
+       finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       finfo0.basic_info.in.file.fnum = fnum1;
+       finfo1 = finfo0;
+       finfo2 = finfo0;
+       finfo3 = finfo0;
+       finfo4 = finfo0;
+       finfo5 = finfo0;
+       pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       pinfo0.basic_info.in.file.path = fname;
+       pinfo1 = pinfo0;
+       pinfo2 = pinfo0;
+       pinfo3 = pinfo0;
+       pinfo4 = pinfo0;
+       pinfo5 = pinfo0;
+       pinfo6 = pinfo0;
+       pinfo7 = pinfo0;
+
+       /* get the initial times */
+       GET_INFO_BOTH(finfo0,pinfo0);
+
+       /* do a write */
+       torture_comment(tctx, "Do a write on the file handle\n");
+       written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+       if (written != 1) {
+               torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+               ret = false;
+               goto done;
+       }
+
+       GET_INFO_BOTH(finfo1,pinfo1);
+       COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
 
        torture_comment(tctx, "Set write time in the future on the 2nd file handle\n");
        SET_INFO_FILE_EX(finfo0, time(NULL) + 86400, cli2->tree, fnum2);
@@ -2143,7 +2740,7 @@ again:
 
        /* make sure the 2 second delay from the first write are canceled */
        start = timeval_current();
-       end = timeval_add(&start, 15 * sec, 0);
+       end = timeval_add(&start, 10 * sec, 0);
        while (!timeval_expired(&end)) {
 
                /* get the times after the first write */
@@ -2151,13 +2748,13 @@ again:
 
                if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
        GET_INFO_BOTH(finfo3,pinfo3);
@@ -2168,7 +2765,7 @@ again:
 
        /* sure any further write doesn't update the write time */
        start = timeval_current();
-       end = timeval_add(&start, 15 * sec, 0);
+       end = timeval_add(&start, 10 * sec, 0);
        while (!timeval_expired(&end)) {
                /* do a write */
                torture_comment(tctx, "Do a write on the file handle\n");
@@ -2183,13 +2780,13 @@ again:
 
                if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
-               msleep(2 * msec);
+               smb_msleep(1 * msec);
        }
 
        GET_INFO_BOTH(finfo4,pinfo4);
@@ -2199,7 +2796,7 @@ again:
        }
 
        /* sleep */
-       msleep(5 * msec);
+       smb_msleep(5 * msec);
 
        GET_INFO_BOTH(finfo5,pinfo5);
        COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
@@ -2219,6 +2816,70 @@ again:
                torture_comment(tctx, "Server updated the write_time on close (correct)\n");
        }
 
+       /* See what the second write handle thinks the time is ? */
+       finfo5.basic_info.in.file.fnum = fnum2;
+       GET_INFO_FILE2(finfo5);
+       COMPARE_WRITE_TIME_EQUAL(finfo5, pinfo6);
+
+       /* See if we have lost the sticky write time on handle2 */
+       smb_msleep(3 * msec);
+       torture_comment(tctx, "Have we lost the sticky write time ?\n");
+
+       /* Make sure any further normal write doesn't update the write time */
+       start = timeval_current();
+       end = timeval_add(&start, 10 * sec, 0);
+       while (!timeval_expired(&end)) {
+               /* do a write */
+               torture_comment(tctx, "Do a write on the second file handle\n");
+               written = smbcli_write(cli2->tree, fnum2, 0, "x", 0, 1);
+               if (written != 1) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_FILE2(finfo5);
+               GET_INFO_PATH(pinfo6);
+
+               if (finfo5.basic_info.out.write_time > pinfo6.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+       /* What about a truncate write ? */
+       start = timeval_current();
+       end = timeval_add(&start, 10 * sec, 0);
+       while (!timeval_expired(&end)) {
+               /* do a write */
+               torture_comment(tctx, "Do a truncate write on the second file handle\n");
+               written = smbcli_write(cli2->tree, fnum2, 0, "x", 0, 0);
+               if (written != 0) {
+                       torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
+                       ret = false;
+                       goto done;
+               }
+               /* get the times after the write */
+               GET_INFO_FILE2(finfo5);
+               GET_INFO_PATH(pinfo6);
+
+               if (finfo5.basic_info.out.write_time > pinfo6.basic_info.out.write_time) {
+                       double diff = timeval_elapsed(&start);
+                       torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
+                                       "(wrong!)\n",
+                                       diff);
+                       ret = false;
+                       break;
+               }
+               smb_msleep(1 * msec);
+       }
+
+
        /* keep the 2nd handle open and rerun tests */
        if (first) {
                first = false;
@@ -2251,26 +2912,232 @@ again:
        return ret;
 }
 
+static bool test_delayed_write_update7(struct torture_context *tctx, struct smbcli_state *cli)
+{
+       union smb_open open_parms;
+       union smb_fileinfo finfo1, finfo2, finfo3;
+       const char *fname = BASEDIR "\\torture_file7.txt";
+       NTSTATUS status;
+       int fnum1 = -1;
+       bool ret = true;
+       TALLOC_CTX *mem_ctx; 
 
-/* 
+       torture_comment(tctx, "\nRunning test_delayed_write_update7 (timestamp resolution test)\n");
+
+        mem_ctx = talloc_init("test_delayed_write_update7");
+        if (!mem_ctx) return false;
+
+       ZERO_STRUCT(finfo1);
+       ZERO_STRUCT(finfo2);
+       ZERO_STRUCT(finfo3);
+       ZERO_STRUCT(open_parms);
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+
+       /* Create the file. */
+       fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       if (fnum1 == -1) {
+               torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
+               return false;
+       }
+
+       finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       finfo1.basic_info.in.file.fnum = fnum1;
+       finfo2 = finfo1;
+       finfo3 = finfo1;
+
+       /* Get the initial timestamps. */
+       status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
+
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
+       
+       /* Set the pending write time to a value with ns. */
+       SET_INFO_FILE_NS(finfo, time(NULL) + 86400, 103, cli->tree, fnum1);
+
+       /* Get the current pending write time by fnum. */
+       status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
+
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
+
+       /* Ensure the time is actually different. */
+       if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
+               torture_result(tctx, TORTURE_FAIL,
+                       "setfileinfo time matches original fileinfo time");
+               ret = false;
+       }
+
+       /* Get the current pending write time by path. */
+       finfo3.basic_info.in.file.path = fname;
+       status = smb_raw_pathinfo(cli->tree, tctx, &finfo3);
+
+       if (finfo2.basic_info.out.write_time != finfo3.basic_info.out.write_time) {
+               torture_result(tctx, TORTURE_FAIL, 
+                       "qpathinfo time doens't match fileinfo time");
+               ret = false;
+       }
+
+       /* Now close the file. Re-open and check that the write
+          time is identical to the one we wrote. */
+
+       smbcli_close(cli->tree, fnum1);
+
+       open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
+       open_parms.ntcreatex.in.flags = 0;
+       open_parms.ntcreatex.in.access_mask = SEC_GENERIC_READ;
+       open_parms.ntcreatex.in.file_attr = 0;
+       open_parms.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE|
+                                       NTCREATEX_SHARE_ACCESS_READ|
+                                       NTCREATEX_SHARE_ACCESS_WRITE;
+       open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       open_parms.ntcreatex.in.create_options = 0;
+       open_parms.ntcreatex.in.fname = fname;
+
+       status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
+       talloc_free(mem_ctx);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               torture_result(tctx, TORTURE_FAIL,
+                       "setfileinfo time matches original fileinfo time");
+               ret = false;
+       }
+
+       fnum1 = open_parms.ntcreatex.out.file.fnum;
+
+       /* Check the returned time matches. */
+        if (open_parms.ntcreatex.out.write_time != finfo2.basic_info.out.write_time) {
+               torture_result(tctx, TORTURE_FAIL,
+                       "final open time does not match set time");
+               ret = false;
+       }
+
+ done:
+
+       smbcli_close(cli->tree, fnum1);
+
+       smbcli_unlink(cli->tree, fname);
+       smbcli_deltree(cli->tree, BASEDIR);
+       return ret;
+}
+
+/*
+   Test if creating a file in a directory with an open handle updates the
+   write timestamp (it should).
+*/
+static bool test_directory_update8(struct torture_context *tctx, struct smbcli_state *cli)
+{
+       union smb_fileinfo dir_info1, dir_info2;
+       union smb_open open_parms;
+       const char *fname = BASEDIR "\\torture_file.txt";
+       NTSTATUS status;
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool ret = true;
+       double used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
+       int normal_delay = 2000000;
+       double sec = ((double)used_delay) / ((double)normal_delay);
+       int msec = 1000 * sec;
+       TALLOC_CTX *mem_ctx = talloc_init("test_delayed_write_update8");
+
+        if (!mem_ctx) return false;
+
+       torture_comment(tctx, "\nRunning test directory write update\n");
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+
+       /* Open a handle on the directory - and leave it open. */
+       ZERO_STRUCT(open_parms);
+        open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
+        open_parms.ntcreatex.in.flags = 0;
+        open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
+        open_parms.ntcreatex.in.file_attr = 0;
+        open_parms.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE|
+                                        NTCREATEX_SHARE_ACCESS_READ|
+                                        NTCREATEX_SHARE_ACCESS_WRITE;
+        open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+        open_parms.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+        open_parms.ntcreatex.in.fname = BASEDIR;
+
+        status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
+        talloc_free(mem_ctx);
+
+        if (!NT_STATUS_IS_OK(status)) {
+                torture_result(tctx, TORTURE_FAIL,
+                        "failed to open directory handle");
+                ret = false;
+               goto done;
+        }
+
+        fnum1 = open_parms.ntcreatex.out.file.fnum;
+
+        /* Store the returned write time. */
+       ZERO_STRUCT(dir_info1);
+       dir_info1.basic_info.out.write_time = open_parms.ntcreatex.out.write_time;
+
+       torture_comment(tctx, "Initial write time %s\n",
+              nt_time_string(tctx, dir_info1.basic_info.out.write_time));
+
+       /* sleep */
+       smb_msleep(3 * msec);
+
+       /* Now create a file within the directory. */
+       fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       if (fnum2 == -1) {
+               torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
+                ret = false;
+               goto done;
+       }
+       smbcli_close(cli->tree, fnum2);
+
+       /* Read the directory write time again. */
+       ZERO_STRUCT(dir_info2);
+       dir_info2.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       dir_info2.basic_info.in.file.fnum = fnum1;
+
+       status = smb_raw_fileinfo(cli->tree, tctx, &dir_info2);
+
+       torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
+
+       /* Ensure it's been incremented. */
+       COMPARE_WRITE_TIME_GREATER(dir_info2, dir_info1);
+
+       torture_comment(tctx, "Updated write time %s\n",
+              nt_time_string(tctx, dir_info2.basic_info.out.write_time));
+
+ done:
+
+       if (fnum1 != -1)
+               smbcli_close(cli->tree, fnum1);
+       smbcli_unlink(cli->tree, fname);
+       smbcli_deltree(cli->tree, BASEDIR);
+
+       return ret;
+}
+
+/*
    testing of delayed update of write_time
 */
 struct torture_suite *torture_delay_write(void)
 {
-       struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "DELAYWRITE");
+       struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "delaywrite");
 
        torture_suite_add_2smb_test(suite, "finfo update on close", test_finfo_after_write);
        torture_suite_add_1smb_test(suite, "delayed update of write time", test_delayed_write_update);
-       torture_suite_add_1smb_test(suite, "update of write time and SMBwrite truncate ", test_delayed_write_update1);
+       torture_suite_add_1smb_test(suite, "update of write time and SMBwrite truncate", test_delayed_write_update1);
        torture_suite_add_1smb_test(suite, "update of write time and SMBwrite truncate expand", test_delayed_write_update1a);
        torture_suite_add_1smb_test(suite, "update of write time using SET_END_OF_FILE", test_delayed_write_update1b);
        torture_suite_add_1smb_test(suite, "update of write time using SET_ALLOCATION_SIZE", test_delayed_write_update1c);
        torture_suite_add_2smb_test(suite, "delayed update of write time using 2 connections", test_delayed_write_update2);
        torture_suite_add_2smb_test(suite, "delayed update of write time 3", test_delayed_write_update3);
+       torture_suite_add_2smb_test(suite, "delayed update of write time 3a", test_delayed_write_update3a);
        torture_suite_add_2smb_test(suite, "delayed update of write time 3b", test_delayed_write_update3b);
+       torture_suite_add_2smb_test(suite, "delayed update of write time 3c", test_delayed_write_update3c);
        torture_suite_add_2smb_test(suite, "delayed update of write time 4", test_delayed_write_update4);
        torture_suite_add_2smb_test(suite, "delayed update of write time 5", test_delayed_write_update5);
+       torture_suite_add_2smb_test(suite, "delayed update of write time 5b", test_delayed_write_update5b);
        torture_suite_add_2smb_test(suite, "delayed update of write time 6", test_delayed_write_update6);
+       torture_suite_add_1smb_test(suite, "timestamp resolution test", test_delayed_write_update7);
+       torture_suite_add_1smb_test(suite, "timestamp resolution test", test_delayed_write_update7);
+       torture_suite_add_1smb_test(suite, "directory timestamp update test", test_directory_update8);
 
        return suite;
 }