# HG changeset patch # User Pierre-Yves David # Date 1618852348 -7200 # Node ID faa43f09ad980b7ea36c95ea39708fbcf11c692f # Parent 52cee44aa1a073fa34b79c7b03eea53e2a803169 streamclone: remove sleep based "synchronisation" in tests 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. Differential Revision: https://phab.mercurial-scm.org/D10478 diff -r 52cee44aa1a0 -r faa43f09ad98 mercurial/streamclone.py --- a/mercurial/streamclone.py Mon Apr 19 19:10:49 2021 +0200 +++ b/mercurial/streamclone.py Mon Apr 19 19:12:28 2021 +0200 @@ -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 diff -r 52cee44aa1a0 -r faa43f09ad98 tests/test-clone-uncompressed.t --- a/tests/test-clone-uncompressed.t Mon Apr 19 19:10:49 2021 +0200 +++ b/tests/test-clone-uncompressed.t Mon Apr 19 19:12:28 2021 +0200 @@ -433,14 +433,35 @@ extension for delaying the server process so we reliably can modify the repo while cloning - $ cat > delayer.py < 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 < 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 -r 52cee44aa1a0 -r faa43f09ad98 tests/testlib/ext-stream-clone-steps.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testlib/ext-stream-clone-steps.py Mon Apr 19 19:12:28 2021 +0200 @@ -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 + )