Revert "test_delayed_write_update4 HACKS ..."
[metze/samba/wip.git] / source4 / torture / basic / delaywrite.c
index 0a0331585a95a25ee4045f2eb63bfff137d91ecb..6f5bd2a8b6a9f2403bf788ae3cc731ae2c08a49e 100644 (file)
 #include "libcli/libcli.h"
 #include "torture/util.h"
 #include "torture/basic/proto.h"
-
-#define W2K8R2_TIMEDELAY_SECS 1
-#define W2K3_TIMEDELAY_SECS 2
-#define TIMEDELAY_SECS W2K3_TIMEDELAY_SECS
+#include "lib/util/time_basic.h"
 
 #define BASEDIR "\\delaywrite"
 
@@ -47,7 +44,7 @@ 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;
@@ -57,68 +54,58 @@ static bool test_delayed_write_update(struct torture_context *tctx, struct smbcl
        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_result(tctx, TORTURE_FAIL, "Failed to open %s", 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");
-       
-       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);
+       torture_comment(tctx, "Initial write time %s\n",
+                       nt_time_string(tctx, finfo1.basic_info.out.write_time));
 
-       if (written != 1) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "write failed - wrote %d bytes (%s)\n", 
-                                          (int)written, __location__);
-               return false;
-       }
+       written =  smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
+       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 < (TIMEDELAY_SECS * sec)) {
-                               torture_result(tctx, TORTURE_FAIL, "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);
                smb_msleep(1 * msec);
        }
-       
-       if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server did not update write time (wrong!)");
-               ret = false;
-       }
 
+       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,21 +125,21 @@ 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];
+       bool first;
+       bool updated;
 
        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_result(tctx, TORTURE_FAIL, "Failed to open %s", 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);
@@ -172,8 +159,11 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
 
        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) */
@@ -181,112 +171,82 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
 
        /* Do a zero length SMBwrite call to truncate. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 1024, 0);
-
-       if (written != 0) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "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);
+       first = true;
+       updated = false;
        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) {
-                       torture_result(tctx, TORTURE_FAIL, 
-                                                  "file not truncated, size = %u (should be 1024)",
-                               (unsigned int)finfo2.all_info.out.size);
-                       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));
-               if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
-                       double diff = timeval_elapsed(&start);
-                       if (diff > (0.25 * sec)) {
-                               torture_result(tctx, TORTURE_FAIL, "After SMBwrite truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
-                               ret = false;
-                               break;
-                       }
+                       nt_time_string(tctx, finfo2.all_info.out.write_time));
 
-                       torture_comment(tctx, "After SMBwrite truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+               if (finfo1.all_info.out.write_time !=
+                   finfo2.all_info.out.write_time)
+               {
+                       updated = true;
                        break;
                }
+
                fflush(stdout);
                smb_msleep(1 * msec);
+               first = false;
        }
 
-       if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server did not update write time (wrong!)");
-               ret = false;
-       }
+       torture_assert(tctx, updated,
+                      "Server did not update write time within 120 seconds");
+
+       torture_assert(tctx, first, talloc_asprintf(tctx,
+                      "Server did not update write time immediately but only "
+                      "after %.2f seconds!", timeval_elapsed(&start)));
+
+       torture_comment(tctx, "Server updated write time immediately. Good!\n");
 
        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_result(tctx, TORTURE_FAIL, 
-                                          "write failed - wrote %d bytes (%s)",
-                                          (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, size = %u (should be 1024)\n",
-                               (unsigned int)finfo3.all_info.out.size));
-                       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)(wrong)\n",
-                                       diff, sec);
-                       break;
-               }
                fflush(stdout);
                smb_msleep(1 * msec);
        }
 
-       if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server updated write time (wrong!)");
-               ret = false;
-       }
+       torture_comment(tctx, "Server did not update write time within 10 "
+                       "seconds. Good!\n");
 
        fflush(stdout);
        smb_msleep(2 * msec);
@@ -298,13 +258,17 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
        torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
-       if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               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");
-       }
+       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);
@@ -327,21 +291,21 @@ 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];
+       bool first;
+       bool updated;
 
        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_result(tctx, TORTURE_FAIL, "Failed to open %s", 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);
@@ -361,66 +325,54 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
 
        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));
 
        /* Do a zero length SMBwrite call to truncate. */
        written = smbcli_smbwrite(cli->tree, fnum1, "x", 10240, 0);
 
