예제 #1
0
class _BaseStratumTest(unittest.TestCase):
    __test__ = False

    def setUp(self):
        super().setUp()
        self.manager = self.create_peer('testnet')
        self.manager.allow_mining_without_peers()
        self.factory = StratumFactory(self.manager,
                                      port=8123,
                                      reactor=MemoryReactorClock())
        self.factory.start()
        self.protocol = self.factory.buildProtocol('127.0.0.1')
        self.transport = StringTransportWithDisconnection()
        self.transport.protocol = self.protocol
        self.protocol.makeConnection(self.transport)
        # subscribe and ignore response
        _send_subscribe(self.protocol)
        self.job = self._get_latest_message()['params']
        self.transport.clear()

    def tearDown(self):
        super().tearDown()
        self.factory.stop()

    def _get_latest_message(self):
        data = self.transport.value().split(JSONRPC.delimiter)[-2]
        return json_loads(data)
    def test_thingsGetLogged(self):
        """
        Check the output produced by L{policies.TrafficLoggingFactory}.
        """
        wrappedFactory = Server()
        wrappedFactory.protocol = WriteSequenceEchoProtocol
        t = StringTransportWithDisconnection()
        f = TestLoggingFactory(wrappedFactory, "test")
        p = f.buildProtocol(("1.2.3.4", 5678))
        t.protocol = p
        p.makeConnection(t)

        v = f.openFile.getvalue()
        self.assertIn("*", v)
        self.assertFalse(t.value())

        p.dataReceived(b"here are some bytes")

        v = f.openFile.getvalue()
        self.assertIn("C 1: {!r}".format(b"here are some bytes"), v)
        self.assertIn("S 1: {!r}".format(b"here are some bytes"), v)
        self.assertEqual(t.value(), b"here are some bytes")

        t.clear()
        p.dataReceived(b"prepare for vector! to the extreme")
        v = f.openFile.getvalue()
        self.assertIn("SV 1: {!r}".format([b"prepare for vector! to the extreme"]), v)
        self.assertEqual(t.value(), b"prepare for vector! to the extreme")

        p.loseConnection()

        v = f.openFile.getvalue()
        self.assertIn("ConnectionDone", v)
예제 #3
0
    def testThingsGetLogged(self):
        wrappedFactory = Server()
        wrappedFactory.protocol = WriteSequenceEchoProtocol
        t = StringTransportWithDisconnection()
        f = TestLoggingFactory(wrappedFactory, 'test')
        p = f.buildProtocol(('1.2.3.4', 5678))
        t.protocol = p
        p.makeConnection(t)

        v = f.openFile.getvalue()
        self.failUnless('*' in v, "* not found in %r" % (v,))
        self.failIf(t.value())

        p.dataReceived('here are some bytes')

        v = f.openFile.getvalue()
        self.assertNotEqual(-1, v.find("C 1: 'here are some bytes'"), "Expected client string not found in %r" % (v,))
        self.assertNotEqual(-1, v.find("S 1: 'here are some bytes'"), "Expected server string not found in %r" % (v,))
        self.assertEquals(t.value(), 'here are some bytes')

        t.clear()
        p.dataReceived('prepare for vector! to the extreme')
        v = f.openFile.getvalue()
        self.assertNotEqual(-1, v.find("SV 1: ['prepare for vector! to the extreme']"), "Expected server string not found in %r" % (v,))
        self.assertEquals(t.value(), 'prepare for vector! to the extreme')

        p.loseConnection()

        v = f.openFile.getvalue()
        self.assertNotEqual(-1, v.find('ConnectionDone'), "Connection done notification not found in %r" % (v,))
예제 #4
0
    def test_thingsGetLogged(self):
        """
        Check the output produced by L{policies.TrafficLoggingFactory}.
        """
        wrappedFactory = Server()
        wrappedFactory.protocol = WriteSequenceEchoProtocol
        t = StringTransportWithDisconnection()
        f = TestLoggingFactory(wrappedFactory, 'test')
        p = f.buildProtocol(('1.2.3.4', 5678))
        t.protocol = p
        p.makeConnection(t)

        v = f.openFile.getvalue()
        self.assertIn('*', v)
        self.assertFalse(t.value())

        p.dataReceived(b'here are some bytes')

        v = f.openFile.getvalue()
        self.assertIn("C 1: %r" % (b'here are some bytes',), v)
        self.assertIn("S 1: %r" % (b'here are some bytes',), v)
        self.assertEqual(t.value(), b'here are some bytes')

        t.clear()
        p.dataReceived(b'prepare for vector! to the extreme')
        v = f.openFile.getvalue()
        self.assertIn("SV 1: %r" % ([b'prepare for vector! to the extreme'],), v)
        self.assertEqual(t.value(), b'prepare for vector! to the extreme')

        p.loseConnection()

        v = f.openFile.getvalue()
        self.assertIn('ConnectionDone', v)
