Beispiel #1
0
    def test_asynchronous_durable_subscription(self, topic_durable, broker,
                                               iqa: IQAInstance):
        """
        This test must be defined as the second one (as tests defined in classes run sequentially in py.test).
        With that said, the previous test left the durable subscriptions available in the related Broker instance.
        So when this test runs, the Publishers will run first and will publish a pre-defined (self.MESSAGES) number
        of messages into the related multicast address (topic_durable).
        It waits till all publishers are done sending (or timed-out).
        Next it will connect one Durable Subscriber instance with the "topic_durable" address across all routers
        in the topology. Then it waits till all receivers are done receiving (or timed-out).
        Then it validates:
        - Number of messages sent
        - Number of messages received by each receiver (expecting self.MESSAGES * len(routers))
        - Integrity of received messages by comparing received body SHA1 with unique SHA1 sum from sent body.
        :param topic_durable: Fixture that provides the topic to send/receive from
        :param broker: A Broker component instance (not being used yet, but illustrates which broker is being used)
        :param iqa: IQAInstance fixture that provides a list with all routers that will be used
        :return:
        """

        # Broker instance
        broker_instance = iqa.get_brokers(broker)[0]
        assert broker_instance

        # List of routers to use
        routers = iqa.get_routers()

        # Create publisher list
        publishers = self.create_publishers(routers, topic_durable)

        # Wait till all senders have delivered their messages
        [p.join() for p in publishers]

        # Assert all senders sent correct amount of messages
        self.validate_all_messages_sent(publishers)

        # Create subscriber list
        # At this point, as previous test (synchronous) completed, a durable subscription already
        # exists, so subscribers should be able to retrieve their messages properly now
        subscribers = self.create_subscribers(routers,
                                              topic_durable,
                                              durable=True)

        # Wait till all subscribers are done
        # the stopped flag will turn into true if any of them times out
        [s.join() for s in subscribers]

        # Assert that all receivers received expected amount of messages
        self.validate_all_messages_received(publishers[0].message_body,
                                            routers, subscribers)
Beispiel #2
0
    def test_synchronous_nondurable_subscription(self, topic_nondurable,
                                                 broker, iqa: IQAInstance):
        """
        Connects one Non-Durable Subscriber instance to the "topic_durable" address across all routers.
        Once all subscribers are connected, it starts one Publisher against each router
        in the topology.
        Next the test waits till all senders are done and till all receivers are done receiving (or timed-out).
        Then it validates:
        - Number of messages sent
        - Number of messages received by each receiver (expecting self.MESSAGES * len(routers))
        - Integrity of received messages by comparing received body SHA1 with unique SHA1 sum from sent body.
        :param topic_nondurable: Fixture that provides the topic to send/receive from
        :param broker: A Broker component instance (not being used yet, but illustrates which broker is being used)
        :param iqa: IQAInstance fixture that provides a list with all routers that will be used
        :return:
        """

        # Broker instance
        broker_instance = iqa.get_brokers(broker)[0]
        assert broker_instance

        # List of routers to use
        routers = iqa.get_routers()

        # Create subscriber list
        subscribers = self.create_subscribers(routers,
                                              topic_nondurable,
                                              durable=False)

        # Wait till all receivers have been created
        while not all(s.receiver for s in subscribers):
            time.sleep(TestDurableNonDurableSubscription.DELAY)

        # Create publisher list
        publishers = self.create_publishers(routers, topic_nondurable)

        # Wait till all publishers and subscribers done
        # the stopped flag will turn into true if any of them times out
        [p.join() for p in publishers]
        [s.join() for s in subscribers]

        # Assert all senders sent correct amount of messages
        self.validate_all_messages_sent(publishers)

        # Assert that all receivers received expected amount of messages
        self.validate_all_messages_received(publishers[0].message_body,
                                            routers, subscribers)
