Mini Shell
from guppy.heapy.test import support
class TestCase(support.TestCase):
def setUp(self):
support.TestCase.setUp(self)
self.sets = self.guppy.sets
heapdefs = getattr(self.sets.setsc, '_NyHeapDefs_'),
self.root = []
self.heapyc = self.guppy.heapy.heapyc
self.hv = self.heapyc.HeapView(self.root, heapdefs)
self.nodeset = self.sets.immnodeset
self.mutnodeset = self.sets.mutnodeset
self.nodegraph = self.heapyc.NodeGraph
class TestHeapView(TestCase):
def test_hiding_tag(self):
hiding_tag = self.hv._hiding_tag_
a = []
ns = self.mutnodeset([a])
ng = self.nodegraph([(a, a)])
self.aseq(self.hv.relimg([ns]), self.nodeset([a]))
self.aseq(self.hv.relimg([ng]), self.nodeset([a]))
ns._hiding_tag_ = hiding_tag
self.aseq(self.hv.relimg([ns]), self.nodeset([]))
ng._hiding_tag_ = hiding_tag
self.aseq(self.hv.relimg([ng]), self.nodeset([]))
self.hv._hiding_tag_ = []
self.aseq(self.hv.relimg([ns]), self.nodeset([a, None]))
self.aseq(self.hv.relimg([ng]), self.nodeset([a, None]))
def test_inheritance_from_heapview(self):
# I am not using inheritance from HeapView,
# but it would be kinda weird if it didn't work.
HeapView = self.guppy.heapy.heapyc.HeapView
x = 'x'
newroot = [x]
class HV(HeapView):
def __new__(self):
return HeapView.__new__(HV, newroot, ())
hv = HV()
assert hv.heap() == self.nodeset([x, newroot])
def test_inheritance_from_special_types(self):
# Test that relate, size & traverse function correctly for inherited types
# as discussed in Notes Apr 14 2005.
# Testing with a standard type (list) with specially size and relate definitions,
# and a heapdef'd type (mutnodeset) with size, relate and traverse defs.
# Test includes more than 1 level of inheritance, since the generic
# method needs to go over all bases and not just the (first) base.
hv = self.hv
hv._hiding_tag_ = [] # Different from default nodeset's hiding_tag
immnodeset = self.sets.immnodeset
mutnodeset = self.sets.mutnodeset
for base in (list, mutnodeset):
class T(base):
__slots__ = 't',
class U(T):
__slots__ = 'u',
a = base()
t = T()
t.t = []
u = U()
u.t = []
u.u = []
data = list(range(16))
for x in data:
a.append(x)
t.append(x)
u.append(x)
# Test size
za = hv.indisize_sum([a])
zt = hv.indisize_sum([t])
zu = hv.indisize_sum([u])
self.assertTrue(za < zt < zu)
# Test traverse
self.aseq(hv.relimg([a]), immnodeset(data))
self.aseq(hv.relimg([t]), immnodeset(data+[T, t.t]))
self.aseq(hv.relimg([u]), immnodeset(data+[U, u.t, u.u]))
# Test relate
def rel(src, tgt):
r = hv.relate(src, tgt)
self.assertTrue(r != ((),)*len(r))
return r
self.aseq(rel(t, data[1]), rel(a, data[1]))
self.aseq(rel(u, data[1]), rel(a, data[1]))
self.aseq(rel(u, u.t), rel(t, t.t))
rel(u, u.u)
def test_nodeset_circularity(self):
# The traversal to function correctly for types inherited from nodeset
# required a fix as discussed in Notes Apr 14 2005.
# This method intends to test that this fix was harmless wrt gc & circularity.
# To make this method fail, it was necessary to disable nodeset gc traversal.
# xxx It seems I have not yet come around to write this test...
pass
def test_registered_hiding(self):
hv = self.hv
class Set(object):
__slots__ = 'some', '_hiding_tag_', 'other'
class Der(Set):
pass
hv.register__hiding_tag__type(Set)
# Der is inherited and registration follows its base type.
s = Set()
d = Der()
t = Set()
some = []
other = []
dother = []
s.some = some
s.other = other
d.some = some
d.other = dother
self.root.append([s, t, d])
self.root.append(s)
self.root.append(d)
self.root.append(t)
x = hv.heap()
assert dother in x
assert some in x
assert other in x
assert s in x
assert d in x
assert t in x
s._hiding_tag_ = hv._hiding_tag_
d._hiding_tag_ = hv._hiding_tag_
x = hv.heap()
assert some not in x
assert other not in x
assert s not in x
assert d not in x
assert t in x
he = []
hv._hiding_tag_ = he
x = hv.heap()
assert dother in x
assert some in x
assert other in x
assert s in x
assert d in x
assert t in x
def test_timing(self):
# Test some timing aspects of heap traversal
from time import process_time as clock
hv = self.hv
d = []
h = [d]
self.root.extend(100000*[h])
self.root.extend(list(range(100000)))
start = clock()
x = hv.heap()
elapsed0 = clock() - start
print('elapsed0', elapsed0, 'len(x)', len(x))
class Set(object):
__slots__ = 'some', '_hiding_tag_', 'other'
class Der(Set):
pass
hv.register__hiding_tag__type(Set)
s = Set()
s._hiding_tag_ = hv._hiding_tag_
d = Der()
d._hiding_tag_ = hv._hiding_tag_
self.root[0:50000] = 25000*[s, d]
start = clock()
x = hv.heap()
elapsed1 = clock() - start
print('elapsed1', elapsed1, 'len(x)', len(x))
# This has failed a couple of times so I remove it now, (apr 5 2008)
# xxx should look into this later ...
#self.assert_(elapsed1 < 3.0 * elapsed0)
class TestLeak(support.TestCase):
def test_1(self):
import gc
from sys import getrefcount as grc
support.TestCase.setUp(self)
sets = self.guppy.sets
heapdefs = getattr(sets.setsc, '_NyHeapDefs_'),
root = []
heapyc = self.guppy.heapy.heapyc
nodeset = sets.mutnodeset
nodegraph = heapyc.NodeGraph
class T(object):
__slots__ = 'a', '_hiding_tag_', 'tonly'
pass
class U(T):
__slots__ = 'b',
pass
class V(object):
__slots__ = 'c',
gc.collect()
ns = nodeset()
a = [ns]
a.append(a)
b = []
he = []
c = []
t = T()
tonly = []
t.a = a
t._hiding_tag_ = he
t.tonly = tonly
u = U()
u.a = a
u._hiding_tag_ = he
u.b = b
v = V()
v.c = c
a = [x for x in [list]]
li = [he, a, b, c, t, u, v, T, U, V, ns, nodeset, list]
rcli0 = [grc(x) for x in li]
ns |= li + list(range(10000, 10010))
root.extend(li)
rcli = [grc(x) for x in li]
rec = nodeset([x for x in li])
x = None
rec.append(rec)
ns.add(rec)
rec._hiding_tag_ = rec
hv = heapyc.HeapView(root, heapdefs)
hv.register__hiding_tag__type(T)
h = hv.heap()
assert a in h
assert c in h
assert tonly in h
hv._hiding_tag_ = he
h = hv.heap()
del x
del h
del hv
ns.discard(rec)
rec = None
gc.collect()
nrcli = [grc(x) for x in li]
self.aseq(rcli, nrcli)
root[:] = []
ns.clear()
nrcli0 = [grc(x) for x in li]
self.aseq(rcli0, nrcli0)
def test_weaky(self):
# Test that the extra-type information in heapview
# will still allow types to come, be used, and go, and be collected
# This depends on that they are weakly-referenced
# so internal heapview structures can remove them when they are
# to be collected.
import gc
from sys import getrefcount as grc
support.TestCase.setUp(self)
sets = self.guppy.sets
heapdefs = getattr(sets.setsc, '_NyHeapDefs_'),
root = []
heapyc = self.guppy.heapy.heapyc
nodeset = sets.NodeSet
nodegraph = heapyc.NodeGraph
gc.collect()
probe = []
rcprobe = grc(probe)
class T(object):
x = probe
class U(T):
pass
T.U = U # Make circular dependency
t = T()
u = U()
root.append(t)
root.append(u)
hv = heapyc.HeapView(root, heapdefs)
x = hv.heap()
assert t in x
x = None
T = t = U = u = None
root[:] = []
gc.collect() # 2 collections needed sometimes? Note Apr 15 2005
nrcprobe = grc(probe)
self.aseq(nrcprobe, rcprobe)
class TestNodeGraph(TestCase):
def test_constructor_and_methods(self):
# Test constructor w no arg
ng = self.nodegraph()
# Test add_edge
ng.add_edge(1, 2)
# Test add_edges_n1
ng.add_edges_n1([3, 4], 5)
lng = list(ng)
lng.sort()
assert lng == [(1, 2), (3, 5), (4, 5)]
# Test as_flat_list
fl = ng.as_flat_list()
fl.sort()
assert fl == [1, 2, 3, 4, 5, 5]
# Test copy
cp = ng.copy()
cp.add_edge(5, 6)
# Test __iter__ explicitly
lng1 = list(ng.__iter__())
lng1.sort()
assert lng1 == lng
lcp = list(cp)
lcp.sort()
assert lcp == [(1, 2), (3, 5), (4, 5), (5, 6)]
# Test domain_covers
assert ng.domain_covers([1, 3, 4])
assert not ng.domain_covers([1, 3, 4, 5])
# Test domain_restricted
rng = ng.domain_restricted([1, 3])
# Test get_domain
assert rng.get_domain() == self.nodeset([1, 3])
lrng = list(rng)
lrng.sort()
assert lrng == [(1, 2), (3, 5)]
# Test get_range
assert rng.get_range() == self.nodeset([2, 5])
# Test invert
rng.invert()
lrng = list(rng)
lrng.sort()
assert lrng == [(2, 1), (5, 3)]
# Test inverted
ing = ng.inverted()
ling = list(ing)
ling.sort()
assert ling == [(2, 1), (5, 3), (5, 4)]
# Test relimg
assert ing.relimg([2]) == self.nodeset([1])
assert ing.relimg([2, 5, 3]) == self.nodeset([1, 3, 4])
# Test update
ing.update([(3, 7), (4, 8)])
assert ing.relimg([2, 5, 3]) == self.nodeset([1, 3, 4, 7])
# Test updated
uing = ing.updated([(2, 9)])
assert ing.relimg([2, 5, 3]) == self.nodeset([1, 3, 4, 7])
assert uing.relimg([2, 5, 3]) == self.nodeset([1, 3, 4, 7, 9])
# Test __getitem__
tgts = list(uing[2])
tgts.sort()
assert tgts == [1, 9]
# Test __len__
assert len(uing) == 6
uing[2] = (2, 8)
# Test __setitem__
tgts = list(uing[2])
tgts.sort()
assert tgts == [2, 8]
# Test clear
ng.clear()
assert list(ng) == []
# Test constructor with iterable
ng = self.nodegraph([(1, 2)])
assert list(ng) == [(1, 2)]
assert not ng.is_mapping
# Test constructor with is_mapping flag
ng = self.nodegraph(is_mapping=True)
assert ng.is_mapping
assert list(ng) == []
ng.add_edge(1, 2)
assert list(ng) == [(1, 2)]
assert ng[1] == 2
ng = self.nodegraph(is_mapping=False)
assert not ng.is_mapping
# Test constructor with iterable & is_mapping flag
for ng in (self.nodegraph([(1, 2)], True),
self.nodegraph(iterable=[(1, 2)], is_mapping=True),
self.nodegraph([(1, 2)], is_mapping=True),
self.nodegraph(is_mapping=True, iterable=[(1, 2)])
):
assert ng.is_mapping
assert list(ng) == [(1, 2)]
assert ng[1] == 2
ng[1] = 3
assert ng[1] == 3
# Test is_sorted flag
# though this behaviour is not fixed - may change with implementation
ng = self.nodegraph()
ng.add_edge(1, 2)
ng.add_edge(2, 1)
assert not ng.is_sorted
ng[1]
assert ng.is_sorted
def test_inheritance(self):
class T(self.heapyc.NodeGraph):
__slots__ = 'x'
def as_sorted_list(self):
a = list(self)
a.sort()
return a
t = T()
t.add_edge(1, 2)
t.add_edge(2, 3)
assert t.as_sorted_list() == [(1, 2), (2, 3)]
t = T([(4, 5), (6, 7)])
assert t.as_sorted_list() == [(4, 5), (6, 7)]
# Test that the base type functionality has been inherited
# by making test_constructor_and_methods think NodeGraph is T
self.nodegraph = T
self.test_constructor_and_methods()
# Test with a constructor with new argument
# and some more attributes
class R(T):
__slots__ = 'stop',
def __new__(self, stop):
r = T.__new__(R, is_mapping=1)
r.add_edges_n1(list(range(stop)), 0)
r.stop = stop
return r
def keys(self):
return list(self.get_domain())
def values(self):
return [self[k] for k in list(self.keys())]
r = R(10)
assert r.stop == 10
assert r.is_mapping
lr = list(r)
lr.sort()
assert lr[-2:] == [(8, 0), (9, 0)]
keys = list(r.keys())
keys.sort()
assert keys == list(range(10))
values = list(r.values())
assert values == [0]*10
class TestClassifiers(TestCase):
# Some new standalone classifiers tests.
# Some old are also tested via test_Classifiers.
def test_inrel(self):
def str_inrel(c):
c = list(c)
c.sort()
return ', '.join(['(%s, %r)' % (x.kind, x.relator) for x in c])
hv = self.hv
rg = self.nodegraph()
x = []
y = [x]
rg.add_edge(x, y)
cli = hv.cli_inrel(rg, {}, {})
c = cli.classify(x)
self.aseq(str_inrel(c), '(2, 0)')
for i in range(5):
y.append(x)
c = cli.classify(x)
self.aseq(str_inrel(c), '(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5)')
for i in range(5):
r = {str(i): x}
rg.add_edge(x, r)
c = cli.classify(x)
def test_nodetuple_richcompare(self):
hv = self.hv
cli = hv.cli_and((hv.cli_id(),), {})
a, b = cli.classify(1), cli.classify(2)
self.assertTrue(a != b)
self.assertFalse(a == b)
self.assertTrue(a >= b or a <= b)
self.assertFalse(a >= b and a <= b)
self.assertTrue(a > b or a < b)
self.assertFalse(a > b and a < b)
a, b = cli.classify(1), cli.classify(1)
self.assertFalse(a != b)
self.assertTrue(a == b)
self.assertTrue(a >= b or a <= b)
self.assertTrue(a >= b and a <= b)
self.assertFalse(a > b or a < b)
self.assertFalse(a > b and a < b)
def test_main(debug=False):
support.run_unittest(TestClassifiers, debug)
support.run_unittest(TestNodeGraph, debug)
support.run_unittest(TestLeak, debug)
support.run_unittest(TestHeapView, debug)
if __name__ == "__main__":
test_main()
Zerion Mini Shell 1.0