Exemple #1
0
class TestChannelConnect(unittest.TestCase):

    timeout = 2

    def setUp(self):
        self.cli = MockClient()

    def tearDown(self):
        if hasattr(self, 'chan'):
            self.chan.close()
            del self.chan
        import gc
        gc.collect()
        if hasattr(self, 'check'):
            # Ensure no remaining references
            x = self.check()
            if x is not None:
                from TwCA.util.debug import showRefs
                print 'refs of', x
                showRefs(x)
            self.assertTrue(
                self.check() is None, 'Test object not destroyed because of '
                'lingering references')
        if hasattr(self, 'cli'):
            self.cli.close()
            del self.cli

    @inlineCallbacks
    def test_reconn(self):
        """connect, disconnect, and reconnect
        """

        self.chan = CAClientChannel('somepv', self.cli)
        #self.check=ref(self.chan) #TODO: find the reference leak!

        cb = Counter()

        def conCB(chan, status):
            if status:
                cb.c += 5
            else:
                cb.c -= 1

        self.chan.status.add(conCB)

        circ = MockCircuit()
        circ.transport.connector.doCon(circ)

        self.cli._L.callback(('localhost', 42))
        self.cli._O.callback(circ)

        # wait until channel calls circ.addchan(chan)
        chan = yield circ.reqAttach

        self.assertEqual(chan, self.chan)
        self.assertEqual(chan.state, chan.S_attach)

        self.assertTrue(chan._d is not None)

        # fall out of circ.addchan(chan)
        # before sending packets
        yield deferLater(reactor, 0, lambda: None)

        # send rights
        self.chan.dispatch(CAmessage(cmd=22, p2=3), circ)
        # send channel create ok
        self.chan.dispatch(CAmessage(cmd=18, dtype=6, count=10, p2=52), circ)

        self.assertTrue(chan._d is None)

        # verify decode
        self.assertEqual(chan.rights, 3)
        self.assertEqual(chan.sid, 52)
        self.assertEqual((chan.dbr, chan.maxcount), (6, 10))

        self.assertEqual(self.chan.state, self.chan.S_connect)

        # wait for channel to signal connected
        chan = yield self.chan.whenCon

        # check that status callback was fired
        self.assertEqual(cb.c, 5)

        # prepare to drop circuit
        circ2 = MockCircuit()
        circ2.transport.connector.doCon(circ2)

        self.cli._L = succeed(('localhost', 43))
        self.cli._O = succeed(circ2)

        circ.transport.connector.doLost(circ)
        circ.close()

        # wait for channel to signal disconnected
        chan = yield self.chan.whenDis

        self.assertEqual(chan.state, chan.S_init)
        # verify decode
        self.assertEqual(chan.rights, 0)
        self.assertEqual(chan.sid, None)
        self.assertEqual((chan.dbr, chan.maxcount), (None, 0))

        # check the status cb was notified of dcnt
        self.assertEqual(cb.c, 4)

        # wait until channel reattaches
        chan = yield circ2.reqAttach
        self.assertEqual(self.chan, chan)
        self.assertEqual(chan._circ, circ2)

        self.assertEqual(chan.state, chan.S_attach)

        self.assertTrue(chan._d is not None)

        # fall out of circ.addchan(chan)
        yield deferLater(reactor, 0, lambda: None)

        # send rights
        self.chan.dispatch(CAmessage(cmd=22, p2=2), circ2)
        # send channel create ok
        self.chan.dispatch(CAmessage(cmd=18, dtype=5, count=11, p2=53), circ2)

        # verify decode
        self.assertEqual(chan.rights, 2)
        self.assertEqual(chan.sid, 53)
        self.assertEqual((chan.dbr, chan.maxcount), (5, 11))

        self.assertEqual(self.chan.state, self.chan.S_connect)

        # wait for channel to signal connected
        chan = yield self.chan.whenCon

        # check that status callback was fired
        self.assertEqual(cb.c, 9)

        self.chan.close()
        circ2.close()

        returnValue(None)
