Patchwork [2,of,2] run-tests: add --rev to run tests with specific version of hg

login
register
mail settings
Submitter timeless@mozdev.org
Date April 7, 2016, 11:21 a.m.
Message ID <5a5505c3a9fd803099b9.1460028108@waste.org>
Download mbox | patch
Permalink /patch/14422/
State Deferred
Headers show

Comments

timeless@mozdev.org - April 7, 2016, 11:21 a.m.
# HG changeset patch
# User timeless <timeless@mozdev.org>
# Date 1460027637 0
#      Thu Apr 07 11:13:57 2016 +0000
# Node ID 5a5505c3a9fd803099b97edee2e554d02ddf06a3
# Parent  502190ebde8f7489eec812006cfb1f7025a73562
run-tests: add --rev to run tests with specific version of hg

This is mostly designed for use outside of hg.

If you want to run tests based on the version of Mercurial you're
targeting, you will probably need a wrapper test, as seen in the
tests provided with this commit.

* We can not use "archive" because the version information is lost.
* We have to include the tag commit too, otherwise the version
calculation will mess up.
* Old versions of mercurial don't necessarily support the repo format
that the current repo has, so we have to blacklist any unsupported
features.
* Certain versions of mercurial choke on the obsstore format, so we
remove it.
Pierre-Yves David - April 13, 2016, 6:37 a.m.
On 04/07/2016 04:21 AM, timeless wrote:
> # HG changeset patch
> # User timeless <timeless@mozdev.org>
> # Date 1460027637 0
> #      Thu Apr 07 11:13:57 2016 +0000
> # Node ID 5a5505c3a9fd803099b97edee2e554d02ddf06a3
> # Parent  502190ebde8f7489eec812006cfb1f7025a73562
> run-tests: add --rev to run tests with specific version of hg
>
> This is mostly designed for use outside of hg.
>
> If you want to run tests based on the version of Mercurial you're
> targeting, you will probably need a wrapper test, as seen in the
> tests provided with this commit.
>
> * We can not use "archive" because the version information is lost.

Can you elaborate on what we do use? (and some more details about how 
all this work)
timeless - April 13, 2016, 4:08 p.m.
timeless wrote:
>> If you want to run tests based on the version of Mercurial you're
>> targeting, you will probably need a wrapper test, as seen in the
>> tests provided with this commit.
>>
>> * We can not use "archive" because the version information is lost.

Pierre-Yves David wrote:
> Can you elaborate on what we do use? (and some more details about how all
> this work)

* We create a clone in $HGTMP/source containing at least the specified
revision, and applicable tags (in order to ensure that tag information is
available for hg version), using a repository format supported by the specified
version of hg.

Patch

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -263,6 +263,9 @@ 
     parser.add_option("--with-python3", metavar="PYTHON3",
                       help="Python 3 interpreter (if running under Python 2)"
                            " (TEMPORARY)")