-       if (written != 0) {
-               torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)",
-                      (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);
+       first = true;
+       updated = false;
        while (!timeval_expired(&end)) {
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s", 
-                                                  nt_errstr(status));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo2.all_info.out.size != 10240) {
-                       torture_result(tctx, TORTURE_FAIL, 
-                                                  "file not truncated, size = %u (should be 10240)",
-                               (unsigned int)finfo2.all_info.out.size);
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo2.all_info.out.size, 10240,
+                                        "file not truncated to expected size "
+                                        "(10240)");
 
                torture_comment(tctx, "write time %s\n",
-                      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)) {
-                               torture_result(tctx, TORTURE_FAIL, "After SMBwrite truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
-                               ret = false;
-                               break;
-                       }
+                       nt_time_string(tctx, finfo2.all_info.out.write_time));
 
-                       torture_comment(tctx, "After SMBwrite truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+               if (finfo1.all_info.out.write_time !=
+                   finfo2.all_info.out.write_time)
+               {
+                       updated = true;
                        break;
                }
+
                fflush(stdout);
                smb_msleep(1 * msec);
+               first = false;
        }
 
-       if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server did not update write time (wrong!)");
-               ret = false;
-       }
+       torture_assert(tctx, updated,
+                      "Server did not update write time within 120 seconds");
+
+       torture_assert(tctx, first, talloc_asprintf(tctx,
+                      "Server did not update write time immediately but only "
+                      "after %.2f seconds!", timeval_elapsed(&start)));
+
+       torture_comment(tctx, "Server updated write time immediately. Good!\n");
 
        fflush(stdout);
        smb_msleep(2 * msec);
@@ -428,48 +380,37 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
        /* 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);
 
-       torture_assert_int_equal(tctx, written, 1, 
-                                                        "unexpected number of bytes written");
+       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)) {
-                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s\n", 
-                                                  nt_errstr(status));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo3.all_info.out.size != 10240) {
-                       torture_result(tctx, TORTURE_FAIL, 
-                                                  "file not truncated, size = %u (should be 10240)",
-                                                  (unsigned int)finfo3.all_info.out.size);
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo3.all_info.out.size, 10240,
+                                        "file not truncated to expected size "
+                                        "(10240)");
 
                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_result(tctx, TORTURE_FAIL, "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
-                       break;
-               }
                fflush(stdout);
                smb_msleep(1 * msec);
        }
 
-       if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server updated write time (wrong!)");
-               ret = false;
-       }
+       torture_comment(tctx, "Server did not update write time within 10 "
+                       "seconds. Good!\n");
 
        /* the close should trigger an write time update */
        smbcli_close(cli->tree, fnum1);
@@ -478,13 +419,17 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
        torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
-       if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               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");
-       }
+       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);
@@ -507,21 +452,21 @@ 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];
+       bool first;
+       bool updated;
 
        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_result(tctx, TORTURE_FAIL, "Failed to open %s", 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);
@@ -541,8 +486,11 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
 
        torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
+       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));
+               nt_time_string(tctx, finfo1.all_info.out.write_time));
 
        /* Do a SET_END_OF_FILE_INFO call to truncate. */
        status = smbcli_ftruncate(cli->tree, fnum1, (uint64_t)10240);
@@ -551,52 +499,40 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
 
        start = timeval_current();
        end = timeval_add(&start, (120*sec), 0);
