def testBaseTrace(self): """Basic tests of BaseTrace""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id=Id('a')) b = Element(id=Id('b')) a.add(b) b.add(Pin(dia=1, thickness=1, clearance=1, mask=1, id=Id('foo'))) b.add(Pad(a=(0,0), b=(1,1), thickness=0.5, clearance=0.2, mask=0.6, id=Id('bar'))) class basetrace(BaseTrace): valid_endpoint_types = (Pin,Pad) a.add(basetrace(id='t')) a.t.set_endpoints(a.b.foo,a.b.bar) T(a.t.a().id,Id('a/b/foo')) T(a.t.b().id,Id('a/b/bar')) T(a.b.foo in a.t.connects) T(a.b.bar in a.t.connects) T(a.b.foo.connects.to(a.t)) T(a.b.bar.connects.to(a.t))
def testElementRef_apply_remove_context(self): """ElementRef._(apply|remove)_context""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) global bypass class skit(Element): def f(self,d): global bypass r = bypass bypass = d return ElementRef(self,r) a = Element(id=Id('a')) a.add(Element(id=Id('b'))) a.b.add(Element(id=Id('c'))) s = skit(id=Id('s')) a.b.c.add(s) bypass = Id('.') r = a.b.c.s.f(None) T(r().id,Id('a/b/c/s')) bypass = Id('../../..') r = a.b.c.s.f(r) T(bypass().id,Id('.')) T(r().id,Id('a'))
def testElement_with(self): """with Element()""" a = Element(id='a') b = Element(id='b') a.add(b) with a.b as b2: self.assert_(b is b2)
def T(t,context,expected): elem = Element() elem.transform = context got = t._apply_context(context) self.assert_(repr(expected) == repr(got),'apply_context - got: %s expected: %s' % (got,expected)) got = got._remove_context(context) expected = t self.assert_(repr(expected) == repr(got),'apply_context - got: %s expected: %s' % (got,expected))
def testElementAddReturnsWrapped(self): """Element.add(obj) returns wrapped obj""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id='a') r = a.add(Element(id='b')) T(a.b is r) r = a.b.add(Element(id='c')) T(a.b.c is r)
def T(a, b, f, *args, **kwargs): """Element transform function test harness. Applies f(e,*args,**kwargs) to element e. Then applies e.transform to a and checks that the resulting vertex is == b. """ e = Element() f(e, *args, **kwargs) # The repr()-based comparison seems to avoid floating point # "almost" equal errors. self.assert_(repr(e.transform(a)) == repr(b))
def T(t, context, expected): elem = Element() elem.transform = context got = t._apply_context(context) self.assert_( repr(expected) == repr(got), 'apply_context - got: %s expected: %s' % (got, expected)) got = got._remove_context(context) expected = t self.assert_( repr(expected) == repr(got), 'apply_context - got: %s expected: %s' % (got, expected))
def testElementAddObjChecks(self): """Element.add(obj) checks that obj is valid""" def T(ex,obj): self.assertRaises(ex,lambda:Element().add(obj)) # Basic wrongness T(TypeError,None) T(TypeError,'asdf') T(TypeError,2) # Check for wrapped subelements, IE, added element already has a # parent. T(ValueError,Element().add(Element()))
def T(a,b,f,*args,**kwargs): """Element transform function test harness. Applies f(e,*args,**kwargs) to element e. Then applies e.transform to a and checks that the resulting vertex is == b. """ e = Element() f(e,*args,**kwargs) # The repr()-based comparison seems to avoid floating point # "almost" equal errors. self.assert_(repr(e.transform(a)) == repr(b))
def testElementRemoveNotImplemented(self): """Element.remove() not yet implemented""" # This is a real test, if this fails, we need to make sure that # Connects handles the case where a Element parent is removed. a = Element(id=Id('a')) self.assert_(not hasattr(a,'remove'))
def test_Source_notify_unwraps(self): """Source.notify unwraps callables before storing them""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id=Id('a')) called = False class f: def __init__(self): self.called = False def __call__(self): self.called = True f = f() a.notify('foo',f) a.foo = 10 T(f.called)
def testElementInteration(self): """Element interation""" def T(elem,id_set): ids = set() for e in elem: if isinstance(e,Element): ids.add(e.id) id_set = set([Id(i) for i in id_set]) self.assert_(ids == id_set,'got: %s expected: %s' % (ids,id_set)) a = Element(id='a') T(a,set()) for i in range(1,4): a.add(Element(id='_' + str(i))) T(a,set(('a/_1','a/_2','a/_3')))
def testConnectsReprEvalRepr(self): """repr(eval(repr(Connects))) round trip""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id=Id('a')) a.add(Element(id=Id('b'))) a.b.add(Element(id=Id('c'))) a.connects.add(Id('.')) a.connects.add(a.b) a.connects.add(a.b.c) a2 = Element(id='a') a2.connects = eval(repr(a.connects)) a2.connects.base = a2 T(repr(a2.connects),repr(a.connects))
def test_apply_remove_context(self): """V._(apply|remove)_context""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id=Id('a')) b = Element(id=Id('b')) a.add(b) c = Element(id=Id('c')) a.b.add(c) a.v = V(1,1) c.v = V(1,1) translate(a.b,V(0,1)) translate(a.b.c,V(1,0)) T((a.b.c.v == V(2,2)).all()) # The added d element here is important. It's transform is null, so any # optimizations that skip applying null transforms will hopefully # trigger bugs here. # # Secondly, if we used c, it still has a transform applied to any # results from it. For instance with a.b.c as uc, uc.v == V(2,1) right # now. Confusing! d = Element(id=Id('d')) a.b.c.add(d) with a.b.c.d as ud: # The original vertex is at 1,1 The two translations moved by # center point by 0,1 then 1,0 totaling 1,1 so the result cancels # out to 0,0 T((ud[Id('../../')].v == V(0,0)).all()) rotate(a,pi / 2) T(repr(a.b.c.v),repr(V(2,-2))) with a.b.c.d as ud: # Even with the rotation, the translates still cancel out, why? # Because the whole stack above a was rotated, which isn't "seen" # from the perspective of the stack above a. T((ud[Id('../../')].v == V(0,0)).all())
def test_Source_notify_unwraps(self): """Source.notify unwraps callables before storing them""" def T(got, expected=True): self.assert_(expected == got, 'got: %s expected: %s' % (got, expected)) a = Element(id=Id('a')) called = False class f: def __init__(self): self.called = False def __call__(self): self.called = True f = f() a.notify('foo', f) a.foo = 10 T(f.called)
def testElementRef_apply_remove_context(self): """ElementRef._(apply|remove)_context""" def T(got, expected=True): self.assert_(expected == got, 'got: %s expected: %s' % (got, expected)) global bypass class skit(Element): def f(self, d): global bypass r = bypass bypass = d return ElementRef(self, r) a = Element(id=Id('a')) a.add(Element(id=Id('b'))) a.b.add(Element(id=Id('c'))) s = skit(id=Id('s')) a.b.c.add(s) bypass = Id('.') r = a.b.c.s.f(None) T(r().id, Id('a/b/c/s')) bypass = Id('../../..') r = a.b.c.s.f(r) T(bypass().id, Id('.')) T(r().id, Id('a'))
def testElement__getitem__(self): """Element[] lookups""" def T(elem,key,expected_id): got = elem[key] expected_id = Id(expected_id) self.assert_(got.id == expected_id,'got: %s expected: %s' % (got.id,expected_id)) def R(elem,key,partial_stack): # partial_stack is not currently used, but err = None self.assertRaises(KeyError,lambda:elem[key]) a = Element(id='a') T(a,'','a') R(a,'foo',[]) R(a,Id('foo'),[]) R(a,'..',[a]) R(a,'../b',[a]) R(a,'../..',[a]) b = a.add(Element(id='b')) T(a,'b','a/b') with b as b2: R(a,'b/b',[a,b2]) R(b2,'../c',[b2,a]) c = a.add(Element(id='c')) T(a,'c','a/c') d = a.b.add(Element(id='d')) T(a,'b','a/b') T(a,'b/d','a/b/d') T(b,'..',a['.'].id) T(b,'../b',b.id) T(b,'../b/d',d.id) e = Element(id='e') e2 = a.add(e) a['e'].foo = 'foo' self.assert_(e2.foo is e.foo) self.assert_(a.e.foo is e.foo) self.assert_(a['e'].foo is e.foo)
def test_centerof(self): """centerof()""" def T(a,b): self.assert_((a == b).all()) e = Element() T(centerof(e),V(0,0)) translate(e,V(1,2)) T(centerof(e),V(1,2)) self.assertRaises(TypeError,lambda: centerof(V(0,0))) self.assertRaises(TypeError,lambda: centerof(Transformation())) self.assertRaises(TypeError,lambda: centerof('asdf'))
def testConnectsExplicit(self): """Explicit connections""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) def R(ex,fn): self.assertRaises(ex,fn) a = Element(id=Id('a')) T(set(a.connects),set()) b = Element(id=Id('b')) R(ValueError,lambda: a.connects.add(b)) a.add(b) a.add(Element(id=Id('c'))) a.connects.add(a.b) T(a.b in a.connects) T(Id('a/b') in a.connects) T(not (Id('c') in a.connects)) T(not (a.c in a.connects)) R(ValueError,lambda: Element() in a.connects)
def testElementIdAttr(self): """Auto-magical attribute lookup from sub-element Id's""" a = Element(id=Id('a')) translate(a,V(1,1)) foo = Element(id=Id('foo')) translate(foo,V(2,1)) bar = Element(id=Id('bar')) translate(bar,V(1,2)) a.add(foo) a.add(bar) self.assert_(a.foo.id == Id('a/foo')) self.assert_(repr(centerof(a.foo)) == repr(V(3,2))) self.assert_(a.bar.id == Id('a/bar')) self.assert_(repr(centerof(a.bar)) == repr(V(2,3))) self.assertRaises(AttributeError,lambda: a.foobar) foo.foo = 'foo' self.assert_(a.foo.foo is foo.foo) a.foo.bar = 'bar' self.assert_(a.foo.bar is foo.bar)
def testElementSerialize(self): """Element.serialize()""" a = Element(id='') from Tuke.geometry import Circle,Hole,Line from Tuke.pcb import Pin,Pad # a.add(Element(Id('asdf'))) # a.add(Circle(1,'foo',id=rndId())) # a.add(Line((0.1,-0.1),(2,3),0.05,'foo',id=rndId())) # a.add(Hole(3,id=rndId())) # a.add(Pin(1,0.1,0.1,1,id=rndId())) # a.add(Pin(1,0.1,0.1,1,square=True,id=rndId())) # a.add(Pad((0,0),(0,1),0.5,0.1,0.6,id=rndId())) # a.subs[0].add(Element()) from Tuke.geda import Footprint common.load_dataset('geda_footprints') f1 = Footprint(file=common.tmpd + '/plcc4-rgb-led') f2 = Footprint(file=common.tmpd + '/supercap_20mm') print f1.serialize(sys.stdout,full=True) print f2.serialize(sys.stdout,full=True)
def testElementIterlayout(self): """Element.iterlayout()""" def T(got,expected = True): self.assert_(expected == got,'expected: %s got: %s' % (expected,got)) e = Element(id='base') e.add(Element(id='chip')) e.chip.add(Element(id='pad')) e.chip.add(Geometry(layer='sch.lines',id='sym')) e.chip.pad.add(Geometry(layer='top.copper',id='pad')) # Check returned objects and Id auto-mangling T(set([elem.id for elem in e.iterlayout()]), set((Id('base/chip/pad/pad'), Id('base/chip/sym')))) # Check that transforms are working translate(e.chip,V(1,1)) [T(repr(elem.transform), repr(Translation(V(1.0, 1.0)))) for elem in e.iterlayout()] translate(e.chip.pad,V(2,3)) r = {Id('base/chip/sym'):Translation(V(1.0, 1.0)), Id('base/chip/pad/pad'):Translation(V(3.0, 4.0))} for elem in e.iterlayout(): T(repr(r[elem.id]), repr(elem.transform)) # Check layer filtering works T(set([elem.id for elem in e.iterlayout(layer_mask='top.*')]), set((Id('base/chip/pad/pad'),))) T(set([elem.id for elem in e.iterlayout(layer_mask='sch.*')]), set((Id('base/chip/sym'),)))
def testElementAddCollisions(self): """Element.add() attr collisions""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) # Collide with an element a = Element(id='a') b1 = a.add(Element(id='b')) self.assertRaises(Element.IdCollisionError,lambda:a.add(Element(id='b'))) # collide with attr a = Element(id='a') a.b = 10 b1 = a.add(Element(id='b')) T(a.b,10) T(a['b'],b1)
def testBaseTrace_delayed(self): """BaseTrace delayed connects updates""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) class basetrace(BaseTrace): valid_endpoint_types = (Pin,Pad) # Create a new base trace, with two dangling end points t = basetrace(a=Id('../../b/foo'), b=Id('../../b/bar'), id=Id('t')) # Incrementally add elements to the tree z = Element(id=Id('z')) z.add(t) T(z.t.connects.to(Id('b/foo'))) T(z.t.connects.to(Id('b/bar'))) a = Element(id=Id('a')) a.add(z) T(a.z.t.connects.to(Id('a/b/foo'))) T(a.z.t.connects.to(Id('a/b/bar'))) self.assertRaises(KeyError,lambda:a.z.t.a()) self.assertRaises(KeyError,lambda:a.z.t.b()) b = Element(id=Id('b')) a.add(b) b.add(Pin(dia=1, thickness=1, clearance=1, mask=1, id=Id('foo'))) b.add(Pad(a=(0,0), b=(1,1), thickness=0.5, clearance=0.2, mask=0.6, id=Id('bar'))) # We've added foo and bar, so the end points aren't dangling anymore. T(a.b.foo in a.z.t.connects) T(a.b.bar in a.z.t.connects) T(a.b.foo.connects.to(a.z.t)) T(a.b.bar.connects.to(a.z.t)) T(a.z.t.a().id,a.b.foo.id) T(a.z.t.b().id,a.b.bar.id)
def testBaseTrace(self): """Basic tests of BaseTrace""" def T(got, expected=True): self.assert_(expected == got, 'got: %s expected: %s' % (got, expected)) a = Element(id=Id('a')) b = Element(id=Id('b')) a.add(b) b.add(Pin(dia=1, thickness=1, clearance=1, mask=1, id=Id('foo'))) b.add( Pad(a=(0, 0), b=(1, 1), thickness=0.5, clearance=0.2, mask=0.6, id=Id('bar'))) class basetrace(BaseTrace): valid_endpoint_types = (Pin, Pad) a.add(basetrace(id='t')) a.t.set_endpoints(a.b.foo, a.b.bar) T(a.t.a().id, Id('a/b/foo')) T(a.t.b().id, Id('a/b/bar')) T(a.b.foo in a.t.connects) T(a.b.bar in a.t.connects) T(a.b.foo.connects.to(a.t)) T(a.b.bar.connects.to(a.t))
def testElementCommonParent(self): """Element._common_parent and related functions""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id=Id('a')) b = Element(id=Id('b')) T(a.have_common_parent(a)) T(b.have_common_parent(b)) T(not a.have_common_parent(b)) T(not b.have_common_parent(a)) a.add(b) T(a.have_common_parent(b)) T(b.have_common_parent(a)) a.add(Element(id=Id('z'))) a.b.add(Element(id=Id('c'))) T(a.z.have_common_parent(a.b.c)) T(not Element().have_common_parent(a.b.c))
def testElement_notify(self): """Element.notify()""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) a = Element(id=Id('a')) class cb: def __init__(self): self.count = 0 def __call__(self): self.count += 1 self.assertRaises(ValueError, lambda:a.topology_notify(Id('a'),lambda:None)) self.assertRaises(ValueError, lambda:a.topology_notify(Id('z/y'),lambda:None)) self.assertRaises(TypeError, lambda:a.topology_notify(Id('.'),None)) # Test callback adding and deletion cb1 = cb() a.topology_notify(Id('a/b'),cb1) T(unwrap(a).__dict_callbacks__['b'],set((weakref.ref(cb1),))) cb2 = cb() a.topology_notify(Id('a/b'),cb2) T(unwrap(a).__dict_callbacks__['b'], set((weakref.ref(cb1), weakref.ref(cb2)))) del cb1 T(unwrap(a).__dict_callbacks__['b'],set((weakref.ref(cb2),))) del cb2 T(not unwrap(a).__dict_callbacks__.has_key('b') or unwrap(a).__dict_callbacks__['b'] == set()) # Test that callbacks are actually called # Called for adding an object cb1 = cb() a.topology_notify(Id('a/b'),cb1) cb2 = cb() a.topology_notify(Id('a/b'),cb2) b = Element(id=Id('b')) cbp = cb() b.topology_notify(Id('.'),cbp) a.add(b) T(cb1.count,1) T(cb2.count,1) T(cbp.count,1) T(not unwrap(a).__dict_callbacks__.has_key('b')) T(not unwrap(b).__dict_callbacks__.has_key('parent')) # Test for removing an object, just a check that there is no .remove # for now. T(not hasattr(a,'remove'))
def R(ver): a = Element() a.__version__ = ver self.assertRaises(ValueError,lambda: srElement.from_older_version(a))
def testElementIdChecks(self): """Element id validity checks""" self.assertRaises(ValueError,lambda:Element(id='foo/bar'))
def testElementRef(self): """ElementRef""" root = [None] def T(ref, expected_id, expected_magic): r = ElementRef(root[0], ref) r2 = ElementRef(root[0], ref) r = r() r2 = r2() # Deref must return same object. self.assert_(r is r2) # Check that connects is updated if root[0] is not None: self.assert_(root[0].connects.to(r)) self.assert_(r.id == expected_id, 'got id: %s expected id: %s' % (r.id, expected_id)) self.assert_( r.magic == expected_magic, 'got magic: %s expected magic: %s' % (r.magic, expected_magic)) def R(ref): r = ElementRef(root[0], ref) self.assertRaises(KeyError, lambda: r()) a = Element(id=Id('a')) a.magic = 0 b = Element(id=Id('b')) b.magic = 1 a.add(b) c = Element(id=Id('c')) c.magic = 2 a.b.add(c) z = Element(id=Id('z')) z.magic = 3 z.add(a) y = Element(id=Id('y')) y.magic = 4 z.add(y) # Try different roots for r in (a, a.b, a['.']): root[0] = r T(Id('a'), Id('a'), 0) T(a, Id('a'), 0) T(Id('a/b'), Id('a/b'), 1) T(a.b, Id('a/b'), 1) T(Id('a/b/c'), Id('a/b/c'), 2) T(a.b.c, Id('a/b/c'), 2) # ../ T(Id('.'), Id('.'), 3) T(Id('y'), Id('y'), 4) # Check exceptions. R(Id('..')) R(Id('../../')) R(Id('a/z')) R(Id('a/b/c/d'))
def testBaseTrace_delayed(self): """BaseTrace delayed connects updates""" def T(got, expected=True): self.assert_(expected == got, 'got: %s expected: %s' % (got, expected)) class basetrace(BaseTrace): valid_endpoint_types = (Pin, Pad) # Create a new base trace, with two dangling end points t = basetrace(a=Id('../../b/foo'), b=Id('../../b/bar'), id=Id('t')) # Incrementally add elements to the tree z = Element(id=Id('z')) z.add(t) T(z.t.connects.to(Id('b/foo'))) T(z.t.connects.to(Id('b/bar'))) a = Element(id=Id('a')) a.add(z) T(a.z.t.connects.to(Id('a/b/foo'))) T(a.z.t.connects.to(Id('a/b/bar'))) self.assertRaises(KeyError, lambda: a.z.t.a()) self.assertRaises(KeyError, lambda: a.z.t.b()) b = Element(id=Id('b')) a.add(b) b.add(Pin(dia=1, thickness=1, clearance=1, mask=1, id=Id('foo'))) b.add( Pad(a=(0, 0), b=(1, 1), thickness=0.5, clearance=0.2, mask=0.6, id=Id('bar'))) # We've added foo and bar, so the end points aren't dangling anymore. T(a.b.foo in a.z.t.connects) T(a.b.bar in a.z.t.connects) T(a.b.foo.connects.to(a.z.t)) T(a.b.bar.connects.to(a.z.t)) T(a.z.t.a().id, a.b.foo.id) T(a.z.t.b().id, a.b.bar.id)
def testConnectsImplicit(self): """Implicit connections""" def T(got,expected = True): self.assert_(expected == got,'got: %s expected: %s' % (got,expected)) def R(ex,fn): self.assertRaises(ex,fn) # Implicit connections use a lot of weakref magic. That said, they # should function fine with, and without, the garbage collector # enabled. # # That said, until Element.remove is implemented, this can't be a # problem anyway. for i,gc_enabled in enumerate((False,False,False,True,True)): if gc_enabled: gc.enable() else: gc.disable() # Basics a = Element(id=Id('a')) a.add(Element(id=Id('b'))) T(not a.b.connects.to(a)) a.connects.add(a.b) T(a.connects.to(a.b)) T(a.b.connects.to(a)) # Parent change c = Element(id=Id('c')) c.connects.add(Id('.')) c.connects.add(Id('b')) T(c.connects.to(Id('.'))) T(c.connects.to(Id('b'))) a.add(c) T(a.c.connects.to(a)) T(a.c.connects.to(a.b)) T(a.connects.to(a.c)) T(a.b.connects.to(a.c)) # More complex parent changing a = Element(id=Id('a')) b = Element(id=Id('b')) c = Element(id=Id('c')) c.connects.add(Id('../')) b.add(c) a.add(b) T(a.connects.to(Id('a/b/c'))) T(gc.isenabled())
def T(ex,obj): self.assertRaises(ex,lambda:Element().add(obj))
def testElementRef(self): """ElementRef""" root = [None] def T(ref,expected_id,expected_magic): r = ElementRef(root[0],ref) r2 = ElementRef(root[0],ref) r = r() r2 = r2() # Deref must return same object. self.assert_(r is r2) # Check that connects is updated if root[0] is not None: self.assert_(root[0].connects.to(r)) self.assert_(r.id == expected_id, 'got id: %s expected id: %s' % (r.id,expected_id)) self.assert_(r.magic == expected_magic, 'got magic: %s expected magic: %s' % (r.magic,expected_magic)) def R(ref): r = ElementRef(root[0],ref) self.assertRaises(KeyError,lambda: r()) a = Element(id=Id('a')) a.magic = 0 b = Element(id=Id('b')) b.magic = 1 a.add(b) c = Element(id=Id('c')) c.magic = 2 a.b.add(c) z = Element(id=Id('z')) z.magic = 3 z.add(a) y = Element(id=Id('y')) y.magic = 4 z.add(y) # Try different roots for r in (a,a.b,a['.']): root[0] = r T(Id('a'),Id('a'),0) T(a,Id('a'),0) T(Id('a/b'),Id('a/b'),1) T(a.b,Id('a/b'),1) T(Id('a/b/c'),Id('a/b/c'),2) T(a.b.c,Id('a/b/c'),2) # ../ T(Id('.'),Id('.'),3) T(Id('y'),Id('y'),4) # Check exceptions. R(Id('..')) R(Id('../../')) R(Id('a/z')) R(Id('a/b/c/d'))