Modified: qpid/dispatch/trunk/tests/system_tests_management.py URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_management.py?rev=1610827&r1=1610826&r2=1610827&view=diff ============================================================================== --- qpid/dispatch/trunk/tests/system_tests_management.py (original) +++ qpid/dispatch/trunk/tests/system_tests_management.py Tue Jul 15 19:45:09 2014 @@ -20,9 +20,15 @@ """System tests for management of qdrouter""" import unittest, system_test, re, os -from qpid_dispatch_internal.management import Node, ManagementError, Url +from qpid_dispatch_internal.management import Node, ManagementError, Url, BAD_REQUEST, NOT_IMPLEMENTED, STATUS_TEXT, NOT_FOUND from system_test import Qdrouterd, message, retry -from httplib import BAD_REQUEST, NOT_IMPLEMENTED + +LISTENER = 'org.apache.qpid.dispatch.listener' +CONNECTOR = 'org.apache.qpid.dispatch.connector' +FIXED_ADDRESS = 'org.apache.qpid.dispatch.fixed-address' +WAYPOINT = 'org.apache.qpid.dispatch.waypoint' + +ADDRESS = 'org.apache.qpid.dispatch.router.address' class ManagementTest(system_test.TestCase): # pylint: disable=too-many-public-methods @@ -33,8 +39,11 @@ class ManagementTest(system_test.TestCas cls.log_file = name+".log" conf = Qdrouterd.Config([ ('log', {'module':'DEFAULT', 'level':'trace', 'output':cls.log_file}), - ('router', {'mode': 'standalone', 'router-id': name}), - ('listener', {'port':cls.get_port(), 'role':'normal'}) + ('router', { 'mode': 'standalone', 'router-id': name}), + ('listener', {'name': 'l0', 'port':cls.get_port(), 'role':'normal'}), + # Extra listeners to exercise managment query + ('listener', {'name': 'l1', 'port':cls.get_port(), 'role':'normal'}), + ('listener', {'name': 'l2', 'port':cls.get_port(), 'role':'normal'}) ]) cls.router = cls.tester.qdrouterd('%s'%name, conf) cls.router.wait_ready() @@ -45,55 +54,67 @@ class ManagementTest(system_test.TestCas # Temporary access to separate new management address. self.node2 = self.cleanup(Node(Url(self.router.addresses[0], path='$management2'))) - def assertRaisesManagement(self, status, pattern, call, *args, **kwargs): - """Assert that call(*args, **kwargs) raises a ManagementError - with status and matching pattern in description """ + def assertRaisesManagement(self, status, call, *args, **kwargs): + """Assert that call(*args, **kwargs) raises a ManagementError with status""" try: call(*args, **kwargs) - self.fail("Expected ManagementError with %s, %s"%(status, pattern)) + self.fail("Expected ManagementError(%r)"%(STATUS_TEXT[status])) except ManagementError, e: - self.assertEqual(e.status, status) - assert re.search("(?i)"+pattern, e.description), "No match for %s in %s"%(pattern, e.description) + self.assertEqual(status, e.status, + msg="Expected status %r, got '%s'"%(STATUS_TEXT[status], e)) def test_bad_query(self): """Test that various badly formed queries get the proper response""" - self.assertRaisesManagement( - BAD_REQUEST, "No operation", self.node.call, self.node.request()) - self.assertRaisesManagement( - NOT_IMPLEMENTED, "Not Implemented: nosuch", - self.node.call, self.node.request(operation="nosuch")) - self.assertRaisesManagement( - BAD_REQUEST, r'(entityType|attributeNames).*must be provided', - self.node.query) + # No operation attribute + self.assertRaisesManagement(BAD_REQUEST, self.node.call, self.node.request()) + # Unknown operation + self.assertRaisesManagement(NOT_IMPLEMENTED, self.node.call, + self.node.request(operation="nosuch")) + # No entityType or attributeList + self.assertRaisesManagement(BAD_REQUEST, self.node.query) def test_query_type(self): address = 'org.apache.qpid.dispatch.router.address' response = self.node.query(type=address) self.assertEqual(response.attribute_names[0:3], ['type', 'name', 'identity']) - for r in response: # Check types - self.assertEqual(r.type, address) - names = [r.name for r in response] + for r in response.result_maps: # Check types + self.assertEqual(r['type'], address) + names = [r['name'] for r in response.result_maps] self.assertTrue('L$management' in names) self.assertTrue('M0$management' in names) - # TODO aconway 2014-06-05: negative test: offset, count not implemented on router - try: - # Try offset, count - self.assertGreater(len(names), 2) - response0 = self.node.query(type=address, count=1) - self.assertEqual(names[0:1], [r[1] for r in response0]) - response1_2 = self.node.query(type=address, count=2, offset=1) - self.assertEqual(names[1:3], [r[1] for r in response1_2]) - self.fail("Negative test passed!") - except: pass - - def test_query_attribute_names(self): - """TODO aconway 2014-06-05: negative test: attribute_names query doesn't work.""" - response = self.node.query(attribute_names=["type", "name", "identity"]) - try: - self.assertNotEqual([], response) - self.fail("Negative test passed!") - except: pass + def test_query_type(self): + """Query with type only""" + response = self.node2.query(type=LISTENER) + for attr in ['type', 'name', 'identity', 'addr', 'port']: + self.assertIn(attr, response.attribute_names) + for r in response.result_maps: # Check types + self.assertEqual(len(response.attribute_names), len(r)) + self.assertEqual(r['type'], LISTENER) + self.assertTrue( + set(['l0', 'l1', 'l2']) <= set(r['name'] for r in response.result_maps)) + + def test_query_type_attributes(self): + """Query with type and attribute names""" + attribute_names=['type', 'name', 'port'] + response = self.node2.query(type=LISTENER, attribute_names=attribute_names) + self.assertEqual(attribute_names, response.attribute_names) + expect = [[LISTENER, 'l%s' % i, str(self.router.ports[i])] for i in xrange(3)] + for r in expect: # We might have extras in results due to create tests + self.assertIn(r, response.results) + self.assertIn(dict(zip(attribute_names, r)), response.result_maps) + + def test_query_attributes(self): + """Query with attributes only""" + attribute_names=['type', 'name', 'port'] + response = self.node2.query(attribute_names=attribute_names) + self.assertEqual(attribute_names, response.attribute_names) + expect = [[LISTENER, 'l%s' % i, str(self.router.ports[i])] for i in xrange(3)] + for r in expect: # We might have extras in results due to create tests + self.assertIn(r, response.results) + for name in ['router0', 'log0']: + self.assertTrue([r for r in response.result_maps if r['name'] == name], + msg="Can't find result with name '%s'" % name) def assertMapSubset(self, sub, super): """Assert that mapping sub is a subset of mapping super""" @@ -111,20 +132,20 @@ class ManagementTest(system_test.TestCas port = self.get_port() # Note qdrouter schema defines port as string not int, since it can be a service name. attributes = {'name':'foo', 'port':str(port), 'role':'normal', 'sasl-mechanisms': 'ANONYMOUS'} - result = self.assert_create_ok('org.apache.qpid.dispatch.listener', 'foo', attributes) + result = self.assert_create_ok(LISTENER, 'foo', attributes) self.assertEqual(result['identity'], attributes['name']) self.assertEqual(result['addr'], '0.0.0.0') # Connect via the new listener node3 = self.cleanup(Node(Url(port=port, path='$management'))) router = node3.query(type='org.apache.qpid.dispatch.router') - self.assertEqual(self.__class__.router.name, router[0]['name']) + self.assertEqual(self.__class__.router.name, router.result_maps[0]['name']) def test_create_log(self): """Create a log entity""" - # FIXME aconway 2014-07-04: + # FIXME aconway 2014-07-04: rework log entity. # - allow auto-assigned name/identity? Use module as name/identity? - # - rework log entity: 1 entity with full log state, allow updates. + # - 1 entity with full log state, allow updates. log = os.path.abspath("test_create_log.log") self.assert_create_ok('log', 'log.1', dict(module='AGENT', level="error", output=log)) # Cause an error and verify it shows up in the log file. @@ -135,7 +156,7 @@ class ManagementTest(system_test.TestCas msg="Can't find expected ValidationError.*nosuch in '%r'" % logstr) def test_create_fixed_address(self): - self.assert_create_ok('fixed-address', 'fixed1', dict(prefix='fixed1')) + self.assert_create_ok(FIXED_ADDRESS, 'fixed1', dict(prefix='fixed1')) msgr = self.messenger(flush=True) address = self.router.addresses[0]+'/fixed1' msgr.subscribe(address) @@ -157,10 +178,10 @@ class ManagementTest(system_test.TestCas # Configure the router for c in [ - ('fixed-address', 'a1', {'prefix':'foo', 'phase':0, 'fanout':'single', 'bias':'spread'}), - ('fixed-address', 'a2', {'prefix':'foo', 'phase':1, 'fanout':'single', 'bias':'spread'}), - ('connector', 'wp_connector', {'port':str(wp_router.ports[0]), 'sasl-mechanisms': 'ANONYMOUS', 'role': 'on-demand'}), - ('waypoint', 'wp', {'address': 'foo', 'in-phase': 0, 'out-phase': 1, 'connector': 'wp_connector'}) + (FIXED_ADDRESS, 'a1', {'prefix':'foo', 'phase':0, 'fanout':'single', 'bias':'spread'}), + (FIXED_ADDRESS, 'a2', {'prefix':'foo', 'phase':1, 'fanout':'single', 'bias':'spread'}), + (CONNECTOR, 'wp_connector', {'port':str(wp_router.ports[0]), 'sasl-mechanisms': 'ANONYMOUS', 'role': 'on-demand'}), + (WAYPOINT, 'wp', {'address': 'foo', 'in-phase': 0, 'out-phase': 1, 'connector': 'wp_connector'}) ]: self.assert_create_ok(*c) assert retry(lambda: self.router.is_connected, wp_router.ports[0]) @@ -185,5 +206,28 @@ class ManagementTest(system_test.TestCas finally: f.close() + def test_read(self): + attributes = self.node2.read(type=LISTENER, name='l0') + self.assertEqual('l0', attributes['name']) + self.assertEqual('l0', attributes['identity']) + self.assertEqual(str(self.router.ports[0]), attributes['port']) + + attributes = self.node2.read(type=LISTENER, identity='l1') + self.assertEqual('l1', attributes['name']) + self.assertEqual('l1', attributes['identity']) + self.assertEqual(str(self.router.ports[1]), attributes['port']) + + # Can't specify both name and identity + self.assertRaisesManagement( + BAD_REQUEST, self.node2.read, type=LISTENER, name='l0', identity='l1') + + # Bad type + self.assertRaisesManagement( + NOT_FOUND, self.node2.read, type=CONNECTOR, name='l0') + + # Unknown entity + self.assertRaisesManagement( + NOT_FOUND, self.node2.read, type=LISTENER, name='nosuch') + if __name__ == '__main__': unittest.main()
Modified: qpid/dispatch/trunk/tools/qdstat URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tools/qdstat?rev=1610827&r1=1610826&r2=1610827&view=diff ============================================================================== --- qpid/dispatch/trunk/tools/qdstat (original) +++ qpid/dispatch/trunk/tools/qdstat Tue Jul 15 19:45:09 2014 @@ -32,7 +32,7 @@ if not home: home = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib', 'qpid-dispatch') sys.path.insert(0, os.path.join(home, "python")) -from qpid_dispatch_internal.management import Url, Node, Entity +from qpid_dispatch_internal.management import Url, Node, QdSchema, Entity from qpid_dispatch_internal.tools import Display, Header, Sorter, YN, Commas, TimeLong @@ -100,6 +100,12 @@ def OptionsAndArguments(argv): class BusManager(Node): + schema = QdSchema() + + def query(self, entity_type): + return [Entity(m) for m in + super(BusManager, self).query(entity_type).result_maps] + def displayConnections(self): disp = Display(prefix=" ") heads = [] @@ -349,7 +355,7 @@ def main(argv=None): else: print "No response after timeout" except Exception,e: - print "Failed: %s - %s" % (e.__class__.__name__, e) + print "%s: %s - %s" % (sys.argv[0], e.__class__.__name__, e) return 1 --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