+       first = true;
+       updated = false;
        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 != 10240) {
-                       torture_result(tctx, TORTURE_FAIL,
-                                                  "file not truncated (size = %u, should be 10240)",
-                                                  (unsigned int)finfo2.all_info.out.size );
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo2.all_info.out.size, 10240,
+                                        "file not truncated to expected size "
+                                        "(10240)");
 
                torture_comment(tctx, "write time %s\n",
-                      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)) {
-                               torture_result(tctx, TORTURE_FAIL, 
-                                       "After SET_END_OF_FILE truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)",
-                                       diff, sec);
-                               ret = false;
-                               break;
-                       }
+                       nt_time_string(tctx, finfo2.all_info.out.write_time));
 
-                       torture_comment(tctx, "After SET_END_OF_FILE truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+               if (finfo1.all_info.out.write_time !=
+                   finfo2.all_info.out.write_time)
+               {
+                       updated = true;
                        break;
                }
+
                fflush(stdout);
                smb_msleep(1 * msec);
+               first = false;
        }
 
-       if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL,
-                                          "Server did not update write time (wrong!)");
-               ret = false;
-       }
+       torture_assert(tctx, updated,
+                      "Server did not update write time within 120 seconds");
+
+       torture_assert(tctx, first, talloc_asprintf(tctx,
+                      "Server did not update write time immediately but only "
+                      "after %.2f seconds!", timeval_elapsed(&start)));
+
+       torture_comment(tctx, "Server updated write time immediately. Good!\n");
 
        fflush(stdout);
        smb_msleep(2 * msec);
@@ -604,46 +540,37 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
        /* 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);
 
-       torture_assert_int_equal(tctx, written, 1, 
-                                                        "unexpected number of bytes written");
+       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)) {
-                       torture_result(tctx, TORTURE_FAIL,
-                                                  "fileinfo failed: %s", nt_errstr(status));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo3.all_info.out.size != 10240) {
-                       DEBUG(0, ("file not truncated (size = %u, should be 10240)\n",
-                               (unsigned int)finfo3.all_info.out.size ));
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo3.all_info.out.size, 10240,
+                                        "file not truncated to expected size "
+                                        "(10240)");
 
                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);
                smb_msleep(1 * msec);
        }
 
-       if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, "Server updated write time (wrong!)\n");
-               ret = false;
-       }
+       torture_comment(tctx, "Server did not update write time within 10 "
+                       "seconds. Good!\n");
 
        /* the close should trigger an write time update */
        smbcli_close(cli->tree, fnum1);
@@ -652,12 +579,17 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
        torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
-       if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               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");
-       }
+       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);
@@ -680,21 +612,21 @@ 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];
+       bool first;
+       bool updated;
 
        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_result(tctx, TORTURE_FAIL, "Failed to open %s", 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);
@@ -714,8 +646,11 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
 
        torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
+       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));
+               nt_time_string(tctx, finfo1.all_info.out.write_time));
 
        /* Do a SET_ALLOCATION_SIZE call to truncate. */
        parms.allocation_info.level = RAW_SFILEINFO_ALLOCATION_INFO;
@@ -724,103 +659,81 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
 
        status = smb_raw_setfileinfo(cli->tree, &parms);
 
-       torture_assert_ntstatus_ok(tctx, status, 
-                                                          "RAW_SFILEINFO_ALLOCATION_INFO failed");
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "RAW_SFILEINFO_ALLOCATION_INFO failed");
 
        start = timeval_current();
        end = timeval_add(&start, (120*sec), 0);
+       first = true;
+       updated = false;
        while (!timeval_expired(&end)) {
                status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s", 
-                                                  nt_errstr(status));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo2.all_info.out.size != 0) {
-                       torture_result(tctx, TORTURE_FAIL, 
-                                                  "file not truncated (size = %u, should be 10240)",
-                               (unsigned int)finfo2.all_info.out.size);
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo2.all_info.out.size, 0,
+                                        "file not truncated to expected size "
+                                        "(0)");
 
                torture_comment(tctx, "write time %s\n",
-                      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)) {
-                               torture_result(tctx, TORTURE_FAIL, "After SET_ALLOCATION_INFO truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(wrong!)\n",
-                                       diff, sec);
-                               ret = false;
-                               break;
-                       }
+                       nt_time_string(tctx, finfo2.all_info.out.write_time));
 
