Example #1
0
 def client_failure(self, error, *args, **kwargs):
     """ This is called from Twisted upon an error """
     # pylint: disable=unused-argument
     client = args[0]
     client["error"] = error
     log_text(self._logger.error, __name__, "client:{0} failed to start: {1}".format(args[0]["name"], error))
     return ConnectionError(str(error))
Example #2
0
 def server_failure(self, error, *args, **kwargs):
     """ This is called when a server fails to connect """
     # pylint: disable=unused-argument
     server = args[0]
     server["error"] = error
     log_text(self._logger.error, __name__, "server:{0} failed to start: {1}".format(args[0]["name"], error))
     return ConnectionError(str(error))
Example #3
0
    def server_success(self, result, *args, **kwargs):
        """ This is called when a server starts listening """
        # pylint: disable=unused-argument
        server = args[0]
        server["listener"] = result

        log_text(self._logger.info, __name__, "server:{0} listening on port {1}".format(server["name"], server["port"]))
Example #4
0
 def server_failure(self, error, *args, **kwargs):
     """ This is called when a server fails to connect """
     # pylint: disable=unused-argument
     server = args[0]
     server['error'] = error
     log_text(
         self._logger.error, __name__,
         'server:{0} failed to start: {1}'.format(args[0]['name'], error))
     return ConnectionError(str(error))
Example #5
0
 def client_failure(self, error, *args, **kwargs):
     """ This is called from Twisted upon an error """
     # pylint: disable=unused-argument
     client = args[0]
     client['error'] = error
     log_text(
         self._logger.error, __name__,
         'client:{0} failed to start: {1}'.format(args[0]['name'], error))
     return ConnectionError(str(error))
Example #6
0
 def client_success(self, result, *args, **kwargs):
     """ This is called from Twisted upon connection """
     # pylint: disable=unused-argument
     client = args[0]
     client["connected"] = "success"
     log_text(
         self._logger.info,
         __name__,
         "client:{0} connected to {1}:{2}".format(client["name"], client["host"], client["port"]),
     )
Example #7
0
    def server_success(self, result, *args, **kwargs):
        """ This is called when a server starts listening """
        # pylint: disable=unused-argument
        server = args[0]
        server['listener'] = result

        log_text(
            self._logger.info, __name__,
            'server:{0} listening on port {1}'.format(server['name'],
                                                      server['port']))
Example #8
0
 def client_success(self, result, *args, **kwargs):
     """ This is called from Twisted upon connection """
     # pylint: disable=unused-argument
     client = args[0]
     client['connected'] = 'success'
     log_text(
         self._logger.info, __name__,
         'client:{0} connected to {1}:{2}'.format(client['name'],
                                                  client['host'],
                                                  client['port']))
Example #9
0
    def buildProtocol(self, addr):
        """ Creates and pulls together the components to
            build up the full interface.  This is called from
            Twisted.
        """
        # pylint: disable=unused-argument

        log_text(self._logger.info, None, "Connected: {0} : {1}".format(self.__class__, self._name))

        transport = self.create_transport(self._name, self._node_config, self._link_config)

        self.servers.append(transport)
        return transport
Example #10
0
    def buildProtocol(self, addr):
        """ Creates and pulls together the components to
            build up the full interface.  This is called from
            Twisted.
        """
        # pylint: disable=unused-argument

        log_text(self._logger.info, None,
                 'Connected: {0} : {1}'.format(self.__class__, self._name))

        transport = self.create_transport(self._name, self._node_config,
                                          self._link_config)

        self.servers.append(transport)
        return transport
Example #11
0
    def _start_client(self, client):
        """ This is a helper function that needs to get called
            on the reactor thread.

            Arguments:
                client: The client dict().
        """
        log_text(self._logger.info, None,
                 'client:{0} attempting {1}:{2}'.format(
                     client['name'],
                     client['host'],
                     client['port']))
        endpoint = clientFromString(
            reactor, b"tcp:{0}:{1}:timeout=10".format(client['host'],
                                                      client['port']))
        node = client['node']
        deferred = connectProtocol(endpoint, node)
        deferred.addCallbacks(node.client_success,
                              callbackArgs=(client,),
                              errback=node.client_failure,
                              errbackArgs=(client,))
Example #12
0
    def on_data_received(self, data):
        """ Passes data to the parser.

            Once a message has been fully read in, the on_message callback
            is called.  When an error is detected in a message, on_error is
            called.

            Args:
                data: The binary data that has been received.  This may
                    either be a binary string or a single byte ot data.
        """
        # pylint: disable=too-many-branches,too-many-statements

        if self.is_receiving_data is True:
            self._buffer += data
            return

        try:
            self.is_receiving_data = True
            self._buffer += data

            # Keep looping while we have unprocessed data
            # We start processing only once we have an entire field
            # (e.g. 'id=value') in the buffer, otherwise wait for more
            # data.
            # The problem with the current approach is that if there is a
            # binary field with an incorrect length, we may read past
            # the end of the message.
            # BUGBUG: Need to fix this. A quick hack may be to
            # try to peek to see what the tag id is and do something
            # with that.  On the other hand this may just be a problem
            # with the protocol (should probably specify a maximum
            # allowable length of a binary field as a sanity check)
            while (len(self._buffer) > 0 and
                    self._buffer.find(b'\x01', self._binary_length + 1) != -1):

                # Need to make sure that we have the entire binary field
                # before continuing the processing
                if (self._binary_length > 0 and
                        len(self._buffer) < self._binary_length):
                    break

                # break up the field
                delim = self._buffer.find(b'\x01', self._binary_length + 1)
                field = self._buffer[:delim]
                self._buffer = self._buffer[delim+1:]

                tag_id, value = self._parse_field(field)

                # Is this the start of a message?
                if tag_id == 8:
                    if self.is_parsing:
                        raise FIXParserError('unexpected tag: 8')
                    self.is_parsing = True
                elif not self.is_parsing:
                    raise FIXParserError('message must start with tag 8')

                if self._debug:
                    log_text(self._logger.debug, None,
                             "tag {0} = {1}".format(tag_id, repr(value)))

                self._update_length(field, tag_id, value)
                self._update_checksum(field, tag_id, value)
                self._update_binary(field, tag_id, value)

                # The tag value gets assigned here. Due to grouping
                # the container where the update takes place gets
                # changed
                # self._message[tag_id] = value
                self._update_field(tag_id, value)

                # Is this the end of a message?
                if tag_id == 10:
                    self._receiver.on_message_received(self._message,
                                                       self._message_length,
                                                       self._checksum)
                    self.reset()

        except FIXLengthTooLongError, err:
            self.reset(flush_buffer=True)
            self._receiver.on_error_received(err)
