##// END OF EJS Templates
rust-pyo3: dagop submodule implementation...
rust-pyo3: dagop submodule implementation This is the first demonstration that the passing of objects through the Python interpreter from `rustext` to `pyo3_rustext` actually works. In the Python tests, we conflate the presence of the `pyo3_rustext` package with that of `rustext`, as we do not plan to support building one and not the other (we hope to convert fully to PyO3 soon). The skipping is actually done by the base test class. The implementation of `rank` is as trivial as it was in `hg-cpython`, yet it required to be able to convert exceptions from `vcsgraph`.

File last commit:

r53310:20fe0bf9 default
r53310:20fe0bf9 default
Show More
test-rust-ancestor.py
167 lines | 5.8 KiB | text/x-python | PythonLexer
/ tests / test-rust-ancestor.py
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 import sys
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004
Joerg Sonnenberger
node: import symbols explicitly...
r46729 from mercurial.node import wdirrev
Georges Racinet
rust-cpython: raising error.WdirUnsupported...
r41386
test: extract some generic data and utility from test-rust-ancestor.py...
r44397 from mercurial.testing import revlog as revlogtesting
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 try:
Georges Racinet
rust-pyo3: dagop submodule implementation...
r53310 from mercurial import pyo3_rustext, rustext
Augie Fackler
formatting: blacken the codebase...
r43346
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 rustext.__name__ # trigger immediate actual import
Georges Racinet
rust-pyo3: dagop submodule implementation...
r53310 pyo3_rustext.__name__
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 except ImportError:
Georges Racinet
rust-pyo3: dagop submodule implementation...
r53310 rustext = pyo3_rustext = None
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 else:
# this would fail already without appropriate ancestor.__package__
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 from mercurial.rustext.ancestor import (
AncestorsIterator,
Georges Racinet
rust-cpython: bindings for MissingAncestors...
r41224 LazyAncestors,
MissingAncestors,
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 )
Georges Racinet
rust-cpython: binding for headrevs()...
r41843 from mercurial.rustext import dagop
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
Georges Racinet on incendie.racinet.fr
rust-python-testing: separated base test classes...
r52137 class rustancestorstest(revlogtesting.RustRevlogBasedTestBase):
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 """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 testiteratorrevlist(self):
Georges Racinet
rust-index: using the `hg::index::Index` in ancestors iterator and lazy set...
r52132 idx = self.parserustindex()
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 # checking test assumption about the index binary data:
Augie Fackler
formatting: blacken the codebase...
r43346 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)},
)
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 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])
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 def testlazyancestors(self):
Georges Racinet
rust-index: using the `hg::index::Index` in ancestors iterator and lazy set...
r52132 idx = self.parserustindex()
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 start_count = sys.getrefcount(idx.inner) # should be 2 (see Python doc)
Augie Fackler
formatting: blacken the codebase...
r43346 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)},
)
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 lazy = LazyAncestors(idx, [3], 0, True)
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 # the LazyAncestors instance holds just one reference to the
# inner revlog.
self.assertEqual(sys.getrefcount(idx.inner), start_count + 1)
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149
self.assertTrue(2 in lazy)
self.assertTrue(bool(lazy))
self.assertEqual(list(lazy), [3, 2, 1, 0])
# a second time to validate that we spawn new iterators
self.assertEqual(list(lazy), [3, 2, 1, 0])
# now let's watch the refcounts closer
ait = iter(lazy)
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 self.assertEqual(sys.getrefcount(idx.inner), start_count + 2)
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 del ait
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 self.assertEqual(sys.getrefcount(idx.inner), start_count + 1)
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 del lazy
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 self.assertEqual(sys.getrefcount(idx.inner), start_count)
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149
# let's check bool for an empty one
self.assertFalse(LazyAncestors(idx, [0], 0, False))
Georges Racinet
rust-cpython: bindings for MissingAncestors...
r41224 def testmissingancestors(self):
Georges Racinet on incendie.racinet.fr
rust-index: using `hg::index::Index` in MissingAncestors...
r52133 idx = self.parserustindex()
Georges Racinet
rust-cpython: bindings for MissingAncestors...
r41224 missanc = MissingAncestors(idx, [1])
self.assertTrue(missanc.hasbases())
self.assertEqual(missanc.missingancestors([3]), [2, 3])
missanc.addbases({2})
Georges Racinet
rust-cpython: set conversion for MissingAncestors.bases()...
r41279 self.assertEqual(missanc.bases(), {1, 2})
Georges Racinet
rust-cpython: bindings for MissingAncestors...
r41224 self.assertEqual(missanc.missingancestors([3]), [3])
Georges Racinet
rust: MissingAncestors.basesheads()...
r41282 self.assertEqual(missanc.basesheads(), {2})
Georges Racinet
rust-cpython: bindings for MissingAncestors...
r41224
def testmissingancestorsremove(self):
Georges Racinet on incendie.racinet.fr
rust-index: using `hg::index::Index` in MissingAncestors...
r52133 idx = self.parserustindex()
Georges Racinet
rust-cpython: bindings for MissingAncestors...
r41224 missanc = MissingAncestors(idx, [1])
revs = {0, 1, 2, 3}
missanc.removeancestorsfrom(revs)
self.assertEqual(revs, {2, 3})
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 def testrefcount(self):
Georges Racinet
rust-index: using the `hg::index::Index` in ancestors iterator and lazy set...
r52132 idx = self.parserustindex()
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 start_count = sys.getrefcount(idx.inner)
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083
# refcount increases upon iterator init...
ait = AncestorsIterator(idx, [3], 0, True)
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 self.assertEqual(sys.getrefcount(idx.inner), start_count + 1)
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 self.assertEqual(next(ait), 3)
# and decreases once the iterator is removed
del ait
Georges Racinet
testing: stop skipping all Python tests of Rust revlog...
r53302 self.assertEqual(sys.getrefcount(idx.inner), start_count)
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083
# and removing ref to the index after iterator init is no issue
ait = AncestorsIterator(idx, [3], 0, True)
del idx
Georges Racinet
rust-cpython: binding for LazyAncestors...
r41149 self.assertEqual(list(ait), [3, 2, 1, 0])
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004
Georges Racinet
rust-index: using the `hg::index::Index` in ancestors iterator and lazy set...
r52132 # the index is not tracked by the GC, hence there is nothing more
# we can assert to check that it is properly deleted once its refcount
# drops to 0
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 def testgrapherror(self):
Augie Fackler
formatting: blacken the codebase...
r43346 data = (
test: extract some generic data and utility from test-rust-ancestor.py...
r44397 revlogtesting.data_non_inlined[: 64 + 27]
+ b'\xf2'
+ revlogtesting.data_non_inlined[64 + 28 :]
Augie Fackler
formatting: blacken the codebase...
r43346 )
Georges Racinet
rust-index: using the `hg::index::Index` in ancestors iterator and lazy set...
r52132 idx = self.parserustindex(data=data)
Georges Racinet
rust-cpython: binding for AncestorsIterator...
r41083 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
Georges Racinet
rust-cpython: raising error.WdirUnsupported...
r41386 def testwdirunsupported(self):
# trying to access ancestors of the working directory raises
Georges Racinet
rust-index: using the `hg::index::Index` in ancestors iterator and lazy set...
r52132 idx = self.parserustindex()
Raphaël Gomès
rust: make `Revision` a newtype...
r51872 with self.assertRaises(rustext.GraphError) as arc:
Joerg Sonnenberger
node: import symbols explicitly...
r46729 list(AncestorsIterator(idx, [wdirrev], -1, False))
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004
Raphaël Gomès
rust: make `Revision` a newtype...
r51872 exc = arc.exception
self.assertIsInstance(exc, ValueError)
# rust-cpython issues appropriate str instances for Python 2 and 3
self.assertEqual(exc.args, ('InvalidRevision', wdirrev))
Georges Racinet
rust-cpython: binding for headrevs()...
r41843 def testheadrevs(self):
Georges Racinet
rust-index: using `hg::index::Index` in `hg-cpython::dagops`...
r52134 idx = self.parserustindex()
Georges Racinet
rust-cpython: binding for headrevs()...
r41843 self.assertEqual(dagop.headrevs(idx, [1, 2, 3]), {3})
Georges Racinet
rust-pyo3: dagop submodule implementation...
r53310 def testpyo3_headrevs(self):
idx = self.parserustindex()
self.assertEqual(pyo3_rustext.dagop.headrevs(idx, [1, 2, 3]), {3})
def testpyo3_rank(self):
idx = self.parserustindex()
try:
pyo3_rustext.dagop.rank(idx, 1, 2)
except pyo3_rustext.GraphError as exc:
self.assertEqual(exc.args, ("InconsistentGraphData",))
Augie Fackler
formatting: blacken the codebase...
r43346
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 if __name__ == '__main__':
import silenttestrunner
Augie Fackler
formatting: blacken the codebase...
r43346
Georges Racinet
rust-cpython: testing the bindings from Python...
r41004 silenttestrunner.main(__name__)