-                       torture_comment(tctx, "After SET_ALLOCATION_INFO truncate "
-                                       "server updated write_time after %.2f seconds"
-                                       "(1 sec == %.2f)(correct)\n",
-                                       diff, sec);
+               if (finfo1.all_info.out.write_time !=
+                   finfo2.all_info.out.write_time)
+               {
+                       updated = true;
                        break;
                }
+
                fflush(stdout);
                smb_msleep(1 * msec);
+               first = false;
        }
 
-       if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server did not update write time (wrong!)");
-               ret = false;
-       }
+       torture_assert(tctx, updated,
+                      "Server did not update write time within 120 seconds");
+
+       torture_assert(tctx, first, talloc_asprintf(tctx,
+                      "Server did not update write time immediately but only "
+                      "after %.2f seconds!", timeval_elapsed(&start)));
+
+       torture_comment(tctx, "Server updated write time immediately. Good!\n");
 
        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);
-       torture_assert_int_equal(tctx, written, 1, 
-                                                        "Unexpected number of bytes written");
+       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)) {
-                       torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s", 
-                                                  nt_errstr(status));
-                       ret = false;
-                       break;
-               }
+               torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
 
-               if (finfo3.all_info.out.size != 1) {
-                       torture_result(tctx, TORTURE_FAIL, "file not expanded");
-                       ret = false;
-                       break;
-               }
+               torture_assert_u64_equal(tctx, finfo3.all_info.out.size, 1,
+                                        "file not expaneded");
 
                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);
                smb_msleep(1 * msec);
        }
 
-       if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
-               torture_result(tctx, TORTURE_FAIL, 
-                                          "Server updated write time (wrong!)");
-               ret = false;
-       }
+       torture_comment(tctx, "Server did not update write time within 10 "
+                       "seconds. Good!\n");
 
        /* the close should trigger an write time update */
        smbcli_close(cli->tree, fnum1);
@@ -829,12 +742,15 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
        status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
        torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
 
-       if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
-               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");
-       }
+       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");
 
        if (fnum1 != -1)
                smbcli_close(cli->tree, fnum1);
@@ -860,7 +776,7 @@ 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;
@@ -990,8 +906,8 @@ 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) {
                        double diff = timeval_elapsed(&start);
                        torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds"
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -1082,8 +998,8 @@ 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) {
                        double diff = timeval_elapsed(&start);
                        torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -1162,17 +1078,17 @@ 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 < (TIMEDELAY_SECS * sec)) {
+                       if (diff < (used_delay / (double)1000000)) {
                                torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds"
-                                               "(1sec == %.2f) (wrong!)\n",
-                                               diff, sec);
+                                               "(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);
@@ -1218,7 +1134,7 @@ 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;
@@ -1392,44 +1308,48 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
        COMPARE_WRITE_TIME_EQUAL(given,correct); \
 } while (0)
 
-#define GET_INFO_FILE(finfo) do { \
-       NTSTATUS _status; \
-       _status = smb_raw_fileinfo(cli->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)); \
+#define _DEBUG_BASIC_INFO(finfo, comment) do { \
+       struct timeval atv; \
+       struct timeval wtv; \
+       struct timeval_buf atvb; \
+       struct timeval_buf wtvb; \
+       nttime_to_timeval(&atv, finfo.basic_info.out.access_time); \
+       nttime_to_timeval(&wtv, finfo.basic_info.out.write_time); \
+       torture_comment(tctx, "%s: Access(%s) Write(%s)\n", \
+                       comment, \
+                       timeval_str_buf(&atv, false, true, &atvb), \
+                       timeval_str_buf(&wtv, false, true, &wtvb)); \
 } while (0)
-#define GET_INFO_FILE2(finfo) do { \
+#define _GET_INFO_FILE(tree, finfo) do { \
        NTSTATUS _status; \
-       _status = smb_raw_fileinfo(cli2->tree, tctx, &finfo); \
+       _status = smb_raw_fileinfo(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)); \
+       _DEBUG_BASIC_INFO(finfo, "fileinfo(" #tree ")"); \
 } while (0)