예제 #5
0
    def test_thingsGetLogged(self):
        """
        Check the output produced by L{policies.TrafficLoggingFactory}.
        """
        wrappedFactory = Server()
        wrappedFactory.protocol = WriteSequenceEchoProtocol
        t = StringTransportWithDisconnection()
        f = TestLoggingFactory(wrappedFactory, 'test')
        p = f.buildProtocol(('1.2.3.4', 5678))
        t.protocol = p
        p.makeConnection(t)

        v = f.openFile.getvalue()
        self.failUnless('*' in v, "* not found in %r" % (v,))
        self.failIf(t.value())

        p.dataReceived('here are some bytes')

        v = f.openFile.getvalue()
        self.assertIn("C 1: 'here are some bytes'", v)
        self.assertIn("S 1: 'here are some bytes'", v)
        self.assertEqual(t.value(), 'here are some bytes')

        t.clear()
        p.dataReceived('prepare for vector! to the extreme')
        v = f.openFile.getvalue()
        self.assertIn("SV 1: ['prepare for vector! to the extreme']", v)
        self.assertEqual(t.value(), 'prepare for vector! to the extreme')

        p.loseConnection()

        v = f.openFile.getvalue()
        self.assertIn('ConnectionDone', v)
예제 #6
0
    def testThingsGetLogged(self):
        wrappedFactory = Server()
        wrappedFactory.protocol = WriteSequenceEchoProtocol
        t = StringTransportWithDisconnection()
        f = TestLoggingFactory(wrappedFactory, 'test')
        p = f.buildProtocol(('1.2.3.4', 5678))
        t.protocol = p
        p.makeConnection(t)

        v = f.openFile.getvalue()
        self.failUnless('*' in v, "* not found in %r" % (v,))
        self.failIf(t.value())

        p.dataReceived('here are some bytes')

        v = f.openFile.getvalue()
        self.assertNotEqual(-1, v.find("C 1: 'here are some bytes'"), "Expected client string not found in %r" % (v,))
        self.assertNotEqual(-1, v.find("S 1: 'here are some bytes'"), "Expected server string not found in %r" % (v,))
        self.assertEquals(t.value(), 'here are some bytes')

        t.clear()
        p.dataReceived('prepare for vector! to the extreme')
        v = f.openFile.getvalue()
        self.assertNotEqual(-1, v.find("SV 1: ['prepare for vector! to the extreme']"), "Expected server string not found in %r" % (v,))
        self.assertEquals(t.value(), 'prepare for vector! to the extreme')

        p.loseConnection()

        v = f.openFile.getvalue()
        self.assertNotEqual(-1, v.find('ConnectionDone'), "Connection done notification not found in %r" % (v,))
예제 #7
0
class TestTXDistributeProtocol(TestCase):
    def setUp(self):
        self.p = TXDistributeProtocol()
        self.transport = StringTransportWithDisconnection()
        self.p.factory = MockFactory()
        self.p.makeConnection(self.transport)
        self.transport.protocol = self.p

    def test_sends_valid_version(self):
        self.assertEquals(ns("VERSION:1"), self.transport.value())

    def test_valid_version(self):
        self.transport.clear()
        self.p.stringReceived("VERSION:1")
        self.assertEquals("", self.transport.value())
        self.assertTrue(self.transport.connected)

    def test_invalid_version(self):
        self.transport.clear()
        self.p.stringReceived("VERSION:100")
        self.assertEquals(ns("QUIT"), self.transport.value())
        self.assertFalse(self.transport.connected)

    def test_quit(self):
        self.p.stringReceived("QUIT")
        self.assertFalse(self.transport.connected)

    def test_send(self):
        self.p.stringReceived("SEND:1|('a', 'b')")
        self.assertEqual(self.p.factory.txs, [(1, 'a=b')])

    def test_distribute(self):
        self.transport.clear()
        self.p.distribute((1, ('a', 'b')))
        self.assertEqual(self.transport.value(), ns("SEND:1|('a', 'b')"))
예제 #8
0
    def test_readLimit(self):
        """
        Check the readLimit parameter: read data and check for the pause
        status.
        """
        server = Server()
        tServer = TestableThrottlingFactory(task.Clock(), server, readLimit=10)
        port = tServer.buildProtocol(address.IPv4Address(
            "TCP", "127.0.0.1", 0))
        tr = StringTransportWithDisconnection()
        tr.protocol = port
        port.makeConnection(tr)

        port.dataReceived(b"0123456789")
        port.dataReceived(b"abcdefghij")
        self.assertEqual(tr.value(), b"0123456789abcdefghij")
        self.assertEqual(tServer.readThisSecond, 20)

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, "paused")

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, "producing")

        tr.clear()
        port.dataReceived(b"0123456789")
        port.dataReceived(b"abcdefghij")
        self.assertEqual(tr.value(), b"0123456789abcdefghij")
        self.assertEqual(tServer.readThisSecond, 20)

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, "paused")

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, "producing")
예제 #9
0
    def test_readLimit(self):
        """
        Check the readLimit parameter: read data and check for the pause
        status.
        """
        server = Server()
        tServer = TestableThrottlingFactory(task.Clock(), server, readLimit=10)
        port = tServer.buildProtocol(address.IPv4Address('TCP', '127.0.0.1', 0))
        tr = StringTransportWithDisconnection()
        tr.protocol = port
        port.makeConnection(tr)

        port.dataReceived("0123456789")
        port.dataReceived("abcdefghij")
        self.assertEqual(tr.value(), "0123456789abcdefghij")
        self.assertEqual(tServer.readThisSecond, 20)

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, 'paused')

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, 'producing')

        tr.clear()
        port.dataReceived("0123456789")
        port.dataReceived("abcdefghij")
        self.assertEqual(tr.value(), "0123456789abcdefghij")
        self.assertEqual(tServer.readThisSecond, 20)

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, 'paused')

        tServer.clock.advance(1.05)
        self.assertEqual(tServer.readThisSecond, 0)
        self.assertEqual(tr.producerState, 'producing')
예제 #10
0
class TestTXDistributeProtocol(TestCase):

    def setUp(self):
        self.p = TXDistributeProtocol()
        self.transport = StringTransportWithDisconnection()
        self.p.factory = MockFactory()
        self.p.makeConnection(self.transport)
        self.transport.protocol = self.p

    def test_sends_valid_version(self):
        self.assertEquals(ns("VERSION:1"), self.transport.value())

    def test_valid_version(self):
        self.transport.clear()
        self.p.stringReceived("VERSION:1")
        self.assertEquals("", self.transport.value())
        self.assertTrue(self.transport.connected)

    def test_invalid_version(self):
        self.transport.clear()
        self.p.stringReceived("VERSION:100")
        self.assertEquals(ns("QUIT"), self.transport.value())
        self.assertFalse(self.transport.connected)

    def test_quit(self):
        self.p.stringReceived("QUIT")
        self.assertFalse(self.transport.connected)

    def test_send(self):
        self.p.stringReceived("SEND:1|('a', 'b')")
        self.assertEqual(self.p.factory.txs, [(1, 'a=b')])

    def test_distribute(self):
        self.transport.clear()
        self.p.distribute((1, ('a', 'b')))
        self.assertEqual(self.transport.value(), ns("SEND:1|('a', 'b')"))
예제 #11
0
class TestTruteqTransport(VumiTestCase):
    @inlineCallbacks
    def setUp(self):
        self.tx_helper = self.add_helper(TransportHelper(TruteqTransport))
        self.config = {
            'username': '******',
            'password': '******',
        }
        self.string_transport = StringTransportWithDisconnection()

        # NOTE: pausing the transport before starting so we can
        #       start the SSMIProtocol, which expects the vumi transport
        #       as an argument.
        self.transport = yield self.tx_helper.get_transport(self.config,
                                                            start=False)
        st_endpoint = StringTransportEndpoint(self._ste_connect_callback)

        def truteq_service_maker(endpoint, factory):
            return ReconnectingClientService(st_endpoint, factory)

        self.transport.service_class = truteq_service_maker
        yield self.transport.startWorker()
        yield self.process_login_commands('username', 'password')

    def _ste_connect_callback(self, protocol):
        self.protocol = protocol
        self.string_transport = protocol.transport

    @inlineCallbacks
    def process_login_commands(self, username, password):
        [cmd] = yield self.receive(1)
        self.assertEqual(cmd.command_name, 'LOGIN')
        self.assertEqual(cmd.username, username)
        self.assertEqual(cmd.password, password)
        self.send(Ack(ack_type='1'))
        [link_check] = yield self.receive(1)
        self.assertEqual(link_check.command_name, 'LINK_CHECK')
        returnValue(True)

    def send(self, command):
        return self.protocol.lineReceived(str(command))

    def receive(self, count, clear=True):
        d = Deferred()

        def check_for_input():
            if not self.string_transport.value():
                reactor.callLater(0, check_for_input)
                return

            lines = self.string_transport.value().split(
                self.protocol.delimiter)
            commands = map(SSMIRequest.parse, filter(None, lines))
            if len(commands) >= count:
                if clear:
                    self.string_transport.clear()
                    self.string_transport.write(
                        self.protocol.delimiter.join(map(
                            str, commands[count:])))
                d.callback(commands[:count])

        check_for_input()

        return d

    def incoming_ussd(self,
                      msisdn="12345678",
                      ussd_type=c.USSD_RESPONSE,
                      phase="ignored",
                      message="Hello"):
        self.send(
            USSDMessage(msisdn=msisdn,
                        type=ussd_type,
                        phase=c.USSD_PHASE_UNKNOWN,
                        message=message))

    @inlineCallbacks
    def start_ussd(self, message="*678#", **kw):
        kw.setdefault("msisdn", "12345678")
        kw.setdefault("phase", c.USSD_PHASE_UNKNOWN)
        yield self.transport.handle_raw_inbound_message(
            USSDMessage(type=c.USSD_NEW, message=message, **kw))
        self.tx_helper.clear_dispatched_inbound()

    @inlineCallbacks
    def check_msg(self,
                  from_addr="+12345678",
                  to_addr="*678#",
                  content=None,
                  session_event=None,
                  helper_metadata=None):
        default_hmd = {'truteq': {'genfields': {}}}
        [msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)

        self.assertEqual(msg['transport_name'], self.tx_helper.transport_name)
        self.assertEqual(msg['transport_type'], 'ussd')
        self.assertEqual(msg['transport_metadata'], {})
        self.assertEqual(msg['helper_metadata'], helper_metadata
                         or default_hmd)
        self.assertEqual(msg['from_addr'], from_addr)
        self.assertEqual(msg['to_addr'], to_addr)
        self.assertEqual(msg['content'], content)
        self.assertEqual(msg['session_event'], session_event)
        self.tx_helper.clear_dispatched_inbound()

    @inlineCallbacks
    def test_handle_inbound_ussd_new(self):
        yield self.send(
            USSDMessage(msisdn='27000000000',
                        type=c.USSD_NEW,
                        message='*678#',
                        phase=c.USSD_PHASE_1))
        [msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)
        self.assertEqual(msg['to_addr'], '*678#')
        self.assertEqual(msg['session_event'], SESSION_NEW)
        self.assertEqual(msg['transport_type'], 'ussd')

    @inlineCallbacks
    def test_handle_inbound_extended_ussd_new(self):
        yield self.send(
            ExtendedUSSDMessage(msisdn='27000000000',
                                type=c.USSD_NEW,
                                message='*678#',
                                genfields='::3',
                                phase=c.USSD_PHASE_1))
        [msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)
        self.assertEqual(msg['from_addr'], '+27000000000')
        self.assertEqual(msg['to_addr'], '*678#')
        self.assertEqual(
            msg['helper_metadata'], {
                'truteq': {
                    'genfields': {
                        'IMSI': '',
                        'OperatorID': '3',
                        'SessionID': '',
                        'Subscriber Type': '',
                        'ValiPort': '',
                    }
                }
            })

    @inlineCallbacks
    def test_handle_remote_logout(self):
        cmd = ServerLogout(ip='127.0.0.1')
        with LogCatcher() as logger:
            yield self.send(cmd)
            [warning] = logger.messages()
            self.assertEqual(warning,
                             "Received remote logout command: %r" % (cmd, ))

    @inlineCallbacks
    def test_handle_inbound_ussd_resume(self):
        yield self.start_ussd()
        self.incoming_ussd(ussd_type=c.USSD_RESPONSE, message="Hello")
        yield self.check_msg(content="Hello", session_event=SESSION_RESUME)

    @inlineCallbacks
    def test_handle_inbound_ussd_close(self):
        yield self.start_ussd()
        self.incoming_ussd(ussd_type=c.USSD_END, message="Done")
        yield self.check_msg(content="Done", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def test_handle_inbound_ussd_timeout(self):
        yield self.start_ussd()
        self.incoming_ussd(ussd_type=c.USSD_TIMEOUT, message="Timeout")
        yield self.check_msg(content="Timeout", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def test_handle_inbound_ussd_non_ascii(self):
        yield self.start_ussd()
        self.incoming_ussd(ussd_type=c.USSD_TIMEOUT,
                           message=u"föóbær".encode("iso-8859-1"))
        yield self.check_msg(content=u"föóbær", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def test_handle_inbound_ussd_with_comma_in_content(self):
        yield self.start_ussd()
        self.incoming_ussd(ussd_type=c.USSD_TIMEOUT, message=u"foo, bar")
        yield self.check_msg(content=u"foo, bar", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def _test_outbound_ussd(self,
                            vumi_session_type,
                            ssmi_session_type,
                            content="Test",
                            encoding="utf-8"):
        yield self.tx_helper.make_dispatch_outbound(
            content, to_addr=u"+1234", session_event=vumi_session_type)
        [ussd_call] = yield self.receive(1)
        data = content.encode(encoding) if content else ""
        self.assertEqual(ussd_call.message, data)
        self.assertTrue(isinstance(ussd_call.message, str))
        self.assertEqual(ussd_call.msisdn, '1234')
        self.assertEqual(ussd_call.type, ssmi_session_type)

    def test_handle_outbound_ussd_no_session(self):
        return self._test_outbound_ussd(SESSION_NONE, c.USSD_RESPONSE)

    def test_handle_outbound_ussd_null_content(self):
        return self._test_outbound_ussd(SESSION_NONE,
                                        c.USSD_RESPONSE,
                                        content=None)

    def test_handle_outbound_ussd_resume(self):
        return self._test_outbound_ussd(SESSION_RESUME, c.USSD_RESPONSE)

    def test_handle_outbound_ussd_close(self):
        return self._test_outbound_ussd(SESSION_CLOSE, c.USSD_END)

    def test_handle_outbound_ussd_non_ascii(self):
        return self._test_outbound_ussd(SESSION_NONE,
                                        c.USSD_RESPONSE,
                                        content=u"föóbær",
                                        encoding='iso-8859-1')

    @inlineCallbacks
    def _test_content_wrangling(self, submitted, expected):
        yield self.tx_helper.make_dispatch_outbound(submitted,
                                                    to_addr=u"+1234",
                                                    session_event=SESSION_NONE)
        # Grab what was sent to Truteq
        [ussd_call] = yield self.receive(1)
        expected_msg = SendUSSDMessage(msisdn='1234',
                                       message=expected,
                                       type=c.USSD_RESPONSE)

        self.assertEqual(ussd_call, expected_msg)

    def test_handle_outbound_ussd_with_comma_in_content(self):
        return self._test_content_wrangling('hello world, universe',
                                            'hello world, universe')

    def test_handle_outbound_ussd_with_crln_in_content(self):
        return self._test_content_wrangling('hello\r\nwindows\r\nworld',
                                            'hello\nwindows\nworld')

    def test_handle_outbound_ussd_with_cr_in_content(self):
        return self._test_content_wrangling('hello\rold mac os\rworld',
                                            'hello\nold mac os\nworld')

    @inlineCallbacks
    def test_ussd_addr_retains_asterisks_and_hashes(self):
        self.incoming_ussd(ussd_type=c.USSD_NEW, message="*6*7*8#")
        yield self.check_msg(to_addr="*6*7*8#", session_event=SESSION_NEW)

    @inlineCallbacks
    def test_ussd_addr_appends_hashes_if_missing(self):
        self.incoming_ussd(ussd_type=c.USSD_NEW, message="*6*7*8")
        yield self.check_msg(to_addr="*6*7*8#", session_event=SESSION_NEW)

    @inlineCallbacks
    def test_handle_inbound_sms(self):
        cmd = MoMessage(msisdn='foo', message='bar', sequence='1')
        with LogCatcher() as logger:
            yield self.send(cmd)
            [warning] = logger.messages()
            self.assertEqual(
                warning,
                "Received unsupported message, dropping: %r." % (cmd, ))

    @inlineCallbacks
    def test_reconnect(self):
        """
        When disconnected, the transport should attempt to reconnect.

        We test this by stashing the current protocol instance, disconnecting
        it, and asserting that we get a new protocol instance with the usual
        login commands after reconnection.
        """
        self.transport.client_service.delay = 0
        old_protocol = self.protocol
        yield self.protocol.transport.loseConnection()
        yield deferLater(reactor, 0, lambda: None)  # Let the reactor run.
        self.assertNotEqual(old_protocol, self.protocol)
        yield self.process_login_commands('username', 'password')
예제 #12
0
class MemCacheTestCase(TestCase):
    """
    Test client protocol class L{MemCacheProtocol}.
    """

    class FakedMemcacheLock(MemcacheLock):

        def __init__(
            self, faked, namespace, locktoken,
            timeout=5.0, retry_interval=0.1, expire_time=0
        ):
            """
            @param namespace: a unique namespace for this lock's tokens
            @type namespace: C{str}

            @param locktoken: the name of the locktoken
            @type locktoken: C{str}

            @param timeout: the maximum time in seconds that the lock should
                block
            @type timeout: C{float}

            @param retry_interval: the interval to retry acquiring the lock
            @type retry_interval: C{float}

            @param expiryTime: the time in seconds for the lock to expire.
                Zero: no expiration.
            @type expiryTime: C{float}
            """

            super(MemCacheTestCase.FakedMemcacheLock, self).__init__(
                namespace, locktoken, timeout, retry_interval, expire_time
            )
            self.faked = faked

        def _getMemcacheProtocol(self):

            return self.faked


    def setUp(self):
        """
        Create a memcache client, connect it to a string protocol, and make it
        use a deterministic clock.
        """
        TestCase.setUp(self)
        self.proto = MemCacheProtocol()
        self.clock = Clock()
        self.proto.callLater = self.clock.callLater
        self.transport = StringTransportWithDisconnection()
        self.transport.protocol = self.proto
        self.proto.makeConnection(self.transport)


    def _test(self, d, send, recv, result):
        """
        Shortcut method for classic tests.

        @param d: the resulting deferred from the memcache command.
        @type d: C{Deferred}

        @param send: the expected data to be sent.
        @type send: C{str}

        @param recv: the data to simulate as reception.
        @type recv: C{str}

        @param result: the expected result.
        @type result: C{any}
        """
        def cb(res):
            self.assertEquals(res, result)
        self.assertEquals(self.transport.value(), send)
        self.transport.clear()
        d.addCallback(cb)
        self.proto.dataReceived(recv)
        return d


    def test_get(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(
            self.proto, "lock", "locking"
        )
        return self._test(
            lock.get("foo"),
            "get lock:foo-acbd18db4cc2f85cedef654fccc4a4d8\r\n",
            (
                "VALUE lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 3\r\n"
                "bar\r\nEND\r\n"
            ),
            "bar"
        )


    def test_set(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(
            self.proto, "lock", "locking"
        )
        return self._test(
            lock.set("foo", "bar"),
            "set lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 0 3\r\nbar\r\n",
            "STORED\r\n",
            True
        )


    @inlineCallbacks
    def test_acquire(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(
            self.proto, "lock", "locking"
        )
        yield self._test(
            lock.acquire(),
            "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
            "STORED\r\n",
            True
        )
        self.assertTrue(lock._hasLock)


    @inlineCallbacks
    def test_acquire_ok_timeout_0(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(
            self.proto, "lock", "locking", timeout=0
        )
        yield self._test(
            lock.acquire(),
            "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
            "STORED\r\n",
            True
        )
        self.assertTrue(lock._hasLock)


    @inlineCallbacks
    def test_acquire_fails_timeout_0(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(
            self.proto, "lock", "locking", timeout=0
        )
        try:
            yield self._test(
                lock.acquire(),
                (
                    "add lock:"
                    "locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n"
                    "1\r\n"
                ),
                "NOT_STORED\r\n",
                True
            )
        except MemcacheLockTimeoutError:
            pass
        except Exception, e:
            self.fail("Unknown exception thrown: %s" % (e,))
        else:
class MemCacheTestCase(TestCase):
    """
    Test client protocol class L{MemCacheProtocol}.
    """
    class FakedMemcacheLock(MemcacheLock):
        def __init__(self,
                     faked,
                     namespace,
                     locktoken,
                     timeout=5.0,
                     retry_interval=0.1,
                     expire_time=0):
            """
            @param namespace: a unique namespace for this lock's tokens
            @type namespace: C{str}

            @param locktoken: the name of the locktoken
            @type locktoken: C{str}

            @param timeout: the maximum time in seconds that the lock should
                block
            @type timeout: C{float}

            @param retry_interval: the interval to retry acquiring the lock
            @type retry_interval: C{float}

            @param expiryTime: the time in seconds for the lock to expire.
                Zero: no expiration.
            @type expiryTime: C{float}
            """

            super(MemCacheTestCase.FakedMemcacheLock,
                  self).__init__(namespace, locktoken, timeout, retry_interval,
                                 expire_time)
            self.faked = faked

        def _getMemcacheProtocol(self):

            return self.faked

    def setUp(self):
        """
        Create a memcache client, connect it to a string protocol, and make it
        use a deterministic clock.
        """
        TestCase.setUp(self)
        self.proto = MemCacheProtocol()
        self.clock = Clock()
        self.proto.callLater = self.clock.callLater
        self.transport = StringTransportWithDisconnection()
        self.transport.protocol = self.proto
        self.proto.makeConnection(self.transport)

    def _test(self, d, send, recv, result):
        """
        Shortcut method for classic tests.

        @param d: the resulting deferred from the memcache command.
        @type d: C{Deferred}

        @param send: the expected data to be sent.
        @type send: C{str}

        @param recv: the data to simulate as reception.
        @type recv: C{str}

        @param result: the expected result.
        @type result: C{any}
        """
        def cb(res):
            self.assertEquals(res, result)

        self.assertEquals(self.transport.value(), send)
        self.transport.clear()
        d.addCallback(cb)
        self.proto.dataReceived(recv)
        return d

    def test_get(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock",
                                                  "locking")
        return self._test(
            lock.get("foo"),
            "get lock:foo-acbd18db4cc2f85cedef654fccc4a4d8\r\n",
            ("VALUE lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 3\r\n"
             "bar\r\nEND\r\n"), "bar")

    def test_set(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock",
                                                  "locking")
        return self._test(
            lock.set("foo", "bar"),
            "set lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 0 3\r\nbar\r\n",
            "STORED\r\n", True)

    @inlineCallbacks
    def test_acquire(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock",
                                                  "locking")
        yield self._test(
            lock.acquire(),
            "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
            "STORED\r\n", True)
        self.assertTrue(lock._hasLock)

    @inlineCallbacks
    def test_acquire_ok_timeout_0(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(self.proto,
                                                  "lock",
                                                  "locking",
                                                  timeout=0)
        yield self._test(
            lock.acquire(),
            "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
            "STORED\r\n", True)
        self.assertTrue(lock._hasLock)

    @inlineCallbacks
    def test_acquire_fails_timeout_0(self):
        """
        L{MemCacheProtocol.get} should return a L{Deferred} which is
        called back with the value and the flag associated with the given key
        if the server returns a successful result.
        """
        lock = MemCacheTestCase.FakedMemcacheLock(self.proto,
                                                  "lock",
                                                  "locking",
                                                  timeout=0)
        try:
            yield self._test(
                lock.acquire(),
                ("add lock:"
                 "locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n"
                 "1\r\n"), "NOT_STORED\r\n", True)
        except MemcacheLockTimeoutError:
            pass
        except Exception, e:
            self.fail("Unknown exception thrown: %s" % (e, ))
        else:
예제 #14
0
파일: test_truteq.py 프로젝트: areski/vumi
class TestTruteqTransport(VumiTestCase):

    @inlineCallbacks
    def setUp(self):
        self.tx_helper = self.add_helper(TransportHelper(TruteqTransport))
        self.config = {
            'username': '******',
            'password': '******',
        }
        self.string_transport = StringTransportWithDisconnection()

        # NOTE: pausing the transport before starting so we can
        #       start the SSMIProtocol, which expects the vumi transport
        #       as an argument.
        self.transport = yield self.tx_helper.get_transport(
            self.config, start=False)
        st_endpoint = StringTransportEndpoint(self._ste_connect_callback)

        def truteq_service_maker(endpoint, factory):
            return ReconnectingClientService(st_endpoint, factory)

        self.transport.service_class = truteq_service_maker
        yield self.transport.startWorker()
        yield self.process_login_commands('username', 'password')

    def _ste_connect_callback(self, protocol):
        self.protocol = protocol
        self.string_transport = protocol.transport

    @inlineCallbacks
    def process_login_commands(self, username, password):
        [cmd] = yield self.receive(1)
        self.assertEqual(cmd.command_name, 'LOGIN')
        self.assertEqual(cmd.username, username)
        self.assertEqual(cmd.password, password)
        self.send(Ack(ack_type='1'))
        [link_check] = yield self.receive(1)
        self.assertEqual(link_check.command_name, 'LINK_CHECK')
        returnValue(True)

    def send(self, command):
        return self.protocol.lineReceived(str(command))

    def receive(self, count, clear=True):
        d = Deferred()

        def check_for_input():
            if not self.string_transport.value():
                reactor.callLater(0, check_for_input)
                return

            lines = self.string_transport.value().split(
                self.protocol.delimiter)
            commands = map(SSMIRequest.parse, filter(None, lines))
            if len(commands) >= count:
                if clear:
                    self.string_transport.clear()
                    self.string_transport.write(
                        self.protocol.delimiter.join(
                            map(str, commands[count:])))
                d.callback(commands[:count])

        check_for_input()

        return d

    def incoming_ussd(self, msisdn="12345678", ussd_type=c.USSD_RESPONSE,
                      phase="ignored", message="Hello"):
        return self.transport.handle_raw_inbound_message(
            USSDMessage(msisdn=msisdn, type=ussd_type,
                        phase=c.USSD_PHASE_UNKNOWN,
                        message=message))

    @inlineCallbacks
    def start_ussd(self, message="*678#", **kw):
        yield self.incoming_ussd(ussd_type=c.USSD_NEW, message=message, **kw)
        self.tx_helper.clear_dispatched_inbound()

    @inlineCallbacks
    def check_msg(self, from_addr="+12345678", to_addr="*678#", content=None,
                  session_event=None, helper_metadata=None):
        default_hmd = {'truteq': {'genfields': {}}}
        [msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)

        self.assertEqual(msg['transport_name'], self.tx_helper.transport_name)
        self.assertEqual(msg['transport_type'], 'ussd')
        self.assertEqual(msg['transport_metadata'], {})
        self.assertEqual(
            msg['helper_metadata'], helper_metadata or default_hmd)
        self.assertEqual(msg['from_addr'], from_addr)
        self.assertEqual(msg['to_addr'], to_addr)
        self.assertEqual(msg['content'], content)
        self.assertEqual(msg['session_event'], session_event)
        self.tx_helper.clear_dispatched_inbound()

    @inlineCallbacks
    def test_handle_inbound_ussd_new(self):
        yield self.send(USSDMessage(msisdn='27000000000', type=c.USSD_NEW,
                                    message='*678#', phase=c.USSD_PHASE_1))
        [msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)
        self.assertEqual(msg['to_addr'], '*678#')
        self.assertEqual(msg['session_event'], SESSION_NEW)
        self.assertEqual(msg['transport_type'], 'ussd')

    @inlineCallbacks
    def test_handle_inbound_extended_ussd_new(self):
        yield self.send(ExtendedUSSDMessage(
            msisdn='27000000000', type=c.USSD_NEW, message='*678#',
            genfields='::3', phase=c.USSD_PHASE_1))
        [msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)
        self.assertEqual(msg['from_addr'], '+27000000000')
        self.assertEqual(msg['to_addr'], '*678#')
        self.assertEqual(msg['helper_metadata'], {
            'truteq': {
                'genfields': {
                    'IMSI': '',
                    'OperatorID': '3',
                    'SessionID': '',
                    'Subscriber Type': '',
                    'ValiPort': '',
                }
            }
        })

    @inlineCallbacks
    def test_handle_remote_logout(self):
        cmd = ServerLogout(ip='127.0.0.1')
        with LogCatcher() as logger:
            yield self.send(cmd)
            [warning] = logger.messages()
            self.assertEqual(
                warning,
                "Received remote logout command: %r" % (cmd,))

    @inlineCallbacks
    def test_handle_inbound_ussd_resume(self):
        yield self.start_ussd()
        yield self.incoming_ussd(ussd_type=c.USSD_RESPONSE, message="Hello")
        yield self.check_msg(content="Hello", session_event=SESSION_RESUME)

    @inlineCallbacks
    def test_handle_inbound_ussd_close(self):
        yield self.start_ussd()
        yield self.incoming_ussd(ussd_type=c.USSD_END, message="Done")
        yield self.check_msg(content="Done", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def test_handle_inbound_ussd_timeout(self):
        yield self.start_ussd()
        yield self.incoming_ussd(ussd_type=c.USSD_TIMEOUT, message="Timeout")
        yield self.check_msg(content="Timeout", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def test_handle_inbound_ussd_non_ascii(self):
        yield self.start_ussd()
        yield self.incoming_ussd(
            ussd_type=c.USSD_TIMEOUT, message=u"föóbær".encode("iso-8859-1"))
        yield self.check_msg(content=u"föóbær", session_event=SESSION_CLOSE)

    @inlineCallbacks
    def _test_outbound_ussd(self, vumi_session_type, ssmi_session_type,
                            content="Test", encoding="utf-8"):
        yield self.tx_helper.make_dispatch_outbound(
            content, to_addr=u"+1234", session_event=vumi_session_type)
        [ussd_call] = yield self.receive(1)
        data = content.encode(encoding) if content else ""
        self.assertEqual(ussd_call.message, data)
        self.assertTrue(isinstance(ussd_call.message, str))
        self.assertEqual(ussd_call.msisdn, '1234')
        self.assertEqual(ussd_call.type, ssmi_session_type)

    def test_handle_outbound_ussd_no_session(self):
        return self._test_outbound_ussd(SESSION_NONE, c.USSD_RESPONSE)

    def test_handle_outbound_ussd_null_content(self):
        return self._test_outbound_ussd(SESSION_NONE, c.USSD_RESPONSE,
                                        content=None)

    def test_handle_outbound_ussd_resume(self):
        return self._test_outbound_ussd(SESSION_RESUME, c.USSD_RESPONSE)

    def test_handle_outbound_ussd_close(self):
        return self._test_outbound_ussd(SESSION_CLOSE, c.USSD_END)

    def test_handle_outbound_ussd_non_ascii(self):
        return self._test_outbound_ussd(
            SESSION_NONE, c.USSD_RESPONSE, content=u"föóbær",
            encoding='iso-8859-1')

    @inlineCallbacks
    def _test_content_wrangling(self, submitted, expected):
        yield self.tx_helper.make_dispatch_outbound(
            submitted, to_addr=u"+1234", session_event=SESSION_NONE)
        # Grab what was sent to Truteq
        [ussd_call] = yield self.receive(1)
        expected_msg = SendUSSDMessage(msisdn='1234', message=expected,
                                       type=c.USSD_RESPONSE)

        self.assertEqual(ussd_call, expected_msg)

    def test_handle_outbound_ussd_with_crln_in_content(self):
        return self._test_content_wrangling(
            'hello\r\nwindows\r\nworld', 'hello\nwindows\nworld')

    def test_handle_outbound_ussd_with_cr_in_content(self):
        return self._test_content_wrangling(
            'hello\rold mac os\rworld', 'hello\nold mac os\nworld')

    @inlineCallbacks
    def test_ussd_addr_retains_asterisks_and_hashes(self):
        yield self.incoming_ussd(ussd_type=c.USSD_NEW, message="*6*7*8#")
        yield self.check_msg(to_addr="*6*7*8#", session_event=SESSION_NEW)

    @inlineCallbacks
    def test_ussd_addr_appends_hashes_if_missing(self):
        yield self.incoming_ussd(ussd_type=c.USSD_NEW, message="*6*7*8")
        yield self.check_msg(to_addr="*6*7*8#", session_event=SESSION_NEW)

    @inlineCallbacks
    def test_handle_inbound_sms(self):
        cmd = MoMessage(msisdn='foo', message='bar', sequence='1')
        with LogCatcher() as logger:
            yield self.send(cmd)
            [warning] = logger.messages()
            self.assertEqual(
                warning,
                "Received unsupported message, dropping: %r." % (cmd,))

    @inlineCallbacks
    def test_reconnect(self):
        """
        When disconnected, the transport should attempt to reconnect.

        We test this by stashing the current protocol instance, disconnecting
        it, and asserting that we get a new protocol instance with the usual
        login commands after reconnection.
        """
        self.transport.client_service.delay = 0
        old_protocol = self.protocol
        yield self.protocol.transport.loseConnection()
        yield deferLater(reactor, 0, lambda: None)  # Let the reactor run.
        self.assertNotEqual(old_protocol, self.protocol)
        yield self.process_login_commands('username', 'password')