tests/test-parseindex2.py
author Chris Jerdonek <chris.jerdonek@gmail.com>
Fri, 29 Nov 2013 12:36:28 -0800
changeset 20155 21dafd8546d1
parent 20109 e57c532c3835
child 20159 96b2dd77c85d
permissions -rw-r--r--
parsers: fail fast if Python has wrong minor version (issue4110) This change causes an informative ImportError to be raised when importing the extension module parsers if the minor version of the currently-running Python interpreter doesn't match that of the Python that was used when compiling the extension module. Here is an example of what the new error looks like: Traceback (most recent call last): File "test.py", line 1, in <module> import mercurial.parsers ImportError: Python minor version mismatch: The Mercurial extension modules were compiled with Python 2.7.6, but Mercurial is currently using Python with sys.hexversion=33883888: Python 2.5.6 (r256:88840, Nov 18 2012, 05:37:10) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] at: /opt/local/Library/Frameworks/Python.framework/Versions/2.5/Resources/ Python.app/Contents/MacOS/Python The reason for raising an error in this scenario is that Python's C API is known not to be compatible from minor version to minor version, even if sys.api_version is the same. See for example this Python bug report about incompatibilities between 2.5 and 2.6+: http://bugs.python.org/issue8118 These incompatibilities can cause Mercurial to break in mysterious, unforeseen ways. For example, when Mercurial compiled with Python 2.7 was run with 2.5, the following crash occurred when running "hg status": http://bz.selenic.com/show_bug.cgi?id=4110 After this crash was fixed, running with Python 2.5 no longer crashes, but the following puzzling behavior still occurs: $ hg status ... File ".../mercurial/changelog.py", line 123, in __init__ revlog.revlog.__init__(self, opener, "00changelog.i") File ".../mercurial/revlog.py", line 251, in __init__ d = self._io.parseindex(i, self._inline) File ".../mercurial/revlog.py", line 158, in parseindex index, cache = parsers.parse_index2(data, inline) TypeError: data is not a string which can be reproduced more simply with: import mercurial.parsers as parsers parsers.parse_index2("", True) Both the crash and the TypeError occurred because the Python C API's PyString_Check returns the wrong value when the C header files from Python 2.7 are run with Python 2.5. This is an example of an incompatibility of the sort mentioned in the Python bug report above. Failing fast with an informative error message will result in a better user experience in cases like the above. The information in the ImportError will also simplify troubleshooting for those on Mercurial mailing lists, the bug tracker, etc. This patch only adds the version check to parsers.c, which is sufficient to affect command-line commands like "hg status" and "hg summary". An idea for a future improvement is to move the version-checking C code to a more central location, and have it run when importing all Mercurial extension modules and not just parsers.c.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     1
from mercurial import parsers
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     2
from mercurial.node import nullid, nullrev
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     3
import struct
20155
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
     4
import subprocess
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
     5
import sys
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     6
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     7
# This unit test compares the return value of the original Python
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     8
# implementation of parseindex and the new C implementation for
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
     9
# an index file with and without inlined data
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    10
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    11
# original python implementation
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    12
def gettype(q):
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    13
    return int(q & 0xFFFF)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    14
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    15
def offset_type(offset, type):
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    16
    return long(long(offset) << 16 | type)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    17
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    18
indexformatng = ">Qiiiiii20s12x"
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    19
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    20
def py_parseindex(data, inline) :
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    21
    s = 64
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    22
    cache = None
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    23
    index = []
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    24
    nodemap =  {nullid: nullrev}
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    25
    n = off = 0