-#define GET_INFO_PATH(pinfo) do { \
+#define _GET_INFO_PATH(tree, pinfo) do { \
        NTSTATUS _status; \
-       _status = smb_raw_pathinfo(cli2->tree, tctx, &pinfo); \
+       _status = smb_raw_pathinfo(tree, tctx, &pinfo); \
        if (!NT_STATUS_IS_OK(_status)) { \
                torture_result(tctx, TORTURE_FAIL, __location__": pathinfo failed: %s", \
                               nt_errstr(_status)); \
                ret = false; \
                goto done; \
        } \
-       torture_comment(tctx, "pathinfo: Access(%s) Write(%s)\n", \
-                       nt_time_string(tctx, pinfo.basic_info.out.access_time), \
-                       nt_time_string(tctx, pinfo.basic_info.out.write_time)); \
+       _DEBUG_BASIC_INFO(pinfo, "pathinfo(" #tree ")"); \
+} while (0)
+#define GET_INFO_FILE(finfo) do { \
+       _GET_INFO_FILE(cli->tree, finfo); \
+} while (0)
+#define GET_INFO_FILE2(finfo) do { \
+       _GET_INFO_FILE(cli2->tree, finfo); \
+} while (0)
+#define GET_INFO_PATH(pinfo) do { \
+       _GET_INFO_PATH(cli2->tree, pinfo); \
 } while (0)
 #define GET_INFO_BOTH(finfo,pinfo) do { \
        GET_INFO_FILE(finfo); \
@@ -1490,7 +1410,7 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
        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;
@@ -1543,17 +1463,17 @@ 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 < (TIMEDELAY_SECS * sec)) {
+                       if (diff < (used_delay / (double)1000000)) {
                                torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
-                                               "(1sec == %.2f) (wrong!)\n",
-                                               diff, sec);
+                                               "(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;
                }
                smb_msleep(0.5 * msec);
@@ -1580,8 +1500,8 @@ 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_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -1642,7 +1562,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
        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;
@@ -1705,7 +1625,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
 
                if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (TIMEDELAY_SECS * sec)) {
+                       if (diff < (used_delay / (double)1000000)) {
                                torture_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
                                                "(1sec == %.2f) (wrong!)\n",
                                                diff, sec);
@@ -1714,8 +1634,8 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
                        }
 
                        torture_comment(tctx, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (correct)\n",
-                                       diff, sec);
+                                       "(correct)\n",
+                                       diff);
                        break;
                }
                smb_msleep(0.5 * msec);
@@ -1766,8 +1686,8 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -1853,7 +1773,7 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
        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;
