Patchwork D10478: streamclone: remove sleep based "synchronisation" in tests

login
register
mail settings
Submitter phabricator
Date April 20, 2021, 4:09 a.m.
Message ID <differential-rev-PHID-DREV-hfmwpyotsn6nygx7jnb5-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48795/
State Superseded
Headers show

Comments

phabricator - April 20, 2021, 4:09 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Sleep based test synchronisation does not work.
  
  Variation in machine performance and load can make the two process miss their
  windows. Instead we migrate to explicit signaling through the file system as
  other tests file are using.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10478

AFFECTED FILES
  mercurial/streamclone.py
  tests/test-clone-uncompressed.t
  tests/testlib/ext-stream-clone-steps.py

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/testlib/ext-stream-clone-steps.py b/tests/testlib/ext-stream-clone-steps.py
new file mode 100644
--- /dev/null
+++ b/tests/testlib/ext-stream-clone-steps.py
@@ -0,0 +1,31 @@ 
+from __future__ import absolute_import
+
+from mercurial import (
+    encoding,
+    extensions,
+    streamclone,
+    testing,
+)
+
+
+WALKED_FILE_1 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_1']
+WALKED_FILE_2 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_2']
+
+
+def _test_sync_point_walk_1(orig, repo):
+    testing.write_file(WALKED_FILE_1)
+
+
+def _test_sync_point_walk_2(orig, repo):
+    assert repo._currentlock(repo._lockref) is None
+    testing.wait_file(WALKED_FILE_2)
+
+
+def uisetup(ui):
+    extensions.wrapfunction(
+        streamclone, '_test_sync_point_walk_1', _test_sync_point_walk_1
+    )
+
+    extensions.wrapfunction(
+        streamclone, '_test_sync_point_walk_2', _test_sync_point_walk_2
+    )
diff --git a/tests/test-clone-uncompressed.t b/tests/test-clone-uncompressed.t
--- a/tests/test-clone-uncompressed.t
+++ b/tests/test-clone-uncompressed.t
@@ -433,14 +433,35 @@ 
 extension for delaying the server process so we reliably can modify the repo
 while cloning
 
-  $ cat > delayer.py <<EOF
-  > import time
-  > from mercurial import extensions, vfs
-  > def __call__(orig, self, path, *args, **kwargs):
-  >     if path == 'data/f1.i':
-  >         time.sleep(2)
-  >     return orig(self, path, *args, **kwargs)
-  > extensions.wrapfunction(vfs.vfs, '__call__', __call__)
+  $ cat > stream_steps.py <<EOF
+  > import os
+  > import sys
+  > from mercurial import (
+  >     encoding,
+  >     extensions,
+  >     streamclone,
+  >     testing,
+  > )
+  > WALKED_FILE_1 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_1']
+  > WALKED_FILE_2 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_2']
+  > 
+  > def _test_sync_point_walk_1(orig, repo):
+  >     testing.write_file(WALKED_FILE_1)
+  > 
+  > def _test_sync_point_walk_2(orig, repo):
+  >     assert repo._currentlock(repo._lockref) is None
+  >     testing.wait_file(WALKED_FILE_2)
+  > 
+  > extensions.wrapfunction(
+  >     streamclone,
+  >     '_test_sync_point_walk_1',
+  >     _test_sync_point_walk_1
+  > )
+  > extensions.wrapfunction(
+  >     streamclone,
+  >     '_test_sync_point_walk_2',
+  >     _test_sync_point_walk_2
+  > )
   > EOF
 
 prepare repo with small and big file to cover both code paths in emitrevlogdata
@@ -449,20 +470,32 @@ 
   $ touch repo/f1
   $ $TESTDIR/seq.py 50000 > repo/f2
   $ hg -R repo ci -Aqm "0"
-  $ hg serve -R repo -p $HGPORT1 -d --pid-file=hg.pid --config extensions.delayer=delayer.py
+  $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
+  $ export HG_TEST_STREAM_WALKED_FILE_1
+  $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
+  $ export HG_TEST_STREAM_WALKED_FILE_2
+  $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
+  $ export HG_TEST_STREAM_WALKED_FILE_3
+#   $ cat << EOF >> $HGRCPATH
+#   > [hooks]
+#   > pre-clone=rm -f "$TESTTMP/sync_file_walked_*"
+#   > EOF
+  $ hg serve -R repo -p $HGPORT1 -d --error errors.log --pid-file=hg.pid --config extensions.stream_steps="$RUNTESTDIR/testlib/ext-stream-clone-steps.py"
   $ cat hg.pid >> $DAEMON_PIDS
 
 clone while modifying the repo between stating file with write lock and
 actually serving file content
 
-  $ hg clone -q --stream -U http://localhost:$HGPORT1 clone &
-  $ sleep 1
+  $ (hg clone -q --stream -U http://localhost:$HGPORT1 clone; touch "$HG_TEST_STREAM_WALKED_FILE_3") &
+  $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
   $ echo >> repo/f1
   $ echo >> repo/f2
   $ hg -R repo ci -m "1" --config ui.timeout.warn=-1
-  $ wait
+  $ touch $HG_TEST_STREAM_WALKED_FILE_2
+  $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
   $ hg -R clone id
   000000000000
+  $ cat errors.log
   $ cd ..
 
 Stream repository with bookmarks
diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py
--- a/mercurial/streamclone.py
+++ b/mercurial/streamclone.py
@@ -247,6 +247,8 @@ 
             if size:
                 entries.append((name, size))
                 total_bytes += size
+        _test_sync_point_walk_1(repo)
+    _test_sync_point_walk_2(repo)
 
     repo.ui.debug(
         b'%d files, %d bytes to transfer\n' % (len(entries), total_bytes)
@@ -593,6 +595,14 @@ 
                 fp.close()
 
 
+def _test_sync_point_walk_1(repo):
+    """a function for synchronisation during tests"""
+
+
+def _test_sync_point_walk_2(repo):
+    """a function for synchronisation during tests"""
+
+
 def generatev2(repo, includes, excludes, includeobsmarkers):
     """Emit content for version 2 of a streaming clone.
 
@@ -635,6 +645,8 @@ 
         chunks = _emit2(repo, entries, totalfilesize)
         first = next(chunks)
         assert first is None
+        _test_sync_point_walk_1(repo)
+    _test_sync_point_walk_2(repo)
 
     return len(entries), totalfilesize, chunks