13253
61c9bc3da402 revlog: remove lazy index
Matt Mackall <mpm@selenic.com>
parents: 8117
diff changeset
    26
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    27
    l = len(data) - s
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    28
    append = index.append
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    29
    if inline:
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    30
        cache = (0, data)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    31
        while off <= l:
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    32
            e = struct.unpack(indexformatng, data[off:off + s])
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    33
            nodemap[e[7]] = n
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    34
            append(e)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    35
            n += 1
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    36
            if e[1] < 0:
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    37
                break
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    38
            off += e[1] + s
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    39
    else:
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    40
        while off <= l:
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    41
            e = struct.unpack(indexformatng, data[off:off + s])
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    42
            nodemap[e[7]] = n
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    43
            append(e)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    44
            n += 1
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    45
            off += s
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    46
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    47
    e = list(index[0])
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    48
    type = gettype(e[0])
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    49
    e[0] = offset_type(0, type)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    50
    index[0] = tuple(e)
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    51
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    52
    # add the magic null revision at -1
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    53
    index.append((0, 0, 0, -1, -1, -1, -1, nullid))
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    54
13254
5ef5eb1f3515 revlog: only build the nodemap on demand
Matt Mackall <mpm@selenic.com>
parents: 13253
diff changeset
    55
    return index, cache
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    56
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    57
data_inlined = '\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x8c' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    58
    '\x00\x00\x04\x07\x00\x00\x00\x00\x00\x00\x15\x15\xff\xff\xff' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    59
    '\xff\xff\xff\xff\xff\xebG\x97\xb7\x1fB\x04\xcf\x13V\x81\tw\x1b' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    60
    'w\xdduR\xda\xc6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    61
    'x\x9c\x9d\x93?O\xc30\x10\xc5\xf7|\x8a\xdb\x9a\xa8m\x06\xd8*\x95' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    62
    '\x81B\xa1\xa2\xa2R\xcb\x86Pd\x9a\x0b5$vd_\x04\xfd\xf6\x9c\xff@' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    63
    '\x11!\x0b\xd9\xec\xf7\xbbw\xe7gG6\xad6\x04\xdaN\xc0\x92\xa0$)' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    64
    '\xb1\x82\xa2\xd1%\x16\xa4\x8b7\xa9\xca\xd4-\xb2Y\x02\xfc\xc9' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    65
    '\xcaS\xf9\xaeX\xed\xb6\xd77Q\x02\x83\xd4\x19\xf5--Y\xea\xe1W' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    66
    '\xab\xed\x10\xceR\x0f_\xdf\xdf\r\xe1,\xf5\xf0\xcb\xf5 \xceR\x0f' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    67
    '_\xdc\x0e\x0e\xc3R\x0f_\xae\x96\x9b!\x9e\xa5\x1e\xbf\xdb,\x06' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    68
    '\xc7q\x9a/\x88\x82\xc3B\xea\xb5\xb4TJ\x93\xb6\x82\x0e\xe16\xe6' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    69
    'KQ\xdb\xaf\xecG\xa3\xd1 \x01\xd3\x0b_^\xe8\xaa\xa0\xae\xad\xd1' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    70
    '&\xbef\x1bz\x08\xb0|\xc9Xz\x06\xf6Z\x91\x90J\xaa\x17\x90\xaa' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    71
    '\xd2\xa6\x11$5C\xcf\xba#\xa0\x03\x02*2\x92-\xfc\xb1\x94\xdf\xe2' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    72
    '\xae\xb8\'m\x8ey0^\x85\xd3\x82\xb4\xf0`:\x9c\x00\x8a\xfd\x01' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    73
    '\xb0\xc6\x86\x8b\xdd\xae\x80\xf3\xa9\x9fd\x16\n\x00R%\x1a\x06' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    74
    '\xe9\xd8b\x98\x1d\xf4\xf3+\x9bf\x01\xd8p\x1b\xf3.\xed\x9f^g\xc3' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    75
    '^\xd9W81T\xdb\xd5\x04sx|\xf2\xeb\xd6`%?x\xed"\x831\xbf\xf3\xdc' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    76
    'b\xeb%gaY\xe1\xad\x9f\xb9f\'1w\xa9\xa5a\x83s\x82J\xb98\xbc4\x8b' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    77
    '\x83\x00\x9f$z\xb8#\xa5\xb1\xdf\x98\xd9\xec\x1b\x89O\xe3Ts\x9a4' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    78
    '\x17m\x8b\xfc\x8f\xa5\x95\x9a\xfc\xfa\xed,\xe5|\xa1\xfe\x15\xb9' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    79
    '\xbc\xb2\x93\x1f\xf2\x95\xff\xdf,\x1a\xc5\xe7\x17*\x93Oz:>\x0e'
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    80
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    81
data_non_inlined = '\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01D\x19' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    82
    '\x00\x07e\x12\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    83
    '\xff\xff\xff\xff\xd1\xf4\xbb\xb0\xbe\xfc\x13\xbd\x8c\xd3\x9d' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    84
    '\x0f\xcd\xd9;\x8c\x07\x8cJ/\x00\x00\x00\x00\x00\x00\x00\x00\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    85
    '\x00\x00\x00\x00\x00\x00\x01D\x19\x00\x00\x00\x00\x00\xdf\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    86
    '\x00\x01q\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\xff' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    87
    '\xff\xff\xff\xc1\x12\xb9\x04\x96\xa4Z1t\x91\xdfsJ\x90\xf0\x9bh' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    88
    '\x07l&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    89
    '\x00\x01D\xf8\x00\x00\x00\x00\x01\x1b\x00\x00\x01\xb8\x00\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    90
    '\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\xff\xff\xff\xff\x02\n' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    91
    '\x0e\xc6&\xa1\x92\xae6\x0b\x02i\xfe-\xe5\xbao\x05\xd1\xe7\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    92
    '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01F' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    93
    '\x13\x00\x00\x00\x00\x01\xec\x00\x00\x03\x06\x00\x00\x00\x01' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    94
    '\x00\x00\x00\x03\x00\x00\x00\x02\xff\xff\xff\xff\x12\xcb\xeby1' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    95
    '\xb6\r\x98B\xcb\x07\xbd`\x8f\x92\xd9\xc4\x84\xbdK\x00\x00\x00' \
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    96
    '\x00\x00\x00\x00\x00\x00\x00\x00\x00'
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
    97