Beispiel #3
0
    def test_anycast_messages(self, iqa: IQAInstance):
        router_i1: Dispatch = iqa.get_routers(
            "one_interior_router.Router.I1")[0]
        sender_java: SenderJava = iqa.get_clients(Sender, 'java')[0]
        receiver_java: ReceiverJava = iqa.get_clients(Receiver, 'java')[0]
        assert sender_java
        assert receiver_java

        # URL to communicate
        url = "amqp://%s:%s/anycast/address" % (router_i1.node.get_ip(),
                                                router_i1.port)

        # Receiver
        receiver_java.set_url(url)
        receiver_java.command.stdout = True
        receiver_java.command.logging.log_msgs = 'dict'
        receiver_java.command.control.count = MESSAGE_COUNT
        receiver_java.command.control.timeout = TIMEOUT_SECS

        # Sender
        msg = Message(body=SAMPLE_MESSAGE_BODY)
        sender_java.set_url(url)
        sender_java.command.control.count = MESSAGE_COUNT
        sender_java.command.control.timeout = TIMEOUT_SECS

        # Starting
        receiver_java.receive()
        sender_java.send(msg)

        # Wait for clients
        sender_java.execution.wait()
        receiver_java.execution.wait()

        # Assert messages have been exchanged
        assert sender_java.execution.completed_successfully()
        assert receiver_java.execution.completed_successfully()

        # Assert all messages received
        assert len(
            receiver_java.execution.read_stdout(lines=True)) == MESSAGE_COUNT
def test_basic_messaging_with_all_clients_concurrently(iqa: IQAInstance, length):
    """
    Exchange messages through the router using three pairs of:
    - Java Sender and Receiver
    - Python Sender and Receiver, and
    - NodeJS Sender and Receiver.
    Expects that all messages are exchanged and all external clients complete successfully.
    :param iqa:
    :param length:
    :return:
    """

    receivers = iqa.get_clients(client_type=Receiver)
    senders = iqa.get_clients(client_type=Sender)

    # Run all available clients in parallel
    for receiver in receivers:
        start_receiver(receiver)
    for sender in senders:
        start_sender(sender, length)

    # Validate all results
    for receiver, sender in zip(receivers, senders):
        validate_client_results(receiver, sender)
Beispiel #5
0
    def test_network(self, iqa: IQAInstance):
        assert iqa

        # Expected router from inventory is available
        router_i1: Dispatch = iqa.get_routers(
            "one_interior_router.Router.I1")[0]
        assert router_i1

        # Querying router network
        query = RouterQuery(router_i1.node.get_ip(), router_i1.port)
        nodes = []
        for attempt in range(MAX_ATTEMPTS):
            try:
                nodes = query.node()
                break
            except ConnectionException:
                time.sleep(DELAY_SECS)
                pass

        # Assert only one node in the network (from $management)
        assert len(nodes) == 1
Beispiel #6
0
# Message explaining what this sample does
intro_message = """
This sample will first iterate through all components (router/broker and clients)
defined through the inventory file %s and then it will start:
- One receiver instance of each client consuming messages from:
  /client/<implementation> (implementation being: java, python or nodejs)
  - Receivers will expect 1000 messages each
- One sender instance of each client sending messages to the same address
  pattern explained above (small message)
- Display results
""" % inventory
print(intro_message)

# Loading the instance
print("Loading IQAInstance using inventory file: %s" % inventory)
iqa = IQAInstance(inventory)

# Listing all routers in inventory
print("\n-> List of messaging components parsed from inventory")
for component in iqa.components:  # type: Component

    # List component name and type
    print("   * Name: %-20s | Type: %-10s | Implementation: %s" %
          (component.node.hostname, type(component), component.implementation))

# Router instance to use on clients
router_or_broker = None
for component in iqa.components:
    if isinstance(component, Server):
        router_or_broker = component