Exemple #2
0
class TestChannelFail(unittest.TestCase):

    timeout = 2

    def setUp(self):
        self.cli = MockClient()

    def tearDown(self):
        if hasattr(self, 'chan'):
            self.chan.close()  # redundent, but safe to call again
            del self.chan
        import gc
        gc.collect()
        if hasattr(self, 'check'):
            #Ensure no remaining references
            x = self.check()
            if x is not None:
                from TwCA.util.debug import showRefs
                print 'refs of', x
                showRefs(x)
            self.assertTrue(
                self.check() is None, 'Test object not destroyed because of '
                'lingering references')
        if hasattr(self, 'cli'):
            self.cli.close()
            del self.cli

    def test_noop(self):
        """Startup and shutdown before running reactor
        """
        self.chan = CAClientChannel('testpv', self.cli)
        self.check = ref(self.chan)

        c = Counter()

        @self.chan.whenDis.addCallback
        def onCon(chan):
            self.assertTrue(chan is self.chan)
            c.c += 2

        self.assertEqual(c.c, 2)

        @self.chan.whenCon.addCallback
        def onCon(chan):
            self.assertTrue(chan is None)
            c.c += 1

        self.chan.close()
        del self.chan

        self.assertEqual(c.c, 3)
        self.assertTrue(self.cli._Lname is None)
        self.assertTrue(self.cli._Osrv is None)

    def test_nolookup(self):
        """Lookup fails
        """

        self.chan = CAClientChannel('testpv', self.cli)
        self.check = ref(self.chan)

        self.chan.whenCon.addCallback(lambda x: self.assertTrue(x is None))

        def whenWaiting():
            self.assertTrue(len(self.cli._L.callbacks), 1)
            self.assertTrue(self.cli._Lname == 'testpv')
            self.assertTrue(self.cli._Osrv is None)
            self.cli._L.callback(None)

            self.chan.close()
            del self.chan

        # wait for first connection attempt
        return deferLater(reactor, self.chan.reconnectDelay * 1.1, whenWaiting)

    def test_lookupabort(self):
        """Lookup ok, close before circuit connects
        """

        self.chan = CAClientChannel('missingpv', self.cli)
        self.check = ref(self.chan)

        @self.chan.whenCon.addCallback
        def onCon(x):
            self.assertTrue(x is None)

        def whenWaiting():
            self.assertTrue(len(self.cli._L.callbacks), 1)
            self.assertTrue(self.cli._Lname == 'missingpv')
            self.cli._L.callback(('localhost', 42))
            self.cli._L = succeed(None)

            self.assertTrue(len(self.cli._O.callbacks), 1)
            self.assertEqual(self.cli._Osrv, ('localhost', 42))

            self.chan.close()
            del self.chan

        return deferLater(reactor, self.chan.reconnectDelay * 1.1, whenWaiting)

    @inlineCallbacks
    def test_nocirc(self):
        """Lookup ok, circuit fails to connect
        """

        self.chan = CAClientChannel('somepv', self.cli)
        self.check = ref(self.chan)

        self.chan.whenCon.addCallback(lambda x: self.assertTrue(x is None))

        # wait for connection attempt
        yield deferLater(reactor, self.chan.reconnectDelay * 1.1, lambda: None)

        # ensure channel initiated lookup
        self.assertTrue(len(self.cli._L.callbacks), 1)
        self.assertTrue(self.cli._Lname == 'somepv')
        self.assertTrue(self.cli._Osrv is None)

        self.cli._L.callback(('localhost', 42))
        self.cli._L = Deferred()

        # ensure channel requested a channel
        self.assertTrue(len(self.cli._O.callbacks), 1)
        self.assertEqual(self.cli._Osrv, ('localhost', 42))

        # fail channel request
        self.cli._O.callback(None)

        # wait for connection retry
        yield deferLater(reactor, self.chan.reconnectDelay * 1.1, lambda: None)

        self.assertTrue(len(self.cli._L.callbacks), 1)

        # simulate client close()
        self.chan.close()
        self.cli._L.callback(None)

        del self.chan

    def test_noattach(self):
        """Lookup and connect circuit, but disconnect before attach
        """

        self.chan = CAClientChannel('somepv', self.cli)
        self.check = ref(self.chan)

        self.chan.whenCon.addCallback(lambda x: self.assertTrue(x is None))

        circ = MockCircuit()
        circ.transport.connector.doCon(circ)

        self.cli._L.callback(('localhost', 42))
        self.cli._O.callback(circ)

        d = circ.reqAttach

        @d.addCallback
        def onAttach(chan):
            self.assertEqual(chan, self.chan)
            self.assertEqual(chan.state, chan.S_attach)

            self.assertTrue(chan._d is not None)

            return deferLater(reactor, 0, lambda: None)

        @d.addCallback
        def done(_):
            circ.transport.connector.doLost(circ)
            circ.close()
            self.assertTrue(self.chan._d is None)

            self.assertEqual(self.chan.state, self.chan.S_init)
            self.chan.close()
            self.assertTrue(self.chan._circ is None)

        return circ.reqAttach

    def test_nochan(self):
        """Lookup and connect circuit, but server does not have channel
        """

        self.chan = CAClientChannel('somepv', self.cli)
        self.check = ref(self.chan)

        self.chan.whenCon.addCallback(lambda x: self.assertTrue(x is None))

        circ = MockCircuit()
        circ.transport.connector.doCon(circ)

        self.cli._L.callback(('localhost', 42))
        self.cli._O.callback(circ)

        d = circ.reqAttach

        @d.addCallback
        def onAttach(chan):
            self.assertEqual(chan, self.chan)
            self.assertEqual(chan.state, chan.S_attach)

            self.assertTrue(chan._d is not None)
            return deferLater(reactor, 0, lambda: None)

        @d.addCallback
        def done(_):
            # send channel create fail
            self.chan.dispatch(CAmessage(cmd=26), circ)
            self.assertTrue(self.chan._d is None)

            self.assertEqual(self.chan.state, self.chan.S_init)
            self.chan.close()
            circ.close()

        return circ.reqAttach