This is an automated email from the ASF dual-hosted git repository. gmurthy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/master by this push: new 37aef86 DISPATCH-1453 - Fix the code so that a correct error message shows up when a tx sender attaches in the absence of a coordinated link route. This closes #602. 37aef86 is described below commit 37aef86a9ac20f5925de955846dd001de117ed5a Author: Ganesh Murthy <gmur...@apache.org> AuthorDate: Mon Oct 28 14:51:24 2019 -0400 DISPATCH-1453 - Fix the code so that a correct error message shows up when a tx sender attaches in the absence of a coordinated link route. This closes #602. --- .../modules/address_lookup_client/lookup_client.c | 10 +-- tests/system_tests_one_router.py | 80 +++++++++++++++++++++- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/router_core/modules/address_lookup_client/lookup_client.c b/src/router_core/modules/address_lookup_client/lookup_client.c index 214624b..6bed399 100644 --- a/src/router_core/modules/address_lookup_client/lookup_client.c +++ b/src/router_core/modules/address_lookup_client/lookup_client.c @@ -312,9 +312,6 @@ static qdr_address_t *qdr_lookup_terminus_address_CT(qdr_core_t *core, *unavailable = true; } - if (qdr_terminus_is_coordinator(terminus)) - *unavailable = false; - if (!!addr && addr->core_endpoint != 0) *core_endpoint = true; @@ -341,7 +338,11 @@ static void qdr_link_react_to_first_attach_CT(qdr_core_t *core, if (core_endpoint) { qdrc_endpoint_do_bound_attach_CT(core, addr, link, source, target); } - + else if (unavailable && qdr_terminus_is_coordinator(dir == QD_INCOMING ? target : source) && !addr) { + qdr_link_outbound_detach_CT(core, link, 0, QDR_CONDITION_COORDINATOR_PRECONDITION_FAILED, true); + qdr_terminus_free(source); + qdr_terminus_free(target); + } else if (unavailable) { qdr_link_outbound_detach_CT(core, link, qdr_error(QD_AMQP_COND_NOT_FOUND, "Node not found"), 0, true); qdr_terminus_free(source); @@ -672,7 +673,6 @@ static uint64_t on_reply(qdr_core_t *core, // The address is for a link route, but there are no destinations upstream. Fail with no-route. // qdr_link_outbound_detach_CT(core, link, 0, QDR_CONDITION_NO_ROUTE_TO_DESTINATION, true); - else // // The address is for a link route and there are destinations upstream. Directly forward the attach. diff --git a/tests/system_tests_one_router.py b/tests/system_tests_one_router.py index 521113f..1840229 100644 --- a/tests/system_tests_one_router.py +++ b/tests/system_tests_one_router.py @@ -24,7 +24,7 @@ from __future__ import print_function from proton import Condition, Message, Delivery, Url, symbol, Timeout from system_test import TestCase, Qdrouterd, main_module, TIMEOUT, DIR, Process -from system_test import unittest +from system_test import unittest, QdManager from proton.handlers import MessagingHandler, TransactionHandler from proton.reactor import Container, AtMostOnce, AtLeastOnce, DynamicNodeProperties, LinkOption, ApplicationEvent, EventInjector from proton.utils import BlockingConnection, SyncRequestResponse @@ -503,7 +503,6 @@ class OneRouterTest(TestCase): self.assertEqual(None, test.error) - class Entity(object): def __init__(self, status_code, status_description, attrs): self.status_code = status_code @@ -3160,6 +3159,83 @@ class UnsettledLargeMessageTest(MessagingHandler): self.receiver.close() self.recv_conn.close() +class OneRouterUnavailableCoordinatorTest(TestCase): + @classmethod + def setUpClass(cls): + super(OneRouterUnavailableCoordinatorTest, cls).setUpClass() + name = "test-router" + OneRouterTest.listen_port = cls.tester.get_port() + config = Qdrouterd.Config([ + ('router', {'mode': 'standalone', 'id': 'QDR', 'defaultDistribution': 'unavailable'}), + ('listener', {'port': cls.tester.get_port() }), + ('address', {'prefix': 'closest', 'distribution': 'closest'}), + ('address', {'prefix': 'balanced', 'distribution': 'balanced'}), + ('address', {'prefix': 'multicast', 'distribution': 'multicast'}), + ]) + cls.router = cls.tester.qdrouterd(name, config) + cls.router.wait_ready() + cls.address = cls.router.addresses[0] + + def test_46_coordinator_linkroute_unavailable_DISPATCH_1453(self): + # The defaultDistribution on the router is unavailable. We try to connect a tx sender + # to make sure a good detailed message saying "the link route to a coordinator must be + # configured" is sent back. + test = RejectCoordinatorGoodMessageTest(self.address) + test.run() + self.assertTrue(test.passed) + + def test_47_coordinator_linkroute_available_DISPATCH_1453(self): + # The defaultDistribution on the router is unavailable. We create a link route with $coordinator address + # The link route is not attached to any broker. When the attach comes in, the reject message must be + # condition=:"qd:no-route-to-dest", description="No route to the destination node" + COORDINATOR = "$coordinator" + long_type = 'org.apache.qpid.dispatch.router.config.linkRoute' + qd_manager = QdManager(self, address=self.address) + args = {"prefix": COORDINATOR, "connection": "broker", "dir": "in"} + qd_manager.create(long_type, args) + link_route_created = False + + # Verify that the link route was created by querying for it. + outs = qd_manager.query(long_type)[0] + if outs: + try: + if outs['prefix'] == COORDINATOR: + link_route_created = True + except: + pass + + self.assertTrue(link_route_created) + + # We have verified that the link route has been created but there is no broker connections. + # Now let's try to open a transaction. We should get a no route to destination error + test = RejectCoordinatorGoodMessageTest(self.address, link_route_present=True) + test.run() + self.assertTrue(test.passed) + + +class RejectCoordinatorGoodMessageTest(RejectCoordinatorTest): + def __init__(self, url, link_route_present=False): + super(RejectCoordinatorGoodMessageTest, self).__init__(url) + self.link_route_present = link_route_present + self.error_with_link_route = "No route to the destination node" + + def on_link_error(self, event): + link = event.link + # If the link name is 'txn-ctrl' and there is a link error and it matches self.error, then we know + # that the router has rejected the link because it cannot coordinate transactions itself + if link.name == "txn-ctrl": + if self.link_route_present: + if link.remote_condition.description == self.error_with_link_route and link.remote_condition.name == 'qd:no-route-to-dest': + self.link_error = True + else: + if link.remote_condition.description == self.error and link.remote_condition.name == 'amqp:precondition-failed': + self.link_error = True + + self.check_if_done() + + def run(self): + Container(self).run() + class Q2HoldoffDropTest(MessagingHandler): """ --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org