##// END OF EJS Templates
discovery: move common heads computation inside partialdiscovery object...
discovery: move common heads computation inside partialdiscovery object This remove one of the private attribute access. In additions, head tracking and computation is a typical operation we can speed up using Rust.

File last commit:

r41083:d9f439fc default
r41148:9815d333 default
Show More
test-rust-ancestor.py
107 lines | 4.1 KiB | text/x-python | PythonLexer
/ tests / test-rust-ancestor.py
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 from __future__ import absolute_import
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 import sys
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 import unittest
try:
from mercurial import rustext
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 rustext.__name__ # trigger immediate actual import
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 except ImportError:
rustext = None
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 else:
# this would fail already without appropriate ancestor.__package__
from mercurial.rustext.ancestor import AncestorsIterator
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004
try:
from mercurial.cext import parsers as cparsers
except ImportError:
cparsers = None
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 # picked from test-parse-index2, copied rather than imported
# so that it stays stable even if test-parse-index2 changes or disappears.
data_non_inlined = (
b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01D\x19'
b'\x00\x07e\x12\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff'
b'\xff\xff\xff\xff\xd1\xf4\xbb\xb0\xbe\xfc\x13\xbd\x8c\xd3\x9d'
b'\x0f\xcd\xd9;\x8c\x07\x8cJ/\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x01D\x19\x00\x00\x00\x00\x00\xdf\x00'
b'\x00\x01q\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\xff'
b'\xff\xff\xff\xc1\x12\xb9\x04\x96\xa4Z1t\x91\xdfsJ\x90\xf0\x9bh'
b'\x07l&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x01D\xf8\x00\x00\x00\x00\x01\x1b\x00\x00\x01\xb8\x00\x00'
b'\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\xff\xff\xff\xff\x02\n'
b'\x0e\xc6&\xa1\x92\xae6\x0b\x02i\xfe-\xe5\xbao\x05\xd1\xe7\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01F'
b'\x13\x00\x00\x00\x00\x01\xec\x00\x00\x03\x06\x00\x00\x00\x01'
b'\x00\x00\x00\x03\x00\x00\x00\x02\xff\xff\xff\xff\x12\xcb\xeby1'
b'\xb6\r\x98B\xcb\x07\xbd`\x8f\x92\xd9\xc4\x84\xbdK\x00\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00'
)
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 @unittest.skipIf(rustext is None or cparsers is None,
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 "rustext or the C Extension parsers module "
"ancestor relies on is not available")
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 class rustancestorstest(unittest.TestCase):
"""Test the correctness of binding to Rust code.
This test is merely for the binding to Rust itself: extraction of
Python variable, giving back the results etc.
It is not meant to test the algorithmic correctness of the operations
on ancestors it provides. Hence the very simple embedded index data is
good enough.
Algorithmic correctness is asserted by the Rust unit tests.
"""
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 def parseindex(self):
return cparsers.parse_index2(data_non_inlined, False)[0]
def testiteratorrevlist(self):
idx = self.parseindex()
# checking test assumption about the index binary data:
self.assertEqual({i: (r[5], r[6]) for i, r in enumerate(idx)},
{0: (-1, -1),
1: (0, -1),
2: (1, -1),
3: (2, -1)})
ait = AncestorsIterator(idx, [3], 0, True)
self.assertEqual([r for r in ait], [3, 2, 1, 0])
ait = AncestorsIterator(idx, [3], 0, False)
self.assertEqual([r for r in ait], [2, 1, 0])
def testrefcount(self):
idx = self.parseindex()
start_count = sys.getrefcount(idx)
# refcount increases upon iterator init...
ait = AncestorsIterator(idx, [3], 0, True)
self.assertEqual(sys.getrefcount(idx), start_count + 1)
self.assertEqual(next(ait), 3)
# and decreases once the iterator is removed
del ait
self.assertEqual(sys.getrefcount(idx), start_count)
# and removing ref to the index after iterator init is no issue
ait = AncestorsIterator(idx, [3], 0, True)
del idx
self.assertEqual([r for r in ait], [3, 2, 1, 0])
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004
def testgrapherror(self):
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 data = (data_non_inlined[:64 + 27] +
b'\xf2' +
data_non_inlined[64 + 28:])
idx = cparsers.parse_index2(data, False)[0]
with self.assertRaises(rustext.GraphError) as arc:
AncestorsIterator(idx, [1], -1, False)
exc = arc.exception
self.assertIsInstance(exc, ValueError)
# rust-cpython issues appropriate str instances for Python 2 and 3
self.assertEqual(exc.args, ('ParentOutOfRange', 1))
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004
if __name__ == '__main__':
import silenttestrunner
silenttestrunner.main(__name__)