Example #13
0
def main():
    """ Main entrypoint for the tool.  This will be called from the
        command-line script.
    """
    _setup_logging_config()
    logger = logging.getLogger(__name__)

    test_thread = None
    controller = None

    def term_signal_handler(num, frame):
        """ The signal-handler for the Twisted reactor.
            We assume that all signals are to shutdown the reactor and cancel
            the running tests.
        """
        # pylint: disable=unused-argument
        if controller is not None:
            controller.cancel_test()

        # The actual stop gets called in the finally portion
        # of the run loop.
        # reactor.callInThread(reactor.stop)

    def start_test_thread(call_function):
        """ This will be called on the reactor thread to start up the
            testcase thread.
        """
        test_thread = threading.Thread(target=call_function)
        test_thread.start()

    arg_results = _parse_command_line_args()
    if arg_results.version is True:
        print "{0}, version {1}".format(sys.argv[0], VERSION_STRING)
        sys.exit(2)

    if arg_results.debug is True:
        logger.setLevel(logging.DEBUG)

        # Twisted logging
        observer = log.PythonLoggingObserver()
        observer.start()

    file_name = arg_results.config_file
    if not os.path.isfile(file_name):
        print "Cannot find the configuration file: {0}".format(file_name)
        sys.exit(2)
    config_file = FileConfig(file_name)

    # load/create the TestCaseController
    controller_class = _find_controller(arg_results.test_name)

    log_text(logger.info, None, '================')
    log_text(logger.info, None, 'Starting test: ' +
                                str(datetime.datetime.now().date()))
    log_text(logger.info, None, '  Module: ' + arg_results.test_name)
    log_text(logger.info, None, '  Controller: ' + controller_class.__name__)
    log_text(logger.info, None, '  Config: ' + file_name)

    controller = controller_class(config=config_file,
                                  test_params=arg_results.args)

    log_text(logger.info, None, '')
    log_text(logger.info, None, '  Test case: ' + controller.testcase_id)
    log_text(logger.info, None, '  Description: ' + controller.description)
    log_text(logger.info, None, '================')

    # startup the servers (they don't really startup until reactor.run())
    for server in controller.servers().values():
        log_text(logger.info, None,
                 'server:{0} starting on port {1}'.format(server['name'],
                                                          server['port']))
        endpoint = serverFromString(reactor,
                                    b"tcp:{0}".format(server['port']))
        factory = server['factory']
        deferred = endpoint.listen(factory)
        deferred.addCallbacks(factory.server_success,
                              callbackArgs=(server,),
                              errback=factory.server_failure,
                              errbackArgs=(server,))

    for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM, signal.SIGQUIT]:
        signal.signal(sig, term_signal_handler)

    reactor.callWhenRunning(start_test_thread, controller._execute_test)
    reactor.run()

    if test_thread is not None:
        test_thread.join()

    log_text(logger.info, None, '================')
    log_text(logger.info, None,
             "Test status: {0}\n".format(controller.test_status))
    sys.exit(controller.exit_value)
Example #14
0
 def connectionLost(self, reason=None):
     # pylint: disable=unused-argument
     log_text(self._logger.info, self.name, "Connection lost")
Example #15
0
 def connectionMade(self):
     log_text(self._logger.info, self.name, "Connection made")
Example #16
0
    def on_data_received(self, data):
        """ Passes data to the parser.

            Once a message has been fully read in, the on_message callback
            is called.  When an error is detected in a message, on_error is
            called.

            Args:
                data: The binary data that has been received.  This may
                    either be a binary string or a single byte ot data.
        """
        # pylint: disable=too-many-branches,too-many-statements

        if self.is_receiving_data is True:
            self._buffer += data
            return

        try:
            self.is_receiving_data = True
            self._buffer += data

            # Keep looping while we have unprocessed data
            # We start processing only once we have an entire field
            # (e.g. 'id=value') in the buffer, otherwise wait for more
            # data.
            # The problem with the current approach is that if there is a
            # binary field with an incorrect length, we may read past
            # the end of the message.
            # BUGBUG: Need to fix this. A quick hack may be to
            # try to peek to see what the tag id is and do something
            # with that.  On the other hand this may just be a problem
            # with the protocol (should probably specify a maximum
            # allowable length of a binary field as a sanity check)
            while (len(self._buffer) > 0 and
                   self._buffer.find(b'\x01', self._binary_length + 1) != -1):

                # Need to make sure that we have the entire binary field
                # before continuing the processing
                if (self._binary_length > 0
                        and len(self._buffer) < self._binary_length):
                    break

                # break up the field
                delim = self._buffer.find(b'\x01', self._binary_length + 1)
                field = self._buffer[:delim]
                self._buffer = self._buffer[delim + 1:]

                tag_id, value = self._parse_field(field)

                # Is this the start of a message?
                if tag_id == 8:
                    if self.is_parsing:
                        raise FIXParserError('unexpected tag: 8')
                    self.is_parsing = True
                elif not self.is_parsing:
                    raise FIXParserError('message must start with tag 8')

                if self._debug:
                    log_text(self._logger.debug, None,
                             "tag {0} = {1}".format(tag_id, repr(value)))

                self._update_length(field, tag_id, value)
                self._update_checksum(field, tag_id, value)
                self._update_binary(field, tag_id, value)

                # The tag value gets assigned here. Due to grouping
                # the container where the update takes place gets
                # changed
                # self._message[tag_id] = value
                self._update_field(tag_id, value)

                # Is this the end of a message?
                if tag_id == 10:
                    self._receiver.on_message_received(self._message,
                                                       self._message_length,
                                                       self._checksum)
                    self.reset()

        except FIXLengthTooLongError, err:
            self.reset(flush_buffer=True)
            self._receiver.on_error_received(err)