@@ -1916,17 +1836,17 @@ 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 < (TIMEDELAY_SECS * sec)) {
-                               torture_result(tctx, TORTURE_FAIL, "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;
                }
                smb_msleep(0.5 * msec);
@@ -1953,8 +1873,8 @@ 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_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2008,8 +1928,8 @@ 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;
-       union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
+       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;
@@ -2017,7 +1937,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
        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;
@@ -2039,14 +1959,12 @@ static bool test_delayed_write_update3c(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);
@@ -2098,8 +2016,8 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2163,8 +2081,8 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2225,7 +2143,7 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
        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;
@@ -2285,17 +2203,17 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
 
                if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
                        double diff = timeval_elapsed(&start);
-                       if (diff < (TIMEDELAY_SECS * sec)) {
-                               torture_result(tctx, TORTURE_FAIL, "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;
                }
                smb_msleep(0.5 * msec);
@@ -2322,8 +2240,8 @@ 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_result(tctx, TORTURE_FAIL, "Server updated write_time after %.2f seconds "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2382,7 +2300,7 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
        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;
@@ -2451,8 +2369,8 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2483,8 +2401,8 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2542,7 +2460,7 @@ static bool test_delayed_write_update5b(struct torture_context *tctx,
        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;
@@ -2611,8 +2529,8 @@ static bool test_delayed_write_update5b(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2643,8 +2561,8 @@ static bool test_delayed_write_update5b(struct torture_context *tctx,
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2707,7 +2625,7 @@ static bool test_delayed_write_update6(struct torture_context *tctx,
        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;
@@ -2788,8 +2706,8 @@ again:
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2820,8 +2738,8 @@ again:
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2883,8 +2801,8 @@ again:
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -2910,8 +2828,8 @@ again:
                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 "
-                                       "(1sec == %.2f) (wrong!)\n",
-                                       diff, sec);
+                                       "(wrong!)\n",
+                                       diff);
                        ret = false;
                        break;
                }
@@ -3011,7 +2929,7 @@ static bool test_delayed_write_update7(struct torture_context *tctx, struct smbc
 
        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");
+                       "qpathinfo time doesn't match fileinfo time");
                ret = false;
        }
 
@@ -3071,7 +2989,7 @@ static bool test_directory_update8(struct torture_context *tctx, struct smbcli_s
        int fnum1 = -1;
        int fnum2 = -1;
        bool ret = true;
-       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;
@@ -3152,12 +3070,265 @@ static bool test_directory_update8(struct torture_context *tctx, struct smbcli_s
        return ret;
 }
 
+#undef COMPARE_WRITE_TIME_CMP
+#undef COMPARE_ACCESS_TIME_CMP
+
+#define COMPARE_TIME_CMP(given, gelem, correct, celem, cmp) do { \
+       const uint64_t _r = 10*1000*1000; \
+       NTTIME _g = (given).basic_info.out.gelem; \
+       NTTIME _gr = (_g / _r) * _r; \
+       NTTIME _c = (correct).basic_info.out.celem; \
+       NTTIME _cr = (_c / _r) * _r; \
+       bool _strict = torture_setting_bool(tctx, "strict mode", false); \
+       const char *_err = NULL; \
+       if (_strict && (_g cmp _c)) { \
+               _err = "strict"; \
+       } else if ((_g cmp _c) && (_gr cmp _cr)) { \
+               /* handle filesystem without high resolution timestamps */ \
+               _err = "rounded"; \
+       } \
+       if (_err != NULL) { \
+               struct timeval _gtv; \
+               struct timeval _ctv; \
+               struct timeval_buf _gtvb; \
+               struct timeval_buf _ctvb; \
+               nttime_to_timeval(&_gtv, _g); \
+               nttime_to_timeval(&_ctv, _c); \
+               torture_result(tctx, TORTURE_FAIL, \
+                              __location__": %s wrong (%s.%s)%s %s (%s.%s)%s", \
+                              _err, \
+                              #given, #gelem, \
+                              timeval_str_buf(&_gtv, false, true, &_gtvb), \
+                              #cmp, \
+                              #correct, #celem, \
+                              timeval_str_buf(&_ctv, false, true, &_ctvb)); \
+               ret = false; \
+               goto done; \
+       } \
+} while (0)
+#define COMPARE_WRITE_TIME_CMP(given, correct, cmp) do { \
+       COMPARE_TIME_CMP(given, write_time, correct, write_time, cmp); \
+} while (0)
+#define COMPARE_WRITE_TIME_EQUAL(given,correct) \
+       COMPARE_WRITE_TIME_CMP(given,correct,!=)
+#define COMPARE_WRITE_TIME_GREATER(given,correct) \
+       COMPARE_WRITE_TIME_CMP(given,correct,<=)
+
+#define COMPARE_ACCESS_TIME_CMP(given, correct, cmp) do { \
+       COMPARE_TIME_CMP(given, access_time, correct, access_time, cmp); \
+} while (0)
+#define COMPARE_ACCESS_TIME_EQUAL(given,correct) \
+       COMPARE_ACCESS_TIME_CMP(given,correct,!=)
+#define COMPARE_ACCESS_TIME_GREATER(given,correct) \
+       COMPARE_ACCESS_TIME_CMP(given,correct,<=)
+
+#define COMPARE_CHANGE_TIME_CMP(given, correct, cmp) do { \
+       COMPARE_TIME_CMP(given, change_time, correct, change_time, cmp); \
+} while (0)
+#define COMPARE_CHANGE_TIME_EQUAL(given,correct) \
+       COMPARE_CHANGE_TIME_CMP(given,correct,!=)
+#define COMPARE_CHANGE_TIME_GREATER(given,correct) \
+       COMPARE_CHANGE_TIME_CMP(given,correct,<=)
+
+#define COMPARE_CREATE_TIME_CMP(given, correct, cmp) do { \
+       COMPARE_TIME_CMP(given, create_time, correct, create_time, cmp); \
+} while (0)
+#define COMPARE_CREATE_TIME_EQUAL(given,correct) \
+       COMPARE_CREATE_TIME_CMP(given,correct,!=)
+
+#define COMPARE_ALL_TIMES_EQUAL(given,correct) do { \
+       COMPARE_WRITE_TIME_EQUAL(given,correct); \
+       COMPARE_CHANGE_TIME_EQUAL(given,correct); \
+       COMPARE_ACCESS_TIME_EQUAL(given,correct); \
+       COMPARE_CREATE_TIME_EQUAL(given,correct); \
+} while (0)
+
+#define COMPARE_TIMES_AFTER_WRITE(given,correct) do { \
+       COMPARE_WRITE_TIME_GREATER(given,correct); \
+       COMPARE_CHANGE_TIME_GREATER(given,correct); \
+       COMPARE_ACCESS_TIME_EQUAL(given,correct); \
+       COMPARE_CREATE_TIME_EQUAL(given,correct); \
+       COMPARE_TIME_CMP(given, change_time, given, write_time, !=); \
+} while (0)
+
+struct test_delaywrite_delaywrite1_state {
+       struct torture_context *tctx;
+       struct smbcli_state *cli1;
+       struct smbcli_state *cli2;
+       int fnum1;
+       int fnum2;
+       const char *fname;
+};
+
+static bool test_delaywrite_delaywrite1_get_info(void *private_data,
+                                                  union smb_fileinfo *finfo)
+{
+       struct test_delaywrite_delaywrite1_state *state =
+               (struct test_delaywrite_delaywrite1_state *)private_data;
+       struct torture_context *tctx = state->tctx;
+       struct smbcli_state *cli = state->cli1;
+       struct smbcli_state *cli2 = state->cli2;
+       union smb_fileinfo t1finfo;
+       union smb_fileinfo t2finfo;
+       bool ret = true;
+
+       ZERO_STRUCTP(finfo);
+
+       ZERO_STRUCT(t1finfo);
+       t1finfo.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
+       t1finfo.basic_info.in.file.fnum = state->fnum1;
+
+       ZERO_STRUCT(t2finfo);
+       t2finfo.basic_info.level = RAW_FILEINFO_BASIC_INFORMATION;
+       t2finfo.basic_info.in.file.fnum = state->fnum2;
+
+       GET_INFO_FILE2(t2finfo);
+       GET_INFO_FILE(t1finfo);
+       if (t1finfo.basic_info.out.write_time != t2finfo.basic_info.out.write_time) {
+               /*
+                * There was a race, get it again on handle 2,
+                * but then they have to match.
+                */
+               GET_INFO_FILE2(t2finfo);
+       }
+       COMPARE_ALL_TIMES_EQUAL(t1finfo, t2finfo);
+
+       finfo->basic_info.out = t1finfo.basic_info.out;
+done:
+       return ret;
+}
+
+static bool test_delaywrite_delaywrite1_write_data(void *private_data)
+{
+       struct test_delaywrite_delaywrite1_state *state =
+               (struct test_delaywrite_delaywrite1_state *)private_data;
+       struct torture_context *tctx = state->tctx;
+       bool ret = true;
+       ssize_t nwritten;
+
+       nwritten = smbcli_write(state->cli1->tree, state->fnum1, 0, "x", 0, 1);
+       torture_assert_int_equal_goto(tctx, nwritten, 1,
+                                     ret, done, "smbcli_write");
+
+done:
+       return ret;
+}
+
+static bool test_delaywrite_delaywrite1_close(void *private_data,
+                                             union smb_fileinfo *finfo)
+{
+       struct test_delaywrite_delaywrite1_state *state =
+               (struct test_delaywrite_delaywrite1_state *)private_data;
+       struct torture_context *tctx = state->tctx;
+       struct smbcli_state *cli2 = state->cli2;
+       union smb_fileinfo t2finfo;
+       union smb_fileinfo t2pinfo;
+       bool ret = true;
+
+       ZERO_STRUCTP(finfo);
+
+       /*
+        * 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(state->cli1->tree, state->fnum1);
+       state->fnum1 = -1;
+
+       ZERO_STRUCT(t2finfo);
+       t2finfo.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       t2finfo.basic_info.in.file.fnum = state->fnum2;
+       ZERO_STRUCT(t2pinfo);
+       t2pinfo.basic_info.level = RAW_FILEINFO_BASIC_INFO;
+       t2pinfo.basic_info.in.file.path = state->fname;
+
+       GET_INFO_FILE2(t2finfo);
+
+       smbcli_close(state->cli2->tree, state->fnum2);
+       state->fnum2 = -1;
+
+       GET_INFO_PATH(t2pinfo);
+       COMPARE_ALL_TIMES_EQUAL(t2pinfo, t2finfo);
+
+       finfo->basic_info.out = t2pinfo.basic_info.out;
+
+done:
+       return ret;
+}
+
+static bool test_delaywrite_delaywrite1(struct torture_context *tctx,
+                                       struct smbcli_state *cli,
+                                       struct smbcli_state *cli2)
+{
+       struct test_delaywrite_delaywrite1_state state = {
+               .tctx = tctx,
+               .cli1 = cli,
+               .cli2 = cli2,
+               .fnum1 = -1,
+               .fnum2 = -1,
+       };
+       const char *fname = BASEDIR "\\torture_file3.txt";
+       bool ret = true;
+       double normal_delay = 1000000;
+       double used_delay;
+       bool ok;
+
+       used_delay = torture_setting_int(tctx, "writetimeupdatedelay",
+                                        normal_delay);
+
+       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");
+       state.fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       torture_assert_int_not_equal_goto(tctx, state.fnum1, -1,
+                                         ret, done,
+                                         "unable to open fnum1");
+       state.fnum2 = smbcli_open(cli2->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+       torture_assert_int_not_equal_goto(tctx, state.fnum2, -1,
+                                         ret, done,
+                                         "unable to open fnum2");
+
+       state.fname = fname;
+
+       ok = test_smb_timestamp_writetime1(tctx, used_delay, normal_delay,
+                       "run1",
+                       test_delaywrite_delaywrite1_get_info,
+                       test_delaywrite_delaywrite1_write_data,
+                       NULL, /* close_cb */
+                       &state);
+       torture_assert_goto(tctx, ok, ret, done,
+                            "test_smb_timestamp_writetime1(1)");
+       ok = test_smb_timestamp_writetime1(tctx, used_delay, normal_delay,
+                       "run2",
+                       test_delaywrite_delaywrite1_get_info,
+                       test_delaywrite_delaywrite1_write_data,
+                       test_delaywrite_delaywrite1_close,
+                       &state);
+       torture_assert_goto(tctx, ok, ret, done,
+                           "test_smb_timestamp_writetime1(2)");
+
+ done:
+       if (state.fnum1 != -1) {
+               smbcli_close(cli->tree, state.fnum1);
+       }
+       if (state.fnum2 != -1) {
+               smbcli_close(cli2->tree, state.fnum2);
+       }
+       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 *torture_delay_write(TALLOC_CTX *ctx)
 {
-       struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "delaywrite");
+       struct torture_suite *suite = torture_suite_create(ctx, "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);
@@ -3175,8 +3346,8 @@ struct torture_suite *torture_delay_write(void)
        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);
+       torture_suite_add_2smb_test(suite, "delaywrite1", test_delaywrite_delaywrite1);
 
        return suite;
 }