+    parser.add_option('--rev', type="string",
+                      metavar="rev",
+                      help="run tests using the given revision")
     parser.add_option('--extra-config-opt', action="append",
                       help='set the given config opt in the test hgrc')
     parser.add_option('--random', action="store_true",
@@ -294,12 +297,16 @@ 
 
     if options.with_hg:
         options.with_hg = canonpath(_bytespath(options.with_hg))
+        if options.rev:
+            parser.error('--with-hg and --rev are incompatible')
         if not (os.path.isfile(options.with_hg) and
                 os.access(options.with_hg, os.X_OK)):
             parser.error('--with-hg must specify an executable hg script')
         if not os.path.basename(options.with_hg) == b'hg':
             sys.stderr.write('warning: --with-hg should specify an hg script\n')
     if options.local:
+        if options.rev:
+            parser.error('--local and --rev are incompatible')
         testdir = os.path.dirname(_bytespath(canonpath(sys.argv[0])))
         hgbin = os.path.join(os.path.dirname(testdir), b'hg')
         if os.name != 'nt' and not os.access(hgbin, os.X_OK):
@@ -2330,6 +2337,96 @@ 
             script = _bytespath(script)
             exe = _bytespath(exe)
         hgroot = os.path.dirname(os.path.dirname(script))
+        if self.options.rev:
+            check = "set:mercurial/*.py and " \
+                    'grep(r"requirements.*%s|%s.*requirements")'
+            procs = []
+            rev = self.options.rev
+            with open(os.path.join(hgroot, '.hg', 'requires'), 'r') as requires:
+                for r in requires:
+                    r = r.strip()
+                    proc = subprocess.Popen(['hg', 'locate',
+                                             '--cwd', hgroot,
+                                             '--rev', rev,
+                                             check % (r, r),
+                                            ],
+                                            stderr=subprocess.STDOUT,
+                                            stdout=subprocess.PIPE)
+                    procs.append((r, proc))
+            badreqs = set()
+            while procs:
+                r, proc = procs.pop(0)
+                ret = proc.wait()
+                if wifexited(ret):
+                    ret = os.WEXITSTATUS(ret)
+                if ret:
+                    badreqs.add(r)
+            tempsrc = os.path.join(self._hgtmp, b"source")
+            clone = ['hg', 'clone',
+                     hgroot,
+                     tempsrc,
+                    ]
+            if badreqs:
+                tag = rev
+                proc = subprocess.Popen([
+                          'hg', 'log',
+                          '--cwd', hgroot,
+                          '.hgtags',
+                          '-r', 'desc("Added tag %s for changeset")' % rev,
+                          '-T', '{node}',
+                       ],
+                       stderr=subprocess.STDOUT,
+                       stdout=subprocess.PIPE)
+                ret = proc.wait()
+                if wifexited(ret):
+                    ret = os.WEXITSTATUS(ret)
+                if ret == 0:
+                    tag, _err = proc.communicate()
+                clone.extend(['-r', tag,
+                              '-u', rev,
+                              '--pull',
+                             ])
+                for r in badreqs:
+                    # There are two common ways to disable a repository format
+                    # and there isn't a consistent way to determine which
+                    # applies. Thankfully, unlike obsstore, there's no harm in
+                    # providing both.
+                    clone.extend(['--config', 'format.%s=false' % r,
+                                  '--config', 'format.use%s=false' % r,
+                                 ])
+            else:
+                clone.extend(['-u', self.options.rev,
+                             ])
+
+            proc = subprocess.Popen(clone,
+                                    stderr=subprocess.STDOUT,
+                                    stdout=subprocess.PIPE)
+            ret = proc.wait()
+            if wifexited(ret):
+                ret = os.WEXITSTATUS(ret)
+            if ret:
+                _out, _err = proc.communicate()
+                out = b"hg clone failed (%d):\n" % ret
+                if _out:
+                    out += _out
+                if _err:
+                    out += _err
+                if PYTHON3:
+                    sys.stdout.buffer.write(out)
+                else:
+                    sys.stdout.write(out)
+                sys.exit(1)
+            try:
+                # The current obbstore version (1) is horribly incompatible
+                # with certain older versions of hg which are incapable of
+                # being told to ignore the obsstore. And we don't need an
+                # obsstore for our purposes.
+                # We do need a repository to allow setup to calculate the
+                # version correctly.
+                os.remove(os.path.join(tempsrc, '.hg', 'store', 'obsstore'))
+            except OSError:
+                pass
+            hgroot = tempsrc
         self._hgroot = hgroot
         os.chdir(hgroot)
         nohome = b'--home=""'
diff --git a/tests/test-run-tests.t b/tests/test-run-tests.t
--- a/tests/test-run-tests.t
+++ b/tests/test-run-tests.t
@@ -815,3 +815,32 @@ 
   # Ran 1 tests, 0 skipped, 0 warned, 1 failed.
   python hash seed: * (glob)
   [1]
+
+support for running a different version of mercurial
+note that it is typical for ~1/5 tests not to pass when using older
+versions of mercurial...
+
+  $ cat >> test-version.t <<EOF
+  >   $ hg version
+  >   Mercurial Distributed SCM (version unknown)
+  >   
+  >   Copyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others
+  >   This is free software; see the source for copying conditions. There is NO
+  >   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  > EOF
+  $ run-tests.py --pure --rev 1.2 test-version.t
+  .
+  # Ran 1 tests, 0 skipped, 0 warned, 0 failed.
+
+To run tests at a version from the revision you select from --rev
+you need a test which introspects the source directory
+
+  $ cat > test-old-basic.t <<EOF
+  >   $ run-tests.py --pure --local ../../source/tests/test-basic.t
+  >   .
+  >   # Ran 1 tests, 0 skipped, 0 warned, 0 failed.
+  > EOF
+  $ run-tests.py --pure --rev 1.7 test-old-basic.t
+  .
+  # Ran 1 tests, 0 skipped, 0 warned, 0 failed.
+