From patchwork Thu May 20 14:19:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D10753: persistent-nodemap: add a way to make the picked uid predictable From: phabricator X-Patchwork-Id: 49074 Message-Id: To: Phabricator Cc: mercurial-devel@mercurial-scm.org Date: Thu, 20 May 2021 14:19:42 +0000 marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This will make the test less volatile and therefore easier to maintain. I am setting this is for the persistent nodemap docket first, but my target is to use similar logic for the revlogv2 (and co) test. For persisent nodemap, they are too many different in how each test variants (with rust, without rust, etc) needs new uid for this be really useful (right now). However it will be directly useful for the revlogv2 logic. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10753 AFFECTED FILES mercurial/revlogutils/nodemap.py tests/run-tests.py CHANGE DETAILS To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel diff --git a/tests/run-tests.py b/tests/run-tests.py --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -1376,6 +1376,8 @@ env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') or '' env['HGEMITWARNINGS'] = '1' env['TESTTMP'] = _bytes2sys(self._testtmp) + docket_id_file = os.path.join(_bytes2sys(self._testtmp), 'DOCKETID') + env['HGTEST_DOCKETIDFILE'] = docket_id_file env['TESTNAME'] = self.name env['HOME'] = _bytes2sys(self._testtmp) if os.name == 'nt': diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py --- a/mercurial/revlogutils/nodemap.py +++ b/mercurial/revlogutils/nodemap.py @@ -10,13 +10,16 @@ import errno import os +import random import re import struct from ..node import hex from .. import ( + encoding, error, + pycompat, util, ) @@ -288,6 +291,45 @@ return hex(os.urandom(ID_SIZE)) +# some special test logic to avoid anoying random output in the test +stable_docket_file = encoding.environ.get(b'HGTEST_DOCKETIDFILE') + +if stable_docket_file: + + def _make_uid(): + try: + with open(stable_docket_file, mode='rb') as f: + seed = f.read().strip() + except IOError as inst: + if inst.errno != errno.ENOENT: + raise + seed = b'4' # chosen by a fair dice roll. garanteed to be random + if pycompat.ispy3: + iter_seed = iter(seed) + else: + iter_seed = (ord(c) for c in seed) + # some basic circular sum hashing on 64 bits + int_seed = 0 + low_mask = int('1' * 35, 2) + for i in iter_seed: + high_part = int_seed >> 35 + low_part = (int_seed & low_mask) << 28 + int_seed = high_part + low_part + i + r = random.Random() + if pycompat.ispy3: + r.seed(int_seed, version=1) + else: + r.seed(int_seed) + # once we drop python 3.8 support we can simply use r.randbytes + raw = r.getrandbits(ID_SIZE * 8) + assert ID_SIZE == 8 + p = struct.pack('>Q', raw) + new = hex(p) + with open(stable_docket_file, 'wb') as f: + f.write(new) + return new + + class NodeMapDocket(object): """metadata associated with persistent nodemap data