assert router_or_broker or 'No Router or Broker component defined in inventory file.'
    def test_address_translation_sending(self, address, translates_to, sender,
                                         broker, router, iqa: IQAInstance):
        """
        Send messages to the given "address", through the provided "router" instance. It uses the given
        "sender" (ClientExternal) instance and expects the queue with name "translates_to" to exist in
        the "broker" instance and that the number of messages in it will increase from initial message count
        to the value defined in the SEND_COUNT constant.
        :param address:
        :param translates_to:
        :param sender:
        :param broker:
        :param router:
        :param iqa:
        :return:
        """

        # if not router.node.hostname.startswith('Router.I'):
        #     return

        # Get broker instance for given broker name
        broker_instance: Artemis = iqa.get_brokers(broker)[0]
        assert broker_instance

        # Retrieving current number of messages in the destination address (queue)
        queue = self._get_queue(broker_instance, translates_to)
        initial_message_count = int(queue.message_count)

        # Assert queue has been found
        assert queue
        assert initial_message_count is not None

        # Url to be used by senders and receivers
        url = "amqp://%s:%s/%s" % (router.node.get_ip(), router.port, address)

        # Preparing the external sender
        logging.info("Sending messages to %s - using %s" %
                     (url, sender.implementation))
        sender.reset_command()
        sender.command.stderr = True
        sender.set_url(url)
        sender.command.control.count = self.SEND_COUNT
        sender.command.control.timeout = self.TIMEOUT  # Timeout flag for command to be executed
        sender.command.timeout = self.TIMEOUT  # Timeout for command (needed cause timeout flag is working properly)

        # Defining the message to be sent
        message = Message()
        message.body = self.MESSAGE_BODY

        # Sending and waiting for app to finish
        sender.send(message)
        sender.execution.wait()

        # Validating sender completed successfully
        logging.debug("Sender completed successfully: %s - timed out: %s" %
                      (sender.execution.completed_successfully(),
                       sender.execution.timed_out))

        # Debug output in case of failure
        if not sender.execution.completed_successfully():
            logging.debug("Sender stdout = %s" %
                          sender.execution.read_stdout())
            logging.debug("Sender stderr = %s" %
                          sender.execution.read_stderr())

        assert sender.execution.completed_successfully()

        # Delaying 5 secs to clean up everything
        time.sleep(5)

        # Validates if all messages have been delivered
        queue = self._get_queue(broker_instance, translates_to)
        logging.info(
            "Message count at queue %s - after senders completed = %s" %
            (translates_to, queue.message_count))
        assert (self.SEND_COUNT + initial_message_count) == int(
            queue.message_count)
    def test_address_translation_receiving(self, address, translates_to,
                                           receiver, broker, router,
                                           iqa: IQAInstance):
        """
        Receive messages from the provided "address" connecting with the "router" instance.
        This test will execute an external client using the "receiver" instance and expect it to
        consume RECV_COUNT messages from the given "address". The "address" used for receiving should resolve
        as the "translates_to" value, which must be a queue name on the "broker" instance.
        The number of messages in the respective queue must be equals or greater than RECV_COUNT.
        This test will validate number of received messages as well as perform an SHA1 sum based
        on the message's body, which must match the generated SHA1 sum from message sent earlier.
        :param address:
        :param translates_to:
        :param receiver:
        :param broker:
        :param router:
        :param iqa:
        :return:
        """

        # if not router.node.hostname.startswith('Router.I'):
        #     return

        # Get broker instance for given broker name
        broker_instance: Artemis = iqa.get_brokers(broker)[0]
        assert broker_instance

        # Retrieving current number of messages in the destination address (queue)
        queue = self._get_queue(broker_instance, translates_to)
        initial_message_count = int(queue.message_count)
        logging.info(
            "Initial message count at queue %s - after receivers completed = %s"
            % (translates_to, queue.message_count))

        # Assert queue has been found and senders were able to send something
        assert queue
        assert initial_message_count >= self.RECV_COUNT

        # Url to be used by receivers
        url = "amqp://%s:%s/%s" % (router.node.get_ip(), router.port, address)

        # Preparing receiver
        logging.info("Receiving messages from %s - using %s" %
                     (url, receiver.implementation))
        receiver.reset_command()
        receiver.command.stderr = True
        receiver.set_url(url)
        receiver.command.control.count = self.RECV_COUNT
        # cannot be used with cli-rhea as it is "waiting" for the given amount of time (causing a timeout to happen)
        if receiver.implementation != 'nodejs':
            receiver.command.control.timeout = self.TIMEOUT  # Timeout flag for command to be executed
        receiver.command.logging.log_msgs = 'dict'
        receiver.command.timeout = self.TIMEOUT  # Timeout for command

        # Executes external receiver and waits until it finishes (or times out)
        receiver.receive()
        receiver.execution.wait()

        # Validating results
        logging.info("Receiver completed successfully: %s - timed out: %s" %
                     (receiver.execution.completed_successfully(),
                      receiver.execution.timed_out))

        # Debug output in case of failure
        if not receiver.execution.completed_successfully():
            logging.debug("Receiver stdout = %s" %
                          receiver.execution.read_stdout())
            logging.debug("Receiver stderr = %s" %
                          receiver.execution.read_stderr())

        assert receiver.execution.completed_successfully()

        # Validating message integrity
        stdout_lines = receiver.execution.read_stdout(lines=True)
        assert len(stdout_lines) == self.RECV_COUNT

        # Reading each message body and comparing SHA1 sum
        for recv_msg in stdout_lines:
            # Failing if a blank line was received
            if not recv_msg:
                pytest.fail("Not expecting an empty message")
                continue
            try:
                recv_msg_dict = ast.literal_eval(recv_msg)
            except ValueError:
                pytest.fail("Invalid message body returned. Expecting a dict.")

            # Failing if invalid content received from external client
            if 'content' not in recv_msg_dict.keys():
                pytest.fail(
                    'Expecting a content element as part of message dict.')
                continue

            # Failing if message returned with empty body
            body = recv_msg_dict['content']
            if not body:
                pytest.fail("No message body available")
                continue

            # Validate integrity
            assert hashlib.sha1(
                body.encode('utf-8')).hexdigest() == self.MESSAGE_SHA1SUM

        # Delaying 5 secs to clean up everything
        time.sleep(5)

        # Validates if all messages have been received
        queue = self._get_queue(broker_instance, translates_to)
        logging.info(
            "Message count at queue %s - after receivers completed = %s" %
            (translates_to, queue.message_count))
        assert (initial_message_count - self.RECV_COUNT) == int(
            queue.message_count)