Example #17
0
def main():
    """ Main entrypoint for the tool.  This will be called from the
        command-line script.
    """
    _setup_logging_config()
    logger = logging.getLogger(__name__)

    test_thread = None
    controller = None

    def term_signal_handler(num, frame):
        """ The signal-handler for the Twisted reactor.
            We assume that all signals are to shutdown the reactor and cancel
            the running tests.
        """
        # pylint: disable=unused-argument
        if controller is not None:
            controller.cancel_test()

        # The actual stop gets called in the finally portion
        # of the run loop.
        # reactor.callInThread(reactor.stop)

    def start_test_thread(call_function):
        """ This will be called on the reactor thread to start up the
            testcase thread.
        """
        test_thread = threading.Thread(target=call_function)
        test_thread.start()

    arg_results = _parse_command_line_args()
    if arg_results.version is True:
        print "{0}, version {1}".format(sys.argv[0], VERSION_STRING)
        sys.exit(2)

    if arg_results.debug is True:
        logger.setLevel(logging.DEBUG)

        # Twisted logging
        observer = log.PythonLoggingObserver()
        observer.start()

    file_name = arg_results.config_file
    if not os.path.isfile(file_name):
        print "Cannot find the configuration file: {0}".format(file_name)
        sys.exit(2)
    config_file = FileConfig(file_name)

    # load/create the TestCaseController
    controller_class = _find_controller(arg_results.test_name)

    log_text(logger.info, None, '================')
    log_text(logger.info, None,
             'Starting test: ' + str(datetime.datetime.now().date()))
    log_text(logger.info, None, '  Module: ' + arg_results.test_name)
    log_text(logger.info, None, '  Controller: ' + controller_class.__name__)
    log_text(logger.info, None, '  Config: ' + file_name)

    controller = controller_class(config=config_file,
                                  test_params=arg_results.args)

    log_text(logger.info, None, '')
    log_text(logger.info, None, '  Test case: ' + controller.testcase_id)
    log_text(logger.info, None, '  Description: ' + controller.description)
    log_text(logger.info, None, '================')

    # startup the servers (they don't really startup until reactor.run())
    for server in controller.servers().values():
        log_text(
            logger.info, None,
            'server:{0} starting on port {1}'.format(server['name'],
                                                     server['port']))
        endpoint = serverFromString(reactor, b"tcp:{0}".format(server['port']))
        factory = server['factory']
        deferred = endpoint.listen(factory)
        deferred.addCallbacks(factory.server_success,
                              callbackArgs=(server, ),
                              errback=factory.server_failure,
                              errbackArgs=(server, ))

    for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM, signal.SIGQUIT]:
        signal.signal(sig, term_signal_handler)

    reactor.callWhenRunning(start_test_thread, controller._execute_test)
    reactor.run()

    if test_thread is not None:
        test_thread.join()

    log_text(logger.info, None, '================')
    log_text(logger.info, None,
             "Test status: {0}\n".format(controller.test_status))
    sys.exit(controller.exit_value)
Example #18
0
 def connectionMade(self):
     log_text(self._logger.info, self.name, "Connection made")
Example #19
0
 def connectionLost(self, reason=None):
     # pylint: disable=unused-argument
     log_text(self._logger.info, self.name, "Connection lost")