16363
2cdd7e63211b parsers: incrementally parse the revlog index in C
Bryan O'Sullivan <bryano@fb.com>
parents: 13254
diff changeset
    98
def parse_index2(data, inline):
2cdd7e63211b parsers: incrementally parse the revlog index in C
Bryan O'Sullivan <bryano@fb.com>
parents: 13254
diff changeset
    99
    index, chunkcache = parsers.parse_index2(data, inline)
2cdd7e63211b parsers: incrementally parse the revlog index in C
Bryan O'Sullivan <bryano@fb.com>
parents: 13254
diff changeset
   100
    return list(index), chunkcache
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   101
20155
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   102
def importparsers(hexversion):
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   103
    """Import mercurial.parsers with the given sys.hexversion."""
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   104
    # The file parsers.c inspects sys.hexversion to determine the version
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   105
    # of the currently-running Python interpreter, so we monkey-patch
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   106
    # sys.hexversion to simulate using different versions.
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   107
    code = ("import sys; sys.hexversion=%s; "
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   108
            "import mercurial.parsers" % hexversion)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   109
    cmd = "python -c \"%s\"" % code
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   110
    # We need to do these tests inside a subprocess because parser.c's
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   111
    # version-checking code happens inside the module init function, and
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   112
    # when using reload() to reimport an extension module, "The init function
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   113
    # of extension modules is not called a second time"
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   114
    # (from http://docs.python.org/2/library/functions.html?#reload).
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   115
    p = subprocess.Popen(cmd, shell=True,
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   116
                         stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   117
    return p.communicate()  # returns stdout, stderr
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   118
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   119
def printhexfail(testnumber, hexversion, msg):
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   120
    try:
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   121
        hexstring = hex(hexversion)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   122
    except TypeError:
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   123
        hexstring = None
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   124
    print ("%s) using Python %s and patched sys.hexversion %r (%r): %s" %
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   125
           (testnumber, sys.version_info, hexversion, hexstring, msg))
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   126
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   127
def testversionokay(testnumber, hexversion):
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   128
    stdout, stderr = importparsers(hexversion)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   129
    if stdout:
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   130
        printhexfail(testnumber, hexversion,
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   131
                     "Expected no stdout but got: %r" % stdout)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   132
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   133
def testversionfail(testnumber, hexversion):
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   134
    stdout, stderr = importparsers(hexversion)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   135
    if not "ImportError: Python minor version mismatch" in stdout:
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   136
        printhexfail(testnumber, hexversion,
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   137
                     "Expected stdout to contain %r but got: %r" %
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   138
                     (errstring, stdout))
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   139
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   140
def makehex(major, minor, micro):
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   141
    return int("%x%02x%02x00" % (major, minor, micro), 16)
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   142
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   143
def runversiontests():
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   144
    """Test importing parsers using different Python versions."""
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   145
    info = sys.version_info
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   146
    major, minor, micro = info[0], info[1], info[2]
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   147
    # Test same major-minor versions.
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   148
    testversionokay(1, makehex(major, minor, micro))
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   149
    testversionokay(2, makehex(major, minor, micro + 1))
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   150
    # Test different major-minor versions.
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   151
    testversionfail(3, makehex(major + 1, minor, micro))
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   152
    testversionfail(4, makehex(major, minor + 1, micro))
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   153
    testversionfail(5, "'foo'")
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   154
16363
2cdd7e63211b parsers: incrementally parse the revlog index in C
Bryan O'Sullivan <bryano@fb.com>
parents: 13254
diff changeset
   155
def runtest() :
20155
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   156
    runversiontests()
21dafd8546d1 parsers: fail fast if Python has wrong minor version (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 20109
diff changeset
   157
20109
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   158
    # Check that parse_index2() raises TypeError on bad arguments.
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   159
    try:
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   160
        parse_index2(0, True)
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   161
    except TypeError:
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   162
        pass
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   163
    else:
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   164
        print "Expected to get TypeError."
e57c532c3835 parse_index2: fix crash on bad argument type (issue4110)
Chris Jerdonek <chris.jerdonek@gmail.com>
parents: 16620
diff changeset
   165
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   166
    py_res_1 = py_parseindex(data_inlined, True)
16363
2cdd7e63211b parsers: incrementally parse the revlog index in C
Bryan O'Sullivan <bryano@fb.com>
parents: 13254
diff changeset
   167
    c_res_1 = parse_index2(data_inlined, True)
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   168
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   169
    py_res_2 = py_parseindex(data_non_inlined, False)
16363
2cdd7e63211b parsers: incrementally parse the revlog index in C
Bryan O'Sullivan <bryano@fb.com>
parents: 13254
diff changeset
   170
    c_res_2 = parse_index2(data_non_inlined, False)
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   171
8117
2b30d8488819 remove unnecessary outer parenthesis in if-statements
Martin Geisler <mg@lazybytes.net>
parents: 7110
diff changeset
   172
    if py_res_1 != c_res_1:
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   173
        print "Parse index result (with inlined data) differs!"
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   174
8117
2b30d8488819 remove unnecessary outer parenthesis in if-statements
Martin Geisler <mg@lazybytes.net>
parents: 7110
diff changeset
   175
    if py_res_2 != c_res_2:
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   176
        print "Parse index result (no inlined data) differs!"
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   177
16414
e8d37b78acfb parsers: use base-16 trie for faster node->rev mapping
Bryan O'Sullivan <bryano@fb.com>
parents: 16363
diff changeset
   178
    ix = parsers.parse_index2(data_inlined, True)[0]
e8d37b78acfb parsers: use base-16 trie for faster node->rev mapping
Bryan O'Sullivan <bryano@fb.com>
parents: 16363
diff changeset
   179
    for i, r in enumerate(ix):
e8d37b78acfb parsers: use base-16 trie for faster node->rev mapping
Bryan O'Sullivan <bryano@fb.com>
parents: 16363
diff changeset
   180
        if r[7] == nullid:
e8d37b78acfb parsers: use base-16 trie for faster node->rev mapping
Bryan O'Sullivan <bryano@fb.com>
parents: 16363
diff changeset
   181
            i = -1
16620
e22d6b1dec1d tests: fix test-parseindex2.py when run with --pure
Bryan O'Sullivan <bryano@fb.com>
parents: 16414
diff changeset
   182
        try:
e22d6b1dec1d tests: fix test-parseindex2.py when run with --pure
Bryan O'Sullivan <bryano@fb.com>
parents: 16414
diff changeset
   183
            if ix[r[7]] != i:
e22d6b1dec1d tests: fix test-parseindex2.py when run with --pure
Bryan O'Sullivan <bryano@fb.com>
parents: 16414
diff changeset
   184
                print 'Reverse lookup inconsistent for %r' % r[7].encode('hex')
e22d6b1dec1d tests: fix test-parseindex2.py when run with --pure
Bryan O'Sullivan <bryano@fb.com>
parents: 16414
diff changeset
   185
        except TypeError:
e22d6b1dec1d tests: fix test-parseindex2.py when run with --pure
Bryan O'Sullivan <bryano@fb.com>
parents: 16414
diff changeset
   186
            # pure version doesn't support this
e22d6b1dec1d tests: fix test-parseindex2.py when run with --pure
Bryan O'Sullivan <bryano@fb.com>
parents: 16414
diff changeset
   187
            break
16414
e8d37b78acfb parsers: use base-16 trie for faster node->rev mapping
Bryan O'Sullivan <bryano@fb.com>
parents: 16363
diff changeset
   188
7110
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   189
    print "done"
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   190
75fdc39b6172 Add parseindex2.py test case
Bernhard Leiner <bleiner@gmail.com>
parents:
diff changeset
   191
runtest()