Beispiel #9
0
    def test_asynchronous_nondurable_subscription(self, topic_nondurable,
                                                  broker, iqa: IQAInstance):
        """
        Publishers run first and will publish a pre-defined (self.MESSAGES) number of messages into the related
        multi-cast address (topic_nondurable).
        It waits till all publishers are done sending (or timed-out).
        Next it will connect one Non-Durable Subscriber instance with the "topic_nondurable" address across all routers
        in the topology. Then it waits till all receivers time-out.
        Then it validates:
        - Number of messages sent
        - Expect all receivers to time-out
        - Number of messages received by each receiver (expecting 0)
        :param topic_nondurable: Fixture that provides the topic to send/receive from
        :param broker: A Broker component instance (not being used yet, but illustrates which broker is being used)
        :param iqa: IQAInstance fixture that provides a list with all routers that will be used
        :return:
        """

        async_timeout = 30

        broker_instance = iqa.get_brokers(broker)[0]
        assert broker_instance

        # List of routers to use
        routers = iqa.get_routers()

        # Create subscriber list
        subscribers = self.create_subscribers(routers,
                                              topic_nondurable,
                                              durable=False,
                                              timeout=async_timeout)

        # Wait till all receivers have been created
        while not all(s.receiver for s in subscribers):
            time.sleep(TestDurableNonDurableSubscription.DELAY)

        # Now stop all receivers to ensure non-durable subscription was discarded
        [s.stop_receiver() for s in subscribers]

        # Create publisher list
        publishers = self.create_publishers(routers, topic_nondurable)

        # Wait till all publishers are done sending
        [p.join() for p in publishers]

        # Create subscribers now with a small timeout and expect nothing to be received
        subscribers = self.create_subscribers(routers,
                                              topic_nondurable,
                                              durable=False,
                                              timeout=async_timeout)

        # Wait till all subscribers timeout
        [s.join() for s in subscribers]

        # Assert all senders sent correct amount of messages
        self.validate_all_messages_sent(publishers)

        # Assert that all receivers did not receive any message and that all of them timed out
        assert all([s.received == 0
                    for s in subscribers]), "Expecting no message received"
        assert all([s.timeout_handler.timed_out() for s in subscribers
                    ]), "Expecting all receivers to timeout"
Beispiel #10
0
intro_message = """
This sample will iterate through all the 'broker' components defined at
the '%s' inventory file and it will then:
- Display the broker node hostname and its current status (if able to 
  communicate with it)
- Attempt to start the broker component if it is not running (using a 
  valid system service or a docker container)
  Note: You can stop the broker component and validate if it gets started
- Iterate through all queues and displaying its FQQN and the message count

""" % inventory
print(intro_message)

# Loading the instance
print("Loading IQAInstance using inventory file: %s" % inventory)
iqa = IQAInstance(inventory)

# Iterating through brokers
for broker in iqa.brokers:  # type: Broker

    # List broker node hostname and its status
    print("* Broker: %s - Status: %s" %
          (broker.node.hostname, broker.service.status().name))

    # If broker "service" is reported as not running, try starting it
    if broker.service.status() != ServiceStatus.RUNNING:
        print("  -> starting service: %s" % broker.service.name)
        broker.service.start()

        # Wait till broker web port is available
        for attempt in range(MAX_ATTEMPTS):
Beispiel #11
0
 def iqa(self, deployer):
     inventory_file = deployer.get_inventory(self)
     iqa = IQAInstance(inventory=inventory_file)
     yield iqa