From 633c33f224f3196f3f9bd80bd2e418d8143fea06 Mon Sep 17 00:00:00 2001 From: Kim van der Riet Date: Fri, 4 May 2012 15:39:19 +0000 Subject: QPID-3858: Updated branch - merged from trunk r.1333987 git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1334037 13f79535-47bb-0310-9956-ffa450edef68 --- QPID_VERSION.txt | 2 +- bin/install-cpp-python | 76 + cc/LICENSE | 206 - cc/NOTICE | 8 - cc/README.txt | 84 - cc/config.properties | 25 - cc/config.xml | 37 - cc/config/bdbstore-cpp-trunk.xml | 54 - cc/config/cpp-perftests.xml | 63 - cc/config/cpp-trunk.xml | 59 - cc/config/dotnet-trunk.xml | 63 - cc/config/example-automation.xml | 58 - cc/config/java-jmstck.xml | 63 - cc/config/java-perftests.xml | 72 - cc/config/java-trunk.xml | 142 - cc/config/java/cpp.noprefetch.testprofile | 22 - cc/config/java/cpp.testprofile | 21 - cc/config/java/jndi.properties | 42 - cc/dashboard-config.xml | 31 - cc/scripts/bdbstorecppbuild.sh | 24 - cc/scripts/build.xml | 30 - cc/scripts/check_examples.sh | 69 - cc/scripts/cppbuild-perftests.sh | 23 - cc/scripts/cppbuild.sh | 21 - cc/scripts/dotnetbuild.sh | 21 - cc/scripts/javaconfig.sh | 27 - cc/scripts/javajmstck.sh | 80 - cc/scripts/javareport.sh | 25 - cc/scripts/runbroker.sh | 42 - cc/scripts/stopbroker.sh | 31 - cc/scripts/verify | 100 - cc/scripts/verify_all | 166 - cpp/bindings/qmf/ruby/qmf.rb | 26 +- cpp/bindings/qmf/tests/run_interop_tests | 3 +- cpp/bindings/qpid/Makefile.am | 2 +- cpp/bindings/qpid/dotnet/Makefile.am | 2 - cpp/bindings/qpid/python/python.i | 42 +- cpp/bindings/qpid/ruby/README.rdoc | 2 +- cpp/bindings/qpid/ruby/Rakefile | 4 +- .../features/step_definitions/address_steps.rb | 19 + .../features/step_definitions/connection_steps.rb | 19 + .../features/step_definitions/receiver_steps.rb | 19 + .../ruby/features/step_definitions/sender_steps.rb | 19 + .../features/step_definitions/session_steps.rb | 19 + cpp/bindings/qpid/ruby/lib/qpid/encoding.rb | 6 +- cpp/bindings/qpid/ruby/lib/qpid/version.rb | 2 +- cpp/bindings/swig_python_typemaps.i | 6 +- cpp/configure.ac | 75 +- cpp/design_docs/new-ha-design.txt | 93 +- cpp/etc/Makefile.am | 25 +- cpp/etc/cluster.conf-example.xml.in | 70 + cpp/etc/qpidd | 118 - cpp/etc/qpidd-primary.in | 102 + cpp/etc/qpidd.in | 119 + cpp/include/qpid/Options.h | 4 +- cpp/include/qpid/Url.h | 6 +- cpp/include/qpid/framing/Array.h | 22 +- cpp/include/qpid/framing/FieldTable.h | 56 +- cpp/include/qpid/framing/SequenceNumber.h | 6 +- cpp/include/qpid/framing/SequenceSet.h | 6 +- cpp/include/qpid/sys/MemStat.h | 38 - cpp/include/qpid/types/Variant.h | 4 +- cpp/managementgen/qmfgen/management-types.xml | 2 +- cpp/managementgen/qmfgen/schema.py | 14 +- cpp/managementgen/qmfgen/templates/Class.h | 59 +- cpp/managementgen/qmfgen/templates/Event.h | 13 +- cpp/managementgen/qmfgen/templates/Package.h | 5 +- cpp/rubygen/framing.0-10/structs.rb | 26 +- cpp/src/CMakeLists.txt | 52 +- cpp/src/Makefile.am | 25 +- cpp/src/acl.mk | 2 + cpp/src/config.h.cmake | 1 + cpp/src/ha.mk | 16 +- cpp/src/posix/QpiddBroker.cpp | 17 +- cpp/src/qmf.mk | 1 + cpp/src/qmf/BrokerImportExport.h | 42 + cpp/src/qpid/Options.cpp | 7 +- cpp/src/qpid/Url.cpp | 17 +- cpp/src/qpid/UrlArray.cpp | 2 + cpp/src/qpid/UrlArray.h | 1 - cpp/src/qpid/acl/Acl.cpp | 183 +- cpp/src/qpid/acl/Acl.h | 75 +- cpp/src/qpid/acl/AclConnectionCounter.cpp | 214 + cpp/src/qpid/acl/AclConnectionCounter.h | 81 + cpp/src/qpid/acl/AclData.cpp | 572 +- cpp/src/qpid/acl/AclData.h | 89 +- cpp/src/qpid/acl/AclPlugin.cpp | 4 +- cpp/src/qpid/acl/AclReader.cpp | 222 +- cpp/src/qpid/acl/AclReader.h | 80 +- cpp/src/qpid/acl/AclValidator.cpp | 61 +- cpp/src/qpid/acl/AclValidator.h | 24 +- cpp/src/qpid/acl/management-schema.xml | 34 + cpp/src/qpid/agent/ManagementAgentImpl.cpp | 11 +- cpp/src/qpid/broker/AclModule.h | 191 +- cpp/src/qpid/broker/Bridge.cpp | 15 +- cpp/src/qpid/broker/Bridge.h | 13 +- cpp/src/qpid/broker/Broker.cpp | 7 +- cpp/src/qpid/broker/Broker.h | 87 +- cpp/src/qpid/broker/Connection.cpp | 16 +- cpp/src/qpid/broker/Connection.h | 5 + cpp/src/qpid/broker/ConnectionHandler.cpp | 1 + cpp/src/qpid/broker/ConnectionHandler.h | 1 - cpp/src/qpid/broker/DirectExchange.cpp | 3 +- cpp/src/qpid/broker/DirectExchange.h | 4 +- cpp/src/qpid/broker/DtxManager.cpp | 29 +- cpp/src/qpid/broker/DtxManager.h | 3 + cpp/src/qpid/broker/DtxWorkRecord.cpp | 11 +- cpp/src/qpid/broker/Exchange.cpp | 28 +- cpp/src/qpid/broker/Exchange.h | 2 +- cpp/src/qpid/broker/ExchangeRegistry.cpp | 3 + cpp/src/qpid/broker/ExchangeRegistry.h | 6 +- cpp/src/qpid/broker/Fairshare.cpp | 1 + cpp/src/qpid/broker/FanOutExchange.cpp | 2 +- cpp/src/qpid/broker/FanOutExchange.h | 4 +- cpp/src/qpid/broker/HeadersExchange.cpp | 3 +- cpp/src/qpid/broker/HeadersExchange.h | 4 +- cpp/src/qpid/broker/LegacyLVQ.cpp | 29 +- cpp/src/qpid/broker/LegacyLVQ.h | 1 + cpp/src/qpid/broker/Link.cpp | 263 +- cpp/src/qpid/broker/Link.h | 58 +- cpp/src/qpid/broker/LinkRegistry.cpp | 31 +- cpp/src/qpid/broker/LinkRegistry.h | 110 +- cpp/src/qpid/broker/Message.cpp | 8 +- cpp/src/qpid/broker/MessageDeque.cpp | 20 +- cpp/src/qpid/broker/MessageDeque.h | 7 +- cpp/src/qpid/broker/MessageGroupManager.cpp | 92 +- cpp/src/qpid/broker/MessageGroupManager.h | 19 +- cpp/src/qpid/broker/MessageMap.cpp | 78 +- cpp/src/qpid/broker/MessageMap.h | 2 +- cpp/src/qpid/broker/PriorityQueue.cpp | 118 +- cpp/src/qpid/broker/PriorityQueue.h | 27 +- cpp/src/qpid/broker/Queue.cpp | 667 +- cpp/src/qpid/broker/Queue.h | 147 +- cpp/src/qpid/broker/QueueListeners.cpp | 4 - cpp/src/qpid/broker/QueueListeners.h | 7 +- cpp/src/qpid/broker/QueuedMessage.cpp | 34 + cpp/src/qpid/broker/QueuedMessage.h | 3 + cpp/src/qpid/broker/SaslAuthenticator.cpp | 1 + cpp/src/qpid/broker/SemanticState.cpp | 4 +- cpp/src/qpid/broker/SemanticState.h | 65 +- cpp/src/qpid/broker/SessionAdapter.cpp | 51 +- cpp/src/qpid/broker/SessionAdapter.h | 4 +- cpp/src/qpid/broker/SessionHandler.cpp | 5 + cpp/src/qpid/broker/SessionHandler.h | 10 +- cpp/src/qpid/broker/TopicExchange.cpp | 3 +- cpp/src/qpid/broker/TopicExchange.h | 4 +- cpp/src/qpid/broker/windows/SaslAuthenticator.cpp | 1 + cpp/src/qpid/client/Connection.cpp | 2 +- cpp/src/qpid/client/ConnectionHandler.cpp | 10 +- cpp/src/qpid/client/ConnectionImpl.cpp | 4 +- cpp/src/qpid/client/LoadPlugins.cpp | 6 +- cpp/src/qpid/client/SessionImpl.cpp | 2 +- cpp/src/qpid/client/SslConnector.cpp | 4 +- cpp/src/qpid/client/TCPConnector.cpp | 8 +- cpp/src/qpid/client/amqp0_10/AddressResolution.cpp | 1 + cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp | 3 +- cpp/src/qpid/cluster/Cluster.cpp | 28 +- cpp/src/qpid/cluster/ClusterMap.cpp | 4 +- cpp/src/qpid/cluster/ClusterTimer.cpp | 2 + cpp/src/qpid/cluster/Connection.cpp | 49 + cpp/src/qpid/cluster/Connection.h | 2 + cpp/src/qpid/cluster/CredentialsExchange.cpp | 3 +- cpp/src/qpid/cluster/CredentialsExchange.h | 2 +- cpp/src/qpid/cluster/FailoverExchange.cpp | 2 +- cpp/src/qpid/cluster/FailoverExchange.h | 2 +- cpp/src/qpid/cluster/InitialStatusMap.cpp | 2 +- cpp/src/qpid/cluster/UpdateClient.cpp | 11 +- cpp/src/qpid/cluster/UpdateDataExchange.cpp | 4 +- cpp/src/qpid/cluster/UpdateDataExchange.h | 3 +- cpp/src/qpid/framing/AMQFrame.h | 3 +- cpp/src/qpid/framing/BodyHandler.cpp | 56 - cpp/src/qpid/framing/BodyHandler.h | 56 - cpp/src/qpid/framing/FieldTable.cpp | 219 +- cpp/src/qpid/framing/FrameSet.cpp | 5 +- cpp/src/qpid/framing/FrameSet.h | 1 + cpp/src/qpid/framing/MethodContent.h | 2 +- cpp/src/qpid/framing/TransferContent.cpp | 2 +- cpp/src/qpid/framing/TransferContent.h | 2 +- cpp/src/qpid/framing/amqp_framing.h | 1 - cpp/src/qpid/ha/Backup.cpp | 36 +- cpp/src/qpid/ha/Backup.h | 4 +- cpp/src/qpid/ha/BrokerReplicator.cpp | 190 +- cpp/src/qpid/ha/BrokerReplicator.h | 16 +- cpp/src/qpid/ha/HaBroker.cpp | 95 +- cpp/src/qpid/ha/HaBroker.h | 8 + cpp/src/qpid/ha/HaPlugin.cpp | 28 +- cpp/src/qpid/ha/QueueReplicator.cpp | 62 +- cpp/src/qpid/ha/QueueReplicator.h | 5 +- cpp/src/qpid/ha/ReplicateLevel.cpp | 72 + cpp/src/qpid/ha/ReplicateLevel.h | 52 + cpp/src/qpid/ha/ReplicatingSubscription.cpp | 71 +- cpp/src/qpid/ha/ReplicatingSubscription.h | 4 +- cpp/src/qpid/ha/Settings.h | 7 +- cpp/src/qpid/ha/management-schema.xml | 35 +- cpp/src/qpid/log/Statement.cpp | 44 + cpp/src/qpid/log/posix/SinkOptions.cpp | 8 +- cpp/src/qpid/management/ManagementAgent.cpp | 79 +- cpp/src/qpid/management/ManagementAgent.h | 4 +- .../qpid/management/ManagementDirectExchange.cpp | 8 +- cpp/src/qpid/management/ManagementDirectExchange.h | 4 +- .../qpid/management/ManagementTopicExchange.cpp | 8 +- cpp/src/qpid/management/ManagementTopicExchange.h | 4 +- .../qpid/replication/ReplicatingEventListener.cpp | 4 +- cpp/src/qpid/replication/ReplicationExchange.cpp | 11 +- cpp/src/qpid/replication/ReplicationExchange.h | 2 +- cpp/src/qpid/store/MessageStorePlugin.cpp | 6 +- cpp/src/qpid/store/ms-clfs/MessageLog.cpp | 8 +- cpp/src/qpid/store/ms-clfs/Transaction.h | 1 + cpp/src/qpid/store/ms-clfs/TransactionLog.cpp | 8 +- cpp/src/qpid/sys/MemStat.h | 38 + cpp/src/qpid/sys/Probes.h | 65 + cpp/src/qpid/sys/apr/APRBase.cpp | 89 - cpp/src/qpid/sys/apr/APRBase.h | 74 - cpp/src/qpid/sys/apr/APRPool.cpp | 41 - cpp/src/qpid/sys/apr/APRPool.h | 50 - cpp/src/qpid/sys/apr/Condition.h | 84 - cpp/src/qpid/sys/apr/Mutex.h | 124 - cpp/src/qpid/sys/apr/Shlib.cpp | 49 - cpp/src/qpid/sys/apr/Socket.cpp | 114 - cpp/src/qpid/sys/apr/Thread.cpp | 34 - cpp/src/qpid/sys/apr/Thread.h | 106 - cpp/src/qpid/sys/apr/Time.cpp | 36 - cpp/src/qpid/sys/posix/AsynchIO.cpp | 38 +- cpp/src/qpid/sys/posix/PollableCondition.cpp | 5 - cpp/src/qpid/sys/ssl/SslIo.cpp | 7 +- cpp/src/qpid/sys/windows/AsynchIO.cpp | 100 +- cpp/src/qpid/sys/windows/PollableCondition.cpp | 5 - cpp/src/qpid/sys/windows/Socket.cpp | 10 +- cpp/src/qpid/sys/windows/SslAsynchIO.cpp | 8 +- cpp/src/qpid/xml/XmlExchange.cpp | 4 +- cpp/src/qpid/xml/XmlExchange.h | 2 +- cpp/src/qpidd.cpp | 4 + cpp/src/qpidd.h | 4 + cpp/src/tests/Array.cpp | 4 +- cpp/src/tests/CMakeLists.txt | 25 +- cpp/src/tests/ExchangeTest.cpp | 46 +- cpp/src/tests/FieldTable.cpp | 4 +- cpp/src/tests/Frame.cpp | 1 - cpp/src/tests/FramingTest.cpp | 1 + cpp/src/tests/Makefile.am | 23 +- cpp/src/tests/MessagingSessionTests.cpp | 7 + cpp/src/tests/QueueFlowLimitTest.cpp | 1 + cpp/src/tests/QueueTest.cpp | 52 +- cpp/src/tests/RefCounted.cpp | 6 +- cpp/src/tests/SessionState.cpp | 1 - cpp/src/tests/StringUtils.cpp | 6 +- cpp/src/tests/Uuid.cpp | 2 +- cpp/src/tests/acl.py | 957 +- cpp/src/tests/ais_check | 34 - cpp/src/tests/amqp_0_10/Map.cpp | 98 - cpp/src/tests/amqp_0_10/ProxyTemplate.cpp | 49 - cpp/src/tests/amqp_0_10/apply.cpp | 99 - cpp/src/tests/amqp_0_10/handlers.cpp | 125 - cpp/src/tests/amqp_0_10/serialize.cpp | 429 - cpp/src/tests/brokertest.py | 56 +- cpp/src/tests/cli_tests.py | 139 +- cpp/src/tests/cluster.cmake | 2 +- cpp/src/tests/cluster.mk | 11 +- cpp/src/tests/cluster_failover | 19 + cpp/src/tests/cluster_python_tests | 3 +- cpp/src/tests/cluster_read_credit | 4 +- cpp/src/tests/cluster_test_logs.py | 6 +- cpp/src/tests/cluster_tests.py | 122 +- cpp/src/tests/clustered_replication_test | 27 +- cpp/src/tests/cpg_check.sh.in | 38 + cpp/src/tests/federated_cluster_test | 35 +- cpp/src/tests/ha_tests.py | 523 +- cpp/src/tests/install_env.sh.in | 2 +- cpp/src/tests/ipv6_test | 9 +- cpp/src/tests/logging.cpp | 9 +- cpp/src/tests/python_tests.ps1 | 5 +- cpp/src/tests/qpid-cluster-benchmark | 29 +- cpp/src/tests/qpid-cpp-benchmark | 69 +- cpp/src/tests/qpid-perftest.cpp | 12 +- cpp/src/tests/qpid-ping.cpp | 27 +- cpp/src/tests/qpid-send.cpp | 67 +- cpp/src/tests/qpid-txtest.cpp | 5 +- cpp/src/tests/qpidd-empty.conf | 3 + cpp/src/tests/queue_flow_limit_tests.py | 2 +- cpp/src/tests/reliable_replication_test | 6 +- cpp/src/tests/replication_test | 34 +- cpp/src/tests/ring_queue_test | 2 +- cpp/src/tests/run_acl_tests | 24 +- cpp/src/tests/run_acl_tests.ps1 | 5 +- cpp/src/tests/run_cli_tests | 4 +- cpp/src/tests/run_cluster_authentication_soak | 3 +- cpp/src/tests/run_cluster_authentication_test | 3 +- cpp/src/tests/run_cluster_test | 3 +- cpp/src/tests/run_cluster_tests | 4 +- cpp/src/tests/run_failover_soak | 3 +- cpp/src/tests/run_federation_sys_tests | 8 +- cpp/src/tests/run_federation_tests | 15 +- cpp/src/tests/run_federation_tests.ps1 | 3 +- cpp/src/tests/run_header_test.ps1 | 3 +- cpp/src/tests/run_msg_group_tests | 8 +- cpp/src/tests/run_msg_group_tests_soak | 4 +- cpp/src/tests/run_store_tests.ps1 | 9 +- cpp/src/tests/run_test.ps1 | 5 +- cpp/src/tests/sasl.mk | 21 +- cpp/src/tests/sasl_fed | 16 +- cpp/src/tests/sasl_fed_ex | 12 +- cpp/src/tests/sasl_fed_ex_dynamic_cluster | 4 +- cpp/src/tests/sasl_fed_ex_link_cluster | 3 +- cpp/src/tests/sasl_fed_ex_queue_cluster | 3 +- cpp/src/tests/sasl_fed_ex_route_cluster | 3 +- cpp/src/tests/ssl_test | 13 +- cpp/src/tests/start_cluster | 3 +- cpp/src/tests/test_env.ps1.in | 78 + cpp/src/tests/test_env.sh.in | 2 + cpp/src/tests/testagent.cpp | 11 +- cpp/src/tests/testlib.py | 4 +- cpp/src/tests/windows/DisableWin32ErrorWindows.cpp | 6 +- cpp/src/windows/QpiddBroker.cpp | 12 +- cpp/src/windows/SCM.cpp | 664 +- cpp/xml/cluster.xml | 6 + doc/book/Makefile | 37 +- doc/book/README.txt | 118 - doc/book/build-book.sh | 63 - doc/book/build-chapter.sh | 44 - doc/book/build.sh | 40 - doc/book/build.xml | 193 - doc/book/src/ACL.xml | 800 - doc/book/src/AMQP-.NET-Messaging-Client.xml | 108 - doc/book/src/AMQP-C++-Messaging-Client.xml | 61 - doc/book/src/AMQP-Compatibility.xml | 713 - doc/book/src/AMQP-Java-JMS-Messaging-Client.xml | 94 - doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml | 76 - doc/book/src/AMQP-Messaging-Broker-CPP.xml | 70 - doc/book/src/AMQP-Messaging-Broker-Java-Book.xml | 73 - doc/book/src/AMQP-Messaging-Broker-Java.xml | 72 - doc/book/src/AMQP-Python-Messaging-Client.xml | 62 - doc/book/src/AMQP-Ruby-Messaging-Client.xml | 40 - doc/book/src/AMQP.xml | 98 - doc/book/src/Add-New-Users.xml | 237 - doc/book/src/Binding-URL-Format.xml | 174 - doc/book/src/Book-Info.xml | 68 - doc/book/src/Book.xml | 93 - doc/book/src/Broker-CPP.xml | 40 - doc/book/src/Broker-Configuration-Guide.xml | 28 - doc/book/src/Broker-Java.xml | 45 - ...heat-Sheet-for-configuring-Exchange-Options.xml | 144 - .../Cheat-Sheet-for-configuring-Queue-Options.xml | 259 - doc/book/src/Clients.xml | 25 - doc/book/src/Configure-ACLs.xml | 441 - ...Configure-Java-Qpid-to-use-a-SSL-connection.xml | 84 - .../Configure-Log4j-CompositeRolling-Appender.xml | 150 - .../src/Configure-the-Broker-via-config.xml.xml | 71 - ...gure-the-Virtual-Hosts-via-virtualhosts.xml.xml | 131 - doc/book/src/Configuring-Management-Users.xml | 117 - .../Configuring-Qpid-JMX-Management-Console.xml | 181 - doc/book/src/Connection-URL-Format.xml | 387 - doc/book/src/Debug-using-log4j.xml | 298 - doc/book/src/Download.xml | 174 - doc/book/src/Excel-AddIn.xml | 169 - doc/book/src/FAQ.xml | 524 - doc/book/src/Getting-Started.xml | 90 - .../src/How-to-Tune-M3-Java-Broker-Performance.xml | 172 - doc/book/src/How-to-Use-JNDI.xml | 175 - doc/book/src/How-to-Use-SlowConsumerDisconnect.xml | 280 - doc/book/src/InfoPlugin.xml | 261 - doc/book/src/Introduction.xml | 106 - doc/book/src/Java-Broker-Feature-Guide.xml | 84 - doc/book/src/Java-Broker-StatusLogMessages.xml | 294 - doc/book/src/Java-Environment-Variables.xml | 84 - doc/book/src/Java-JMS-Selector-Syntax.xml | 96 - doc/book/src/LVQ.xml | 182 - doc/book/src/Makefile.inc | 63 + doc/book/src/Management-Console-Security.xml | 252 - doc/book/src/Management-Design-notes.xml | 2136 --- doc/book/src/Managing-CPP-Broker.xml | 462 - doc/book/src/Message-Groups-Guide.xml | 164 - doc/book/src/MessageStore-Tool.xml | 150 - doc/book/src/NET-User-Guide.xml | 1383 -- doc/book/src/Programming-In-Apache-Qpid.xml | 6500 -------- doc/book/src/PythonBrokerTest.xml | 98 - doc/book/src/QMF-Python-Console-Tutorial.xml | 894 - doc/book/src/QMan-Qpid-Management-bridge.xml | 166 - doc/book/src/QmfBook.xml | 101 - doc/book/src/QmfIntroduction.xml | 45 - doc/book/src/Qpid-ACLs.xml | 49 - doc/book/src/Qpid-Book.xml | 93 - ...pid-Compatibility-And-Interoperability-Book.xml | 36 - .../src/Qpid-Interoperability-Documentation.xml | 377 - doc/book/src/Qpid-JMX-Management-Console-FAQ.xml | 96 - .../src/Qpid-JMX-Management-Console-User-Guide.xml | 793 - doc/book/src/Qpid-JMX-Management-Console.xml | 53 - doc/book/src/Qpid-Java-Broker-Management-CLI.xml | 159 - doc/book/src/Qpid-Java-Build-How-To.xml | 365 - doc/book/src/Qpid-Java-FAQ.xml | 895 - doc/book/src/Qpid-Management-Features.xml | 185 - doc/book/src/Qpid-Management-Framework.xml | 944 -- doc/book/src/Qpid-Troubleshooting-Guide.xml | 156 - doc/book/src/Running-CPP-Broker.xml | 385 - doc/book/src/SASL-Compatibility.xml | 70 - doc/book/src/SSL.xml | 180 - doc/book/src/Security-Plugins.xml | 611 - doc/book/src/Security.xml | 1217 -- doc/book/src/Starting-a-cluster.xml | 561 - doc/book/src/System-Properties.xml | 357 - doc/book/src/Use-Priority-Queues.xml | 138 - doc/book/src/Using-Broker-Federation.xml | 661 - .../src/Using-Qpid-with-other-JNDI-Providers.xml | 215 - doc/book/src/Using-message-groups.xml | 295 - doc/book/src/WCF.xml | 137 - .../amqp-advanced-message-queueing-protocol.html | 237 - doc/book/src/common/css/style.css | 279 + doc/book/src/cpp-broker/AMQP-Compatibility.xml | 713 + .../cpp-broker/AMQP-Messaging-Broker-CPP-Book.xml | 75 + doc/book/src/cpp-broker/Active-Active-Cluster.xml | 561 + doc/book/src/cpp-broker/Active-Passive-Cluster.xml | 661 + ...heat-Sheet-for-configuring-Exchange-Options.xml | 144 + .../Cheat-Sheet-for-configuring-Queue-Options.xml | 259 + doc/book/src/cpp-broker/HA-Queue-Replication.xml | 54 + doc/book/src/cpp-broker/LVQ.xml | 181 + doc/book/src/cpp-broker/Makefile | 20 + doc/book/src/cpp-broker/Managing-CPP-Broker.xml | 485 + .../src/cpp-broker/QMF-Python-Console-Tutorial.xml | 894 + .../Qpid-Interoperability-Documentation.xml | 377 + .../src/cpp-broker/Qpid-Management-Framework.xml | 944 ++ doc/book/src/cpp-broker/Running-CPP-Broker.xml | 385 + doc/book/src/cpp-broker/Security.xml | 1258 ++ .../src/cpp-broker/Using-Broker-Federation.xml | 661 + doc/book/src/cpp-broker/Using-message-groups.xml | 295 + doc/book/src/cpp-broker/producer-flow-control.xml | 351 + .../src/cpp-broker/queue-state-replication.xml | 333 + doc/book/src/css/style.css | 129 - doc/book/src/images/jmx_console/3113098.png | Bin 9805 -> 0 bytes doc/book/src/images/jmx_console/3113099.png | Bin 12882 -> 0 bytes doc/book/src/images/jmx_console/3113100.png | Bin 38529 -> 0 bytes doc/book/src/images/jmx_console/3113101.png | Bin 45933 -> 0 bytes doc/book/src/images/jmx_console/3113102.png | Bin 7126 -> 0 bytes doc/book/src/images/jmx_console/3113103.png | Bin 34693 -> 0 bytes doc/book/src/images/jmx_console/3113104.png | Bin 61810 -> 0 bytes doc/book/src/images/jmx_console/3113105.png | Bin 26365 -> 0 bytes doc/book/src/images/jmx_console/3113106.png | Bin 45911 -> 0 bytes doc/book/src/images/jmx_console/3113107.png | Bin 31789 -> 0 bytes doc/book/src/images/jmx_console/3113108.png | Bin 39198 -> 0 bytes doc/book/src/images/jmx_console/3113109.png | Bin 13295 -> 0 bytes doc/book/src/images/jmx_console/3113110.png | Bin 38715 -> 0 bytes doc/book/src/images/jmx_console/3113111.png | Bin 52694 -> 0 bytes doc/book/src/images/jmx_console/3113112.png | Bin 39276 -> 0 bytes doc/book/src/images/jmx_console/3113113.png | Bin 46459 -> 0 bytes doc/book/src/images/jmx_console/3113114.png | Bin 64661 -> 0 bytes doc/book/src/images/jmx_console/3113115.png | Bin 38902 -> 0 bytes doc/book/src/images/jmx_console/3113116.png | Bin 9252 -> 0 bytes doc/book/src/images/jmx_console/3113117.png | Bin 40855 -> 0 bytes doc/book/src/images/jmx_console/3113118.png | Bin 13796 -> 0 bytes doc/book/src/images/jmx_console/3113119.png | Bin 39115 -> 0 bytes .../AMQP-Messaging-Broker-Java-Book.xml | 73 + doc/book/src/java-broker/Add-New-Users.xml | 237 + .../src/java-broker/Broker-Configuration-Guide.xml | 28 + doc/book/src/java-broker/Configure-ACLs.xml | 441 + ...Configure-Java-Qpid-to-use-a-SSL-connection.xml | 84 + .../Configure-Log4j-CompositeRolling-Appender.xml | 150 + .../Configure-the-Broker-via-config.xml.xml | 71 + ...gure-the-Virtual-Hosts-via-virtualhosts.xml.xml | 131 + .../java-broker/Configuring-Management-Users.xml | 117 + .../Configuring-Qpid-JMX-Management-Console.xml | 181 + doc/book/src/java-broker/Debug-using-log4j.xml | 298 + .../How-to-Tune-M3-Java-Broker-Performance.xml | 172 + .../How-to-Use-SlowConsumerDisconnect.xml | 280 + .../src/java-broker/Java-Broker-Feature-Guide.xml | 84 + .../src/java-broker/Java-Environment-Variables.xml | 84 + doc/book/src/java-broker/Makefile | 20 + .../java-broker/Management-Console-Security.xml | 251 + doc/book/src/java-broker/MessageStore-Tool.xml | 150 + .../Qpid-JMX-Management-Console-FAQ.xml | 96 + .../Qpid-JMX-Management-Console-User-Guide.xml | 793 + .../java-broker/Qpid-JMX-Management-Console.xml | 53 + .../Qpid-Java-Broker-Management-CLI.xml | 159 + .../src/java-broker/Qpid-Java-Build-How-To.xml | 365 + doc/book/src/java-broker/Qpid-Java-FAQ.xml | 895 + .../src/java-broker/Qpid-Management-Features.xml | 185 + .../src/java-broker/Qpid-Troubleshooting-Guide.xml | 156 + doc/book/src/java-broker/Topic-Configuration.xml | 107 + doc/book/src/java-broker/Use-Priority-Queues.xml | 138 + doc/book/src/java-broker/images/3113098.png | Bin 0 -> 9805 bytes doc/book/src/java-broker/images/3113099.png | Bin 0 -> 12882 bytes doc/book/src/java-broker/images/3113100.png | Bin 0 -> 38529 bytes doc/book/src/java-broker/images/3113101.png | Bin 0 -> 45933 bytes doc/book/src/java-broker/images/3113102.png | Bin 0 -> 7126 bytes doc/book/src/java-broker/images/3113103.png | Bin 0 -> 34693 bytes doc/book/src/java-broker/images/3113104.png | Bin 0 -> 61810 bytes doc/book/src/java-broker/images/3113105.png | Bin 0 -> 26365 bytes doc/book/src/java-broker/images/3113106.png | Bin 0 -> 45911 bytes doc/book/src/java-broker/images/3113107.png | Bin 0 -> 31789 bytes doc/book/src/java-broker/images/3113108.png | Bin 0 -> 39198 bytes doc/book/src/java-broker/images/3113109.png | Bin 0 -> 13295 bytes doc/book/src/java-broker/images/3113110.png | Bin 0 -> 38715 bytes doc/book/src/java-broker/images/3113111.png | Bin 0 -> 52694 bytes doc/book/src/java-broker/images/3113112.png | Bin 0 -> 39276 bytes doc/book/src/java-broker/images/3113113.png | Bin 0 -> 46459 bytes doc/book/src/java-broker/images/3113114.png | Bin 0 -> 64661 bytes doc/book/src/java-broker/images/3113115.png | Bin 0 -> 38902 bytes doc/book/src/java-broker/images/3113116.png | Bin 0 -> 9252 bytes doc/book/src/java-broker/images/3113117.png | Bin 0 -> 40855 bytes doc/book/src/java-broker/images/3113118.png | Bin 0 -> 13796 bytes doc/book/src/java-broker/images/3113119.png | Bin 0 -> 39115 bytes .../broker/configuration/Topic-Configuration.xml | 107 - doc/book/src/old/ACL.xml | 800 + doc/book/src/old/AMQP-.NET-Messaging-Client.xml | 108 + doc/book/src/old/AMQP-C++-Messaging-Client.xml | 61 + .../src/old/AMQP-Java-JMS-Messaging-Client.xml | 94 + doc/book/src/old/AMQP-Messaging-Broker-CPP.xml | 70 + doc/book/src/old/AMQP-Python-Messaging-Client.xml | 62 + doc/book/src/old/AMQP-Ruby-Messaging-Client.xml | 40 + doc/book/src/old/AMQP.xml | 98 + doc/book/src/old/Binding-URL-Format.xml | 174 + doc/book/src/old/Book-Info.xml | 68 + doc/book/src/old/Book.xml | 93 + doc/book/src/old/Broker-CPP.xml | 40 + doc/book/src/old/Broker-Java.xml | 45 + doc/book/src/old/Clients.xml | 25 + doc/book/src/old/Connection-URL-Format.xml | 387 + doc/book/src/old/Download.xml | 174 + doc/book/src/old/Excel-AddIn.xml | 169 + doc/book/src/old/FAQ.xml | 524 + doc/book/src/old/Getting-Started.xml | 90 + doc/book/src/old/How-to-Use-JNDI.xml | 175 + doc/book/src/old/InfoPlugin.xml | 261 + doc/book/src/old/Introduction.xml | 106 + doc/book/src/old/Java-Broker-StatusLogMessages.xml | 294 + doc/book/src/old/Java-JMS-Selector-Syntax.xml | 96 + doc/book/src/old/Management-Design-notes.xml | 2136 +++ doc/book/src/old/NET-User-Guide.xml | 1383 ++ doc/book/src/old/PythonBrokerTest.xml | 98 + doc/book/src/old/QMan-Qpid-Management-bridge.xml | 166 + doc/book/src/old/Qpid-ACLs.xml | 49 + doc/book/src/old/Qpid-Book.xml | 93 + ...pid-Compatibility-And-Interoperability-Book.xml | 36 + doc/book/src/old/SASL-Compatibility.xml | 70 + doc/book/src/old/SSL.xml | 180 + doc/book/src/old/Security-Plugins.xml | 611 + doc/book/src/old/System-Properties.xml | 357 + .../old/Using-Qpid-with-other-JNDI-Providers.xml | 215 + doc/book/src/old/WCF.xml | 137 + doc/book/src/old/schemas.xml | 102 + doc/book/src/producer-flow-control.xml | 351 - doc/book/src/programming/Makefile | 20 + doc/book/src/programming/Message-Groups-Guide.xml | 164 + .../Programming-In-Apache-Qpid-Book.xml | 6500 ++++++++ doc/book/src/qmf/QmfBook.xml | 101 + doc/book/src/qmf/QmfIntroduction.xml | 45 + doc/book/src/queue-state-replication.xml | 333 - doc/book/src/schemas.xml | 101 - doc/book/xsl/html-custom.xsl | 188 + extras/qmf/setup.py | 2 +- extras/qmf/src/py/qmf/console.py | 2 +- java/.gitignore | 2 + java/amqp-1-0-client-jms/build.xml | 29 + .../apache/qpid/amqp_1_0/jms/example/Hello.java | 178 + .../qpid/amqp_1_0/jms/example/hello.properties | 28 + .../org/apache/qpid/amqp_1_0/jms/AmqpMessage.java | 32 + .../org/apache/qpid/amqp_1_0/jms/BytesMessage.java | 26 + .../org/apache/qpid/amqp_1_0/jms/Connection.java | 37 + .../qpid/amqp_1_0/jms/ConnectionFactory.java | 31 + .../qpid/amqp_1_0/jms/ConnectionMetaData.java | 28 + .../org/apache/qpid/amqp_1_0/jms/Destination.java | 28 + .../apache/qpid/amqp_1_0/jms/JavaSerializable.java | 24 + .../org/apache/qpid/amqp_1_0/jms/MapMessage.java | 37 + .../java/org/apache/qpid/amqp_1_0/jms/Message.java | 178 + .../apache/qpid/amqp_1_0/jms/MessageConsumer.java | 36 + .../apache/qpid/amqp_1_0/jms/MessageProducer.java | 27 + .../apache/qpid/amqp_1_0/jms/ObjectMessage.java | 27 + .../java/org/apache/qpid/amqp_1_0/jms/Queue.java | 26 + .../org/apache/qpid/amqp_1_0/jms/QueueBrowser.java | 30 + .../apache/qpid/amqp_1_0/jms/QueueConnection.java | 30 + .../apache/qpid/amqp_1_0/jms/QueueReceiver.java | 29 + .../org/apache/qpid/amqp_1_0/jms/QueueSender.java | 29 + .../org/apache/qpid/amqp_1_0/jms/QueueSession.java | 42 + .../java/org/apache/qpid/amqp_1_0/jms/Session.java | 75 + .../apache/qpid/amqp_1_0/jms/StreamMessage.java | 26 + .../qpid/amqp_1_0/jms/TemporaryDestination.java | 33 + .../apache/qpid/amqp_1_0/jms/TemporaryQueue.java | 26 + .../apache/qpid/amqp_1_0/jms/TemporaryTopic.java | 26 + .../org/apache/qpid/amqp_1_0/jms/TextMessage.java | 26 + .../java/org/apache/qpid/amqp_1_0/jms/Topic.java | 26 + .../apache/qpid/amqp_1_0/jms/TopicConnection.java | 30 + .../apache/qpid/amqp_1_0/jms/TopicPublisher.java | 26 + .../org/apache/qpid/amqp_1_0/jms/TopicSession.java | 43 + .../apache/qpid/amqp_1_0/jms/TopicSubscriber.java | 29 + .../qpid/amqp_1_0/jms/impl/AmqpMessageImpl.java | 78 + .../qpid/amqp_1_0/jms/impl/BytesMessageImpl.java | 538 + .../amqp_1_0/jms/impl/ConnectionFactoryImpl.java | 173 + .../qpid/amqp_1_0/jms/impl/ConnectionImpl.java | 329 + .../amqp_1_0/jms/impl/ConnectionMetaDataImpl.java | 105 + .../qpid/amqp_1_0/jms/impl/DestinationImpl.java | 85 + .../qpid/amqp_1_0/jms/impl/MapMessageImpl.java | 444 + .../amqp_1_0/jms/impl/MessageConsumerImpl.java | 447 + .../qpid/amqp_1_0/jms/impl/MessageFactory.java | 191 + .../apache/qpid/amqp_1_0/jms/impl/MessageImpl.java | 1209 ++ .../amqp_1_0/jms/impl/MessageProducerImpl.java | 362 + .../qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java | 143 + .../qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java | 138 + .../amqp_1_0/jms/impl/QueueConnectionImpl.java | 48 + .../apache/qpid/amqp_1_0/jms/impl/QueueImpl.java | 56 + .../qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java | 57 + .../qpid/amqp_1_0/jms/impl/QueueSenderImpl.java | 36 + .../qpid/amqp_1_0/jms/impl/QueueSessionImpl.java | 56 + .../apache/qpid/amqp_1_0/jms/impl/SessionImpl.java | 898 + .../qpid/amqp_1_0/jms/impl/StreamMessageImpl.java | 466 + .../qpid/amqp_1_0/jms/impl/TemporaryQueueImpl.java | 105 + .../qpid/amqp_1_0/jms/impl/TemporaryTopicImpl.java | 110 + .../qpid/amqp_1_0/jms/impl/TextMessageImpl.java | 93 + .../amqp_1_0/jms/impl/TopicConnectionImpl.java | 48 + .../apache/qpid/amqp_1_0/jms/impl/TopicImpl.java | 56 + .../qpid/amqp_1_0/jms/impl/TopicPublisherImpl.java | 36 + .../qpid/amqp_1_0/jms/impl/TopicSessionImpl.java | 55 + .../amqp_1_0/jms/impl/TopicSubscriberImpl.java | 133 + .../qpid/amqp_1_0/jms/jndi/NameParserImpl.java | 37 + .../jndi/PropertiesFileInitialContextFactory.java | 230 + .../qpid/amqp_1_0/jms/jndi/ReadOnlyContext.java | 527 + java/amqp-1-0-client/build.xml | 29 + .../qpid/amqp_1_0/client/AcknowledgeMode.java | 28 + .../org/apache/qpid/amqp_1_0/client/Command.java | 43 + .../apache/qpid/amqp_1_0/client/Connection.java | 481 + .../java/org/apache/qpid/amqp_1_0/client/Demo.java | 407 + .../java/org/apache/qpid/amqp_1_0/client/Dump.java | 116 + .../apache/qpid/amqp_1_0/client/Filereceiver.java | 327 + .../apache/qpid/amqp_1_0/client/Filesender.java | 276 + .../org/apache/qpid/amqp_1_0/client/Message.java | 148 + .../org/apache/qpid/amqp_1_0/client/ReadBytes.java | 77 + .../org/apache/qpid/amqp_1_0/client/Receive.java | 246 + .../org/apache/qpid/amqp_1_0/client/Receiver.java | 561 + .../org/apache/qpid/amqp_1_0/client/Request.java | 249 + .../org/apache/qpid/amqp_1_0/client/Respond.java | 347 + .../java/org/apache/qpid/amqp_1_0/client/Send.java | 244 + .../org/apache/qpid/amqp_1_0/client/SendBytes.java | 331 + .../org/apache/qpid/amqp_1_0/client/Sender.java | 392 + .../org/apache/qpid/amqp_1_0/client/Session.java | 354 + .../apache/qpid/amqp_1_0/client/Transaction.java | 49 + .../amqp_1_0/client/TransactionController.java | 194 + .../java/org/apache/qpid/amqp_1_0/client/Util.java | 529 + java/amqp-1-0-common/build.xml | 27 + .../codec/AbstractDescribedTypeWriter.java | 188 + .../qpid/amqp_1_0/codec/AbstractListWriter.java | 41 + .../qpid/amqp_1_0/codec/AbstractMapWriter.java | 95 + .../qpid/amqp_1_0/codec/ArrayTypeConstructor.java | 113 + .../apache/qpid/amqp_1_0/codec/ArrayWriter.java | 82 + .../apache/qpid/amqp_1_0/codec/BinaryString.java | 68 + .../qpid/amqp_1_0/codec/BinaryTypeConstructor.java | 80 + .../apache/qpid/amqp_1_0/codec/BinaryWriter.java | 75 + .../qpid/amqp_1_0/codec/BooleanConstructor.java | 80 + .../apache/qpid/amqp_1_0/codec/BooleanWriter.java | 70 + .../qpid/amqp_1_0/codec/ByteArrayWriter.java | 66 + .../qpid/amqp_1_0/codec/ByteBufferWriter.java | 75 + .../qpid/amqp_1_0/codec/ByteTypeConstructor.java | 59 + .../org/apache/qpid/amqp_1_0/codec/ByteWriter.java | 90 + .../qpid/amqp_1_0/codec/CharTypeConstructor.java | 67 + .../org/apache/qpid/amqp_1_0/codec/CharWriter.java | 53 + .../qpid/amqp_1_0/codec/CompoundTypeAssembler.java | 36 + .../amqp_1_0/codec/CompoundTypeConstructor.java | 192 + .../apache/qpid/amqp_1_0/codec/CompoundWriter.java | 420 + .../qpid/amqp_1_0/codec/DecimalConstructor.java | 230 + .../codec/DefaultDescribedTypeConstructor.java | 70 + .../qpid/amqp_1_0/codec/DelegatingValueWriter.java | 52 + .../apache/qpid/amqp_1_0/codec/DescribedType.java | 85 + .../amqp_1_0/codec/DescribedTypeConstructor.java | 41 + .../codec/DescribedTypeConstructorRegistry.java | 35 + .../qpid/amqp_1_0/codec/DoubleTypeConstructor.java | 58 + .../apache/qpid/amqp_1_0/codec/DoubleWriter.java | 54 + .../org/apache/qpid/amqp_1_0/codec/Encoder.java | 85 + .../qpid/amqp_1_0/codec/FixedEightWriter.java | 108 + .../qpid/amqp_1_0/codec/FixedFourWriter.java | 122 + .../apache/qpid/amqp_1_0/codec/FixedOneWriter.java | 79 + .../qpid/amqp_1_0/codec/FixedSixteenWriter.java | 150 + .../apache/qpid/amqp_1_0/codec/FixedTwoWriter.java | 96 + .../qpid/amqp_1_0/codec/FloatTypeConstructor.java | 58 + .../apache/qpid/amqp_1_0/codec/FloatWriter.java | 54 + .../apache/qpid/amqp_1_0/codec/FrameWriter.java | 245 + .../qpid/amqp_1_0/codec/IntTypeConstructor.java | 58 + .../apache/qpid/amqp_1_0/codec/IntegerWriter.java | 106 + .../org/apache/qpid/amqp_1_0/codec/ListWriter.java | 172 + .../qpid/amqp_1_0/codec/LongTypeConstructor.java | 58 + .../org/apache/qpid/amqp_1_0/codec/LongWriter.java | 111 + .../org/apache/qpid/amqp_1_0/codec/MapWriter.java | 102 + .../qpid/amqp_1_0/codec/NullTypeConstructor.java | 44 + .../org/apache/qpid/amqp_1_0/codec/NullWriter.java | 70 + .../qpid/amqp_1_0/codec/ProtocolHandler.java | 30 + .../qpid/amqp_1_0/codec/ProtocolHeaderHandler.java | 146 + .../amqp_1_0/codec/RestrictedTypeValueWriter.java | 55 + .../qpid/amqp_1_0/codec/ShortTypeConstructor.java | 58 + .../apache/qpid/amqp_1_0/codec/ShortWriter.java | 55 + .../amqp_1_0/codec/SimpleVariableWidthWriter.java | 68 + .../qpid/amqp_1_0/codec/SmallIntConstructor.java | 58 + .../qpid/amqp_1_0/codec/SmallLongConstructor.java | 58 + .../qpid/amqp_1_0/codec/SmallUIntConstructor.java | 58 + .../qpid/amqp_1_0/codec/SmallULongConstructor.java | 59 + .../qpid/amqp_1_0/codec/StringTypeConstructor.java | 132 + .../apache/qpid/amqp_1_0/codec/StringWriter.java | 146 + .../qpid/amqp_1_0/codec/SymbolArrayWriter.java | 170 + .../qpid/amqp_1_0/codec/SymbolTypeConstructor.java | 109 + .../apache/qpid/amqp_1_0/codec/SymbolWriter.java | 102 + .../amqp_1_0/codec/TimestampTypeConstructor.java | 60 + .../qpid/amqp_1_0/codec/TimestampWriter.java | 57 + .../qpid/amqp_1_0/codec/TypeConstructor.java | 32 + .../qpid/amqp_1_0/codec/UByteTypeConstructor.java | 59 + .../qpid/amqp_1_0/codec/UIntTypeConstructor.java | 59 + .../qpid/amqp_1_0/codec/ULongTypeConstructor.java | 61 + .../qpid/amqp_1_0/codec/UShortTypeConstructor.java | 60 + .../qpid/amqp_1_0/codec/UUIDTypeConstructor.java | 62 + .../org/apache/qpid/amqp_1_0/codec/UUIDWriter.java | 63 + .../qpid/amqp_1_0/codec/UnsignedByteWriter.java | 92 + .../qpid/amqp_1_0/codec/UnsignedIntegerWriter.java | 148 + .../qpid/amqp_1_0/codec/UnsignedLongWriter.java | 152 + .../qpid/amqp_1_0/codec/UnsignedShortWriter.java | 56 + .../apache/qpid/amqp_1_0/codec/ValueHandler.java | 159 + .../codec/ValueProducingProtocolHandler.java | 31 + .../apache/qpid/amqp_1_0/codec/ValueWriter.java | 58 + .../codec/VariableWidthTypeConstructor.java | 48 + .../qpid/amqp_1_0/codec/VariableWidthWriter.java | 169 + .../amqp_1_0/codec/WrapperTypeValueWriter.java | 55 + .../qpid/amqp_1_0/codec/ZeroListConstructor.java | 46 + .../qpid/amqp_1_0/codec/ZeroUIntConstructor.java | 45 + .../qpid/amqp_1_0/codec/ZeroULongConstructor.java | 45 + .../org/apache/qpid/amqp_1_0/framing/AMQFrame.java | 68 + .../framing/AMQPProtocolHeaderHandler.java | 85 + .../qpid/amqp_1_0/framing/ConnectionHandler.java | 559 + .../apache/qpid/amqp_1_0/framing/FrameHandler.java | 329 + .../qpid/amqp_1_0/framing/FrameParsingError.java | 34 + .../qpid/amqp_1_0/framing/FrameTypeHandler.java | 31 + .../amqp_1_0/framing/OversizeFrameException.java | 42 + .../apache/qpid/amqp_1_0/framing/SASLFrame.java | 42 + .../qpid/amqp_1_0/framing/SASLFrameHandler.java | 311 + .../framing/SASLProtocolHeaderHandler.java | 86 + .../qpid/amqp_1_0/framing/TransportFrame.java | 51 + .../qpid/amqp_1_0/messaging/MessageAttributes.java | 27 + .../qpid/amqp_1_0/messaging/SectionDecoder.java | 35 + .../amqp_1_0/messaging/SectionDecoderImpl.java | 62 + .../qpid/amqp_1_0/messaging/SectionEncoder.java | 34 + .../amqp_1_0/messaging/SectionEncoderImpl.java | 111 + .../amqp_1_0/transport/AMQPFrameTransport.java | 179 + .../qpid/amqp_1_0/transport/AMQPTransport.java | 170 + .../qpid/amqp_1_0/transport/BytesProcessor.java | 27 + .../qpid/amqp_1_0/transport/BytesTransport.java | 38 + .../amqp_1_0/transport/CallbackHandlerSource.java | 28 + .../amqp_1_0/transport/CircularBytesBuffer.java | 174 + .../amqp_1_0/transport/ConnectionEndpoint.java | 934 ++ .../transport/ConnectionEventListener.java | 43 + .../qpid/amqp_1_0/transport/ConnectionState.java | 31 + .../apache/qpid/amqp_1_0/transport/Container.java | 79 + .../apache/qpid/amqp_1_0/transport/Delivery.java | 95 + .../amqp_1_0/transport/DeliveryStateHandler.java | 28 + .../qpid/amqp_1_0/transport/ErrorHandler.java | 9 + .../amqp_1_0/transport/FrameOutputHandler.java | 36 + .../qpid/amqp_1_0/transport/FrameTransport.java | 37 + .../qpid/amqp_1_0/transport/LinkEndpoint.java | 542 + .../qpid/amqp_1_0/transport/LinkEventListener.java | 31 + .../org/apache/qpid/amqp_1_0/transport/Node.java | 26 + .../transport/ProtocolHeaderTransport.java | 134 + .../amqp_1_0/transport/ReceivingLinkEndpoint.java | 438 + .../amqp_1_0/transport/ReceivingLinkListener.java | 43 + .../transport/ReceivingSessionHalfEndpoint.java | 26 + .../qpid/amqp_1_0/transport/SASLEndpoint.java | 39 + .../qpid/amqp_1_0/transport/SASLEndpointImpl.java | 291 + .../amqp_1_0/transport/SASLFrameTransport.java | 78 + .../qpid/amqp_1_0/transport/SASLTransport.java | 85 + .../amqp_1_0/transport/SendingLinkEndpoint.java | 214 + .../amqp_1_0/transport/SendingLinkListener.java | 43 + .../transport/SendingSessionHalfEndpoint.java | 26 + .../qpid/amqp_1_0/transport/SequenceNumber.java | 110 + .../qpid/amqp_1_0/transport/SessionAttachment.java | 92 + .../qpid/amqp_1_0/transport/SessionEndpoint.java | 781 + .../amqp_1_0/transport/SessionEventListener.java | 47 + .../amqp_1_0/transport/SessionHalfEndpoint.java | 26 + .../qpid/amqp_1_0/transport/SessionState.java | 34 + .../amqp_1_0/transport/StateChangeListener.java | 25 + .../qpid/amqp_1_0/transport/UnsettledTransfer.java | 53 + .../qpid/amqp_1_0/type/AmqpErrorException.java | 54 + .../java/org/apache/qpid/amqp_1_0/type/Binary.java | 161 + .../apache/qpid/amqp_1_0/type/DeliveryState.java | 26 + .../qpid/amqp_1_0/type/DistributionMode.java | 26 + .../apache/qpid/amqp_1_0/type/ErrorCondition.java | 26 + .../org/apache/qpid/amqp_1_0/type/FrameBody.java | 29 + .../org/apache/qpid/amqp_1_0/type/GlobalTxId.java | 26 + .../apache/qpid/amqp_1_0/type/LifetimePolicy.java | 26 + .../org/apache/qpid/amqp_1_0/type/Outcome.java | 26 + .../apache/qpid/amqp_1_0/type/RestrictedType.java | 26 + .../apache/qpid/amqp_1_0/type/SaslFrameBody.java | 27 + .../org/apache/qpid/amqp_1_0/type/Section.java | 27 + .../java/org/apache/qpid/amqp_1_0/type/Source.java | 26 + .../java/org/apache/qpid/amqp_1_0/type/Symbol.java | 90 + .../java/org/apache/qpid/amqp_1_0/type/Target.java | 26 + .../apache/qpid/amqp_1_0/type/TxnCapability.java | 26 + .../java/org/apache/qpid/amqp_1_0/type/TxnId.java | 23 + .../apache/qpid/amqp_1_0/type/UnsignedByte.java | 134 + .../apache/qpid/amqp_1_0/type/UnsignedInteger.java | 149 + .../apache/qpid/amqp_1_0/type/UnsignedLong.java | 162 + .../apache/qpid/amqp_1_0/type/UnsignedShort.java | 132 + .../org/apache/qpid/amqp_1_0/type/WrapperType.java | 27 + .../type/codec/AMQPDescribedTypeRegistry.java | 389 + .../qpid/amqp_1_0/type/messaging/Accepted.java | 46 + .../qpid/amqp_1_0/type/messaging/AmqpSequence.java | 70 + .../qpid/amqp_1_0/type/messaging/AmqpValue.java | 66 + .../type/messaging/ApplicationProperties.java | 64 + .../apache/qpid/amqp_1_0/type/messaging/Data.java | 68 + .../amqp_1_0/type/messaging/DeleteOnClose.java | 46 + .../amqp_1_0/type/messaging/DeleteOnNoLinks.java | 46 + .../type/messaging/DeleteOnNoLinksOrMessages.java | 46 + .../type/messaging/DeleteOnNoMessages.java | 46 + .../type/messaging/DeliveryAnnotations.java | 64 + .../type/messaging/ExactSubjectFilter.java | 82 + .../qpid/amqp_1_0/type/messaging/Filter.java | 28 + .../qpid/amqp_1_0/type/messaging/Footer.java | 70 + .../qpid/amqp_1_0/type/messaging/Header.java | 161 + .../amqp_1_0/type/messaging/JMSSelectorFilter.java | 77 + .../type/messaging/MatchingSubjectFilter.java | 81 + .../type/messaging/MessageAnnotations.java | 64 + .../qpid/amqp_1_0/type/messaging/Modified.java | 112 + .../amqp_1_0/type/messaging/NoLocalFilter.java | 45 + .../qpid/amqp_1_0/type/messaging/Properties.java | 333 + .../qpid/amqp_1_0/type/messaging/Received.java | 88 + .../qpid/amqp_1_0/type/messaging/Rejected.java | 70 + .../qpid/amqp_1_0/type/messaging/Released.java | 46 + .../qpid/amqp_1_0/type/messaging/Source.java | 280 + .../qpid/amqp_1_0/type/messaging/StdDistMode.java | 95 + .../qpid/amqp_1_0/type/messaging/Target.java | 196 + .../type/messaging/TerminusDurability.java | 107 + .../type/messaging/TerminusExpiryPolicy.java | 119 + .../type/messaging/codec/AcceptedConstructor.java | 72 + .../type/messaging/codec/AcceptedWriter.java | 151 + .../messaging/codec/AmqpSequenceConstructor.java | 68 + .../type/messaging/codec/AmqpSequenceWriter.java | 80 + .../type/messaging/codec/AmqpValueConstructor.java | 65 + .../type/messaging/codec/AmqpValueWriter.java | 80 + .../codec/ApplicationPropertiesConstructor.java | 68 + .../codec/ApplicationPropertiesWriter.java | 80 + .../type/messaging/codec/DataConstructor.java | 65 + .../amqp_1_0/type/messaging/codec/DataWriter.java | 80 + .../messaging/codec/DeleteOnCloseConstructor.java | 72 + .../type/messaging/codec/DeleteOnCloseWriter.java | 142 + .../codec/DeleteOnNoLinksConstructor.java | 72 + .../DeleteOnNoLinksOrMessagesConstructor.java | 72 + .../codec/DeleteOnNoLinksOrMessagesWriter.java | 142 + .../messaging/codec/DeleteOnNoLinksWriter.java | 142 + .../codec/DeleteOnNoMessagesConstructor.java | 72 + .../messaging/codec/DeleteOnNoMessagesWriter.java | 142 + .../codec/DeliveryAnnotationsConstructor.java | 68 + .../messaging/codec/DeliveryAnnotationsWriter.java | 80 + .../codec/ExactSubjectFilterConstructor.java | 64 + .../messaging/codec/ExactSubjectFilterWriter.java | 78 + .../type/messaging/codec/FooterConstructor.java | 68 + .../type/messaging/codec/FooterWriter.java | 80 + .../type/messaging/codec/HeaderConstructor.java | 207 + .../type/messaging/codec/HeaderWriter.java | 182 + .../codec/JMSSelectorFilterConstructor.java | 66 + .../messaging/codec/JMSSelectorFilterWriter.java | 79 + .../codec/MatchingSubjectFilterConstructor.java | 65 + .../codec/MatchingSubjectFilterWriter.java | 79 + .../codec/MessageAnnotationsConstructor.java | 68 + .../messaging/codec/MessageAnnotationsWriter.java | 80 + .../type/messaging/codec/ModifiedConstructor.java | 154 + .../type/messaging/codec/ModifiedWriter.java | 166 + .../messaging/codec/NoLocalFilterConstructor.java | 56 + .../type/messaging/codec/NoLocalFilterWriter.java | 89 + .../messaging/codec/PropertiesConstructor.java | 424 + .../type/messaging/codec/PropertiesWriter.java | 246 + .../type/messaging/codec/ReceivedConstructor.java | 126 + .../type/messaging/codec/ReceivedWriter.java | 158 + .../type/messaging/codec/RejectedConstructor.java | 99 + .../type/messaging/codec/RejectedWriter.java | 150 + .../type/messaging/codec/ReleasedConstructor.java | 72 + .../type/messaging/codec/ReleasedWriter.java | 142 + .../type/messaging/codec/SourceConstructor.java | 384 + .../type/messaging/codec/SourceWriter.java | 230 + .../type/messaging/codec/TargetConstructor.java | 269 + .../type/messaging/codec/TargetWriter.java | 198 + .../qpid/amqp_1_0/type/security/SaslChallenge.java | 74 + .../qpid/amqp_1_0/type/security/SaslCode.java | 131 + .../qpid/amqp_1_0/type/security/SaslInit.java | 116 + .../amqp_1_0/type/security/SaslMechanisms.java | 74 + .../qpid/amqp_1_0/type/security/SaslOutcome.java | 95 + .../qpid/amqp_1_0/type/security/SaslResponse.java | 74 + .../security/codec/SaslChallengeConstructor.java | 99 + .../type/security/codec/SaslChallengeWriter.java | 150 + .../type/security/codec/SaslInitConstructor.java | 153 + .../type/security/codec/SaslInitWriter.java | 166 + .../security/codec/SaslMechanismsConstructor.java | 106 + .../type/security/codec/SaslMechanismsWriter.java | 150 + .../security/codec/SaslOutcomeConstructor.java | 126 + .../type/security/codec/SaslOutcomeWriter.java | 158 + .../security/codec/SaslResponseConstructor.java | 99 + .../type/security/codec/SaslResponseWriter.java | 150 + .../amqp_1_0/type/transaction/Coordinator.java | 70 + .../qpid/amqp_1_0/type/transaction/Declare.java | 66 + .../qpid/amqp_1_0/type/transaction/Declared.java | 67 + .../qpid/amqp_1_0/type/transaction/Discharge.java | 87 + .../type/transaction/TransactionErrors.java | 107 + .../type/transaction/TransactionalState.java | 88 + .../amqp_1_0/type/transaction/TxnCapabilities.java | 144 + .../amqp_1_0/type/transaction/TxnCapability.java | 131 + .../transaction/codec/CoordinatorConstructor.java | 117 + .../type/transaction/codec/CoordinatorWriter.java | 150 + .../type/transaction/codec/DeclareConstructor.java | 99 + .../type/transaction/codec/DeclareWriter.java | 150 + .../transaction/codec/DeclaredConstructor.java | 99 + .../type/transaction/codec/DeclaredWriter.java | 150 + .../transaction/codec/DischargeConstructor.java | 126 + .../type/transaction/codec/DischargeWriter.java | 158 + .../codec/TransactionalStateConstructor.java | 126 + .../codec/TransactionalStateWriter.java | 158 + .../qpid/amqp_1_0/type/transport/AmqpError.java | 227 + .../qpid/amqp_1_0/type/transport/Attach.java | 365 + .../apache/qpid/amqp_1_0/type/transport/Begin.java | 239 + .../apache/qpid/amqp_1_0/type/transport/Close.java | 89 + .../amqp_1_0/type/transport/ConnectionError.java | 107 + .../qpid/amqp_1_0/type/transport/Detach.java | 131 + .../qpid/amqp_1_0/type/transport/Disposition.java | 194 + .../apache/qpid/amqp_1_0/type/transport/End.java | 89 + .../apache/qpid/amqp_1_0/type/transport/Error.java | 111 + .../apache/qpid/amqp_1_0/type/transport/Flow.java | 302 + .../qpid/amqp_1_0/type/transport/LinkError.java | 131 + .../apache/qpid/amqp_1_0/type/transport/Open.java | 281 + .../type/transport/ReceiverSettleMode.java | 95 + .../apache/qpid/amqp_1_0/type/transport/Role.java | 95 + .../amqp_1_0/type/transport/SenderSettleMode.java | 107 + .../qpid/amqp_1_0/type/transport/SessionError.java | 119 + .../qpid/amqp_1_0/type/transport/Transfer.java | 299 + .../type/transport/codec/AttachConstructor.java | 465 + .../type/transport/codec/AttachWriter.java | 254 + .../type/transport/codec/BeginConstructor.java | 303 + .../amqp_1_0/type/transport/codec/BeginWriter.java | 206 + .../type/transport/codec/CloseConstructor.java | 99 + .../amqp_1_0/type/transport/codec/CloseWriter.java | 150 + .../type/transport/codec/DetachConstructor.java | 153 + .../type/transport/codec/DetachWriter.java | 166 + .../transport/codec/DispositionConstructor.java | 234 + .../type/transport/codec/DispositionWriter.java | 190 + .../type/transport/codec/EndConstructor.java | 99 + .../amqp_1_0/type/transport/codec/EndWriter.java | 150 + .../type/transport/codec/ErrorConstructor.java | 169 + .../amqp_1_0/type/transport/codec/ErrorWriter.java | 166 + .../type/transport/codec/FlowConstructor.java | 370 + .../amqp_1_0/type/transport/codec/FlowWriter.java | 230 + .../type/transport/codec/OpenConstructor.java | 371 + .../amqp_1_0/type/transport/codec/OpenWriter.java | 222 + .../type/transport/codec/TransferConstructor.java | 369 + .../type/transport/codec/TransferWriter.java | 230 + java/bdbstore/bin/backup.sh | 2 +- java/bdbstore/bin/storeUpgrade.sh | 41 - java/bdbstore/build.xml | 9 +- java/bdbstore/etc/scripts/bdbtest.sh | 43 - .../src/main/java/BDBStoreUpgrade.log4j.xml | 52 - .../store/berkeleydb/AMQShortStringEncoding.java | 2 +- .../server/store/berkeleydb/AMQShortStringTB.java | 49 - .../store/berkeleydb/AbstractBDBMessageStore.java | 1825 +++ .../server/store/berkeleydb/BDBMessageStore.java | 2234 +-- .../store/berkeleydb/BDBMessageStoreFactory.java | 40 + .../server/store/berkeleydb/BDBStoreUpgrade.java | 1299 -- .../qpid/server/store/berkeleydb/ContentTB.java | 52 - .../server/store/berkeleydb/DatabaseVisitor.java | 49 - .../qpid/server/store/berkeleydb/ExchangeTB.java | 59 - .../server/store/berkeleydb/MessageContentKey.java | 42 - .../server/store/berkeleydb/QueueEntryKey.java | 49 - .../server/store/berkeleydb/StringMapBinding.java | 61 - .../server/store/berkeleydb/UUIDTupleBinding.java | 50 - .../berkeleydb/entry/PreparedTransaction.java | 46 + .../store/berkeleydb/entry/QueueEntryKey.java | 45 + .../qpid/server/store/berkeleydb/entry/Xid.java | 52 + .../store/berkeleydb/keys/MessageContentKey_4.java | 44 - .../store/berkeleydb/keys/MessageContentKey_5.java | 44 - .../store/berkeleydb/records/BindingRecord.java | 62 - .../store/berkeleydb/records/ExchangeRecord.java | 53 - .../store/berkeleydb/records/QueueRecord.java | 66 - .../berkeleydb/tuple/ConfiguredObjectBinding.java | 37 + .../store/berkeleydb/tuple/ContentBinding.java | 52 + .../berkeleydb/tuple/MessageMetaDataBinding.java | 77 + .../tuple/PreparedTransactionBinding.java | 127 + .../store/berkeleydb/tuple/QueueEntryBinding.java | 59 + .../store/berkeleydb/tuple/StringMapBinding.java | 59 + .../store/berkeleydb/tuple/UUIDTupleBinding.java | 48 + .../server/store/berkeleydb/tuple/XidBinding.java | 70 + .../store/berkeleydb/tuples/BindingTuple.java | 25 - .../tuples/BindingTupleBindingFactory.java | 45 - .../store/berkeleydb/tuples/BindingTuple_4.java | 76 - .../berkeleydb/tuples/MessageContentKeyTB_4.java | 47 - .../berkeleydb/tuples/MessageContentKeyTB_5.java | 46 - .../MessageContentKeyTupleBindingFactory.java | 45 - .../berkeleydb/tuples/MessageMetaDataTB_4.java | 170 - .../berkeleydb/tuples/MessageMetaDataTB_5.java | 67 - .../tuples/MessageMetaDataTupleBindingFactory.java | 43 - .../store/berkeleydb/tuples/QueueEntryTB.java | 46 - .../server/store/berkeleydb/tuples/QueueTuple.java | 25 - .../tuples/QueueTupleBindingFactory.java | 46 - .../store/berkeleydb/tuples/QueueTuple_4.java | 70 - .../store/berkeleydb/tuples/QueueTuple_5.java | 73 - .../berkeleydb/tuples/TupleBindingFactory.java | 40 - .../berkeleydb/upgrade/AbstractStoreUpgrade.java | 77 + .../store/berkeleydb/upgrade/CursorOperation.java | 89 + .../store/berkeleydb/upgrade/CursorTemplate.java | 75 + .../store/berkeleydb/upgrade/DatabaseCallable.java | 29 + .../berkeleydb/upgrade/DatabaseEntryCallback.java | 30 + .../store/berkeleydb/upgrade/DatabaseRunnable.java | 30 + .../store/berkeleydb/upgrade/DatabaseTemplate.java | 114 + .../store/berkeleydb/upgrade/StoreUpgrade.java | 31 + .../store/berkeleydb/upgrade/UpgradeFrom4To5.java | 915 ++ .../store/berkeleydb/upgrade/UpgradeFrom5To6.java | 1207 ++ .../upgrade/UpgradeInteractionHandler.java | 37 + .../upgrade/UpgradeInteractionResponse.java | 28 + .../server/store/berkeleydb/upgrade/Upgrader.java | 177 + .../BDBMessageStoreConfigurationTest.java | 14 + .../store/berkeleydb/BDBMessageStoreTest.java | 211 +- .../berkeleydb/BDBStoreUpgradeTestPreparer.java | 63 +- .../server/store/berkeleydb/BDBUpgradeTest.java | 324 +- .../tuple/ConfiguredObjectBindingTest.java | 61 + .../upgrade/AbstractUpgradeTestCase.java | 153 + .../berkeleydb/upgrade/DatabaseTemplateTest.java | 83 + .../berkeleydb/upgrade/UpgradeFrom4to5Test.java | 299 + .../berkeleydb/upgrade/UpgradeFrom5To6Test.java | 395 + .../store/berkeleydb/upgrade/UpgraderTest.java | 138 + .../bdbstore-to-upgrade/test-store/00000000.jdb | Bin 1346092 -> 0 bytes .../upgrade/bdbstore-v4/test-store/00000000.jdb | Bin 0 -> 1357197 bytes .../test/resources/upgrade/bdbstore-v5/readme.txt | 5 + .../upgrade/bdbstore-v5/test-store/00000000.jdb | Bin 0 -> 1357227 bytes .../upgrade/bdbstore-v5/test-store/00000001.jdb | Bin 0 -> 1332881 bytes .../security/access/config/PlainConfiguration.java | 1 - .../security/access/plugins/AccessControlTest.java | 9 +- .../access/plugins/PlainConfigurationTest.java | 6 +- java/broker-plugins/experimental/info/MANIFEST.MF | 16 - .../experimental/info/build.properties | 31 - java/broker-plugins/experimental/info/build.xml | 39 - .../main/java/org/apache/qpid/info/Activator.java | 212 - .../main/java/org/apache/qpid/info/AppInfo.java | 96 - .../src/main/java/org/apache/qpid/info/Info.java | 143 - .../java/org/apache/qpid/info/InfoService.java | 30 - .../java/org/apache/qpid/info/InfoServiceImpl.java | 66 - .../main/java/org/apache/qpid/info/SystemInfo.java | 95 - .../java/org/apache/qpid/info/util/HttpPoster.java | 130 - .../org/apache/qpid/info/util/IniFileReader.java | 193 - .../java/org/apache/qpid/info/util/SoapClient.java | 155 - .../java/org/apache/qpid/info/util/XMLWriter.java | 102 - .../apache/qpid/info/systest/InfoPluginTest.java | 277 - .../org/apache/qpid/info/test/HttpPosterTest.java | 107 - .../apache/qpid/info/test/InfoServiceImplTest.java | 63 - .../org/apache/qpid/info/test/InfoServlet.java | 57 - .../java/org/apache/qpid/info/test/InfoTest.java | 114 - .../apache/qpid/info/test/IniFileReaderTest.java | 137 - .../org/apache/qpid/info/test/SoapClientTest.java | 209 - .../org/apache/qpid/info/test/SystemInfoTest.java | 57 - .../org/apache/qpid/info/test/XMLWriterTest.java | 133 - .../shutdown/src/main/java/shutdown.bnd | 2 +- .../exchanges/diagnostic/DiagnosticExchange.java | 10 +- .../diagnostic/DiagnosticExchangeType.java | 6 +- .../extras/exchanges/example/TestExchange.java | 7 +- .../extras/exchanges/example/TestExchangeType.java | 6 +- java/broker/bin/create-example-ssl-stores.bat | 36 - java/broker/bin/create-example-ssl-stores.sh | 38 - java/broker/build.xml | 2 +- java/broker/etc/config.xml | 3 +- java/broker/etc/virtualhosts.xml | 12 +- java/broker/src/main/java/broker.bnd | 2 +- .../org/apache/qpid/qmf/ManagementExchange.java | 22 +- .../main/java/org/apache/qpid/qmf/QMFService.java | 5 + .../apache/qpid/server/AMQBrokerManagerMBean.java | 74 +- .../java/org/apache/qpid/server/AMQChannel.java | 92 +- .../main/java/org/apache/qpid/server/Broker.java | 147 +- .../java/org/apache/qpid/server/BrokerOptions.java | 3 - .../src/main/java/org/apache/qpid/server/Main.java | 7 + .../org/apache/qpid/server/ProtocolExclusion.java | 3 +- .../org/apache/qpid/server/binding/Binding.java | 2 +- .../apache/qpid/server/binding/BindingFactory.java | 94 +- .../server/configuration/ServerConfiguration.java | 13 +- .../ServerNetworkTransportConfiguration.java | 18 +- .../server/configuration/VirtualHostConfig.java | 2 - .../configuration/VirtualHostConfiguration.java | 30 +- .../qpid/server/connection/ConnectionRegistry.java | 12 +- .../server/connection/IConnectionRegistry.java | 9 +- .../qpid/server/exchange/AbstractExchange.java | 27 +- .../server/exchange/DefaultExchangeFactory.java | 27 +- .../server/exchange/DefaultExchangeRegistry.java | 53 +- .../qpid/server/exchange/DirectExchange.java | 11 +- .../org/apache/qpid/server/exchange/Exchange.java | 6 +- .../qpid/server/exchange/ExchangeFactory.java | 7 + .../qpid/server/exchange/ExchangeInitialiser.java | 5 +- .../qpid/server/exchange/ExchangeRegistry.java | 7 +- .../apache/qpid/server/exchange/ExchangeType.java | 4 +- .../qpid/server/exchange/FanoutExchange.java | 10 +- .../qpid/server/exchange/HeadersBinding.java | 42 +- .../qpid/server/exchange/HeadersExchange.java | 42 +- .../apache/qpid/server/exchange/TopicExchange.java | 216 +- .../org/apache/qpid/server/federation/Bridge.java | 10 +- .../apache/qpid/server/federation/BrokerLink.java | 4 +- .../qpid/server/filter/SimpleFilterManager.java | 6 + .../handler/ConnectionOpenMethodHandler.java | 9 +- .../server/handler/ExchangeDeclareHandler.java | 29 +- .../qpid/server/handler/QueueBindHandler.java | 2 +- .../qpid/server/handler/QueueDeclareHandler.java | 12 +- .../qpid/server/handler/QueueDeleteHandler.java | 2 +- .../qpid/server/logging/actors/CurrentActor.java | 16 +- .../messages/ConfigStore_logmessages.properties | 3 +- .../messages/MessageStore_logmessages.properties | 6 +- .../messages/TransactionLog_logmessages.properties | 9 +- .../server/logging/subjects/BindingLogSubject.java | 3 +- .../logging/subjects/MessageStoreLogSubject.java | 8 +- .../AbstractAMQManagedConnectionObject.java | 20 + .../management/JMXManagedObjectRegistry.java | 4 +- .../qpid/server/message/MessageMetaData_0_10.java | 11 + .../qpid/server/message/MessageMetaData_1_0.java | 522 + .../java/org/apache/qpid/server/model/Binding.java | 75 + .../server/model/ConfigurationChangeListener.java | 38 + .../apache/qpid/server/model/ConfiguredObject.java | 229 + .../org/apache/qpid/server/model/Consumer.java | 73 + .../org/apache/qpid/server/model/Exchange.java | 91 + .../model/IllegalStateTransitionException.java | 43 + .../apache/qpid/server/model/LifetimePolicy.java | 27 + .../org/apache/qpid/server/model/Publisher.java | 25 + .../java/org/apache/qpid/server/model/Queue.java | 146 + .../java/org/apache/qpid/server/model/State.java | 30 + .../org/apache/qpid/server/model/Statistics.java | 25 + .../apache/qpid/server/model/UUIDGenerator.java | 54 + .../qpid/server/protocol/AMQProtocolEngine.java | 8 +- .../qpid/server/protocol/AMQSessionModel.java | 8 +- .../qpid/server/protocol/AmqpProtocolVersion.java | 2 +- .../protocol/MultiVersionProtocolEngine.java | 64 +- .../qpid/server/protocol/ProtocolEngine_1_0_0.java | 394 + .../server/protocol/ProtocolEngine_1_0_0_SASL.java | 449 + .../qpid/server/protocol/v1_0/Connection_1_0.java | 98 + .../qpid/server/protocol/v1_0/Destination.java | 28 + .../server/protocol/v1_0/ExchangeDestination.java | 108 + .../qpid/server/protocol/v1_0/LinkRegistry.java | 59 + .../apache/qpid/server/protocol/v1_0/Link_1_0.java | 26 + .../qpid/server/protocol/v1_0/Message_1_0.java | 172 + .../server/protocol/v1_0/QueueDestination.java | 100 + .../server/protocol/v1_0/ReceivingDestination.java | 35 + .../protocol/v1_0/ReceivingLinkAttachment.java | 51 + .../server/protocol/v1_0/ReceivingLink_1_0.java | 305 + .../server/protocol/v1_0/SendingDestination.java | 27 + .../protocol/v1_0/SendingLinkAttachment.java | 44 + .../qpid/server/protocol/v1_0/SendingLink_1_0.java | 648 + .../qpid/server/protocol/v1_0/Session_1_0.java | 446 + .../server/protocol/v1_0/Subscription_1_0.java | 634 + .../protocol/v1_0/TxnCoordinatorLink_1_0.java | 195 + .../qpid/server/protocol/v1_0/UnsettledAction.java | 8 + .../apache/qpid/server/queue/AMQPriorityQueue.java | 9 +- .../org/apache/qpid/server/queue/AMQQueue.java | 6 +- .../apache/qpid/server/queue/AMQQueueFactory.java | 58 +- .../apache/qpid/server/queue/AMQQueueMBean.java | 12 +- .../apache/qpid/server/queue/ConflationQueue.java | 13 +- .../qpid/server/queue/DefaultQueueRegistry.java | 38 + .../apache/qpid/server/queue/IncomingMessage.java | 41 +- .../apache/qpid/server/queue/OutOfOrderQueue.java | 29 +- .../qpid/server/queue/PriorityQueueList.java | 50 +- .../org/apache/qpid/server/queue/QueueContext.java | 9 + .../apache/qpid/server/queue/QueueEntryImpl.java | 17 +- .../qpid/server/queue/QueueEntryVisitor.java | 22 + .../apache/qpid/server/queue/QueueRegistry.java | 5 + .../apache/qpid/server/queue/SimpleAMQQueue.java | 223 +- .../qpid/server/queue/SimpleQueueEntryList.java | 25 +- .../org/apache/qpid/server/queue/SortedQueue.java | 11 +- .../qpid/server/registry/ApplicationRegistry.java | 60 +- .../qpid/server/registry/BrokerConfigAdapter.java | 1 - .../ConfigurationFileApplicationRegistry.java | 18 - .../auth/manager/AuthenticationManager.java | 3 + .../PrincipalDatabaseAuthenticationManager.java | 5 + .../sasl/anonymous/AnonymousSaslServerFactory.java | 2 +- .../security/auth/sasl/plain/PlainSaslServer.java | 63 +- .../qpid/server/store/AbstractMessageStore.java | 43 - .../server/store/ConfigurationRecoveryHandler.java | 15 +- .../qpid/server/store/ConfiguredObjectHelper.java | 183 + .../qpid/server/store/ConfiguredObjectRecord.java | 65 + .../qpid/server/store/DerbyMessageStore.java | 2363 --- .../server/store/DurableConfigurationStore.java | 29 +- .../java/org/apache/qpid/server/store/Event.java | 32 + .../apache/qpid/server/store/EventListener.java | 25 + .../org/apache/qpid/server/store/EventManager.java | 55 + .../qpid/server/store/MemoryMessageStore.java | 185 +- .../server/store/MemoryMessageStoreFactory.java | 37 + .../qpid/server/store/MessageMetaDataType.java | 5 +- .../org/apache/qpid/server/store/MessageStore.java | 110 +- .../qpid/server/store/MessageStoreConstants.java | 27 + .../qpid/server/store/MessageStoreFactory.java | 27 + .../apache/qpid/server/store/NullMessageStore.java | 146 + .../server/store/OperationalLoggingListener.java | 73 + .../java/org/apache/qpid/server/store/State.java | 38 + .../org/apache/qpid/server/store/StateManager.java | 151 + .../org/apache/qpid/server/store/StoreFuture.java | 40 + .../qpid/server/store/StoredMemoryMessage.java | 4 +- .../apache/qpid/server/store/StoredMessage.java | 2 +- .../org/apache/qpid/server/store/Transaction.java | 81 + .../store/TransactionLogRecoveryHandler.java | 13 +- .../qpid/server/store/TransactionLogResource.java | 4 +- .../qpid/server/store/derby/DerbyMessageStore.java | 2449 +++ .../store/derby/DerbyMessageStoreFactory.java | 40 + .../qpid/server/subscription/Subscription.java | 8 +- .../qpid/server/subscription/SubscriptionImpl.java | 14 +- .../server/subscription/Subscription_0_10.java | 35 +- .../server/transport/ServerConnectionDelegate.java | 24 +- .../qpid/server/transport/ServerSession.java | 194 +- .../server/transport/ServerSessionDelegate.java | 446 +- .../qpid/server/txn/AlreadyKnownDtxException.java | 32 + .../server/txn/AsyncAutoCommitTransaction.java | 35 +- .../qpid/server/txn/AutoCommitTransaction.java | 11 +- .../qpid/server/txn/DistributedTransaction.java | 247 + .../java/org/apache/qpid/server/txn/DtxBranch.java | 349 + .../org/apache/qpid/server/txn/DtxException.java | 44 + .../qpid/server/txn/DtxNotSelectedException.java | 30 + .../org/apache/qpid/server/txn/DtxRegistry.java | 333 + .../server/txn/IncorrectDtxStateException.java | 32 + .../qpid/server/txn/JoinAndResumeDtxException.java | 32 + .../apache/qpid/server/txn/LocalTransaction.java | 3 +- .../qpid/server/txn/NotAssociatedDtxException.java | 32 + .../qpid/server/txn/RollbackOnlyDtxException.java | 32 + .../apache/qpid/server/txn/ServerTransaction.java | 5 +- .../server/txn/SuspendAndFailDtxException.java | 32 + .../qpid/server/txn/TimeoutDtxException.java | 32 + .../qpid/server/txn/UnknownDtxBranchException.java | 32 + .../apache/qpid/server/util/MapJsonSerializer.java | 69 + .../org/apache/qpid/server/virtualhost/State.java | 29 + .../qpid/server/virtualhost/VirtualHost.java | 21 +- .../VirtualHostConfigRecoveryHandler.java | 259 +- .../qpid/server/virtualhost/VirtualHostImpl.java | 650 +- .../qpid/server/AMQBrokerManagerMBeanTest.java | 3 +- .../org/apache/qpid/server/AMQChannelTest.java | 52 + .../server/configuration/MockConnectionConfig.java | 20 + .../VirtualHostConfigurationTest.java | 3 +- .../exchange/AbstractHeadersExchangeTestBase.java | 57 +- .../qpid/server/exchange/ExchangeMBeanTest.java | 13 +- .../qpid/server/exchange/TopicExchangeTest.java | 2 +- .../logging/messages/MessageStoreMessagesTest.java | 58 +- .../subjects/MessageStoreLogSubjectTest.java | 4 +- .../server/plugins/OsgiSystemPackageUtilTest.java | 4 +- .../protocol/AMQProtocolSessionMBeanTest.java | 4 +- .../protocol/InternalTestProtocolSession.java | 5 +- .../MultiVersionProtocolEngineFactoryTest.java | 18 +- .../qpid/server/queue/AMQQueueAlertTest.java | 39 +- .../qpid/server/queue/AMQQueueFactoryTest.java | 5 +- .../qpid/server/queue/AMQQueueMBeanTest.java | 19 +- .../java/org/apache/qpid/server/queue/AckTest.java | 13 +- .../org/apache/qpid/server/queue/MockAMQQueue.java | 5 +- .../qpid/server/queue/MockStoredMessage.java | 6 +- .../qpid/server/queue/PriorityQueueListTest.java | 117 + .../qpid/server/queue/QueueEntryListTestBase.java | 33 + .../qpid/server/queue/SimpleAMQQueueTest.java | 59 +- .../server/queue/SimpleQueueEntryImplTest.java | 20 + .../server/queue/SimpleQueueEntryListTest.java | 19 +- .../server/queue/SortedQueueEntryListTest.java | 16 +- .../registry/ApplicationRegistryShutdownTest.java | 5 +- .../auth/rmi/RMIPasswordAuthenticatorTest.java | 30 +- .../security/auth/sasl/SaslServerTestCase.java | 2 +- .../store/DurableConfigurationStoreTest.java | 377 + .../apache/qpid/server/store/EventManagerTest.java | 72 + .../apache/qpid/server/store/MessageStoreTest.java | 16 +- .../store/OperationalLoggingListenerTest.java | 181 + .../qpid/server/store/ReferenceCountingTest.java | 4 +- .../qpid/server/store/SkeletonMessageStore.java | 157 - .../apache/qpid/server/store/StateManagerTest.java | 195 + .../qpid/server/store/TestMemoryMessageStore.java | 98 - .../server/store/TestableMemoryMessageStore.java | 57 +- .../store/TestableMemoryMessageStoreFactory.java | 37 + .../qpid/server/subscription/MockSubscription.java | 4 + .../qpid/server/transport/ServerSessionTest.java | 67 + .../qpid/server/txn/MockStoreTransaction.java | 54 +- .../qpid/server/util/InternalBrokerBaseCase.java | 7 +- .../qpid/server/util/MapJsonSerializerTest.java | 53 + .../qpid/server/virtualhost/MockVirtualHost.java | 26 +- .../server/virtualhost/VirtualHostImplTest.java | 84 +- java/build.deps | 43 +- java/build.xml | 20 +- java/client/src/main/java/client.bnd | 2 +- .../org/apache/qpid/client/AMQBrokerDetails.java | 8 +- .../java/org/apache/qpid/client/AMQConnection.java | 29 +- .../qpid/client/AMQConnectionDelegate_0_10.java | 2 + .../org/apache/qpid/client/AMQQueueBrowser.java | 68 +- .../java/org/apache/qpid/client/AMQSession.java | 141 +- .../org/apache/qpid/client/AMQSession_0_10.java | 64 +- .../org/apache/qpid/client/AMQSession_0_8.java | 19 +- .../apache/qpid/client/BasicMessageConsumer.java | 18 +- .../apache/qpid/client/BasicMessageProducer.java | 222 +- .../qpid/client/BasicMessageProducer_0_10.java | 4 +- .../qpid/client/BasicMessageProducer_0_8.java | 8 +- .../java/org/apache/qpid/client/Closeable.java | 7 +- .../org/apache/qpid/client/XAResourceImpl.java | 25 +- .../java/org/apache/qpid/client/XASessionImpl.java | 16 +- .../client/handler/ClientMethodDispatcherImpl.java | 4 +- .../qpid/client/message/FieldTableSupport.java | 7 +- .../qpid/client/protocol/AMQProtocolHandler.java | 3 +- .../qpid/client/protocol/AMQProtocolSession.java | 15 +- .../apache/qpid/client/util/BlockingWaiter.java | 39 +- .../jndi/PropertiesFileInitialContextFactory.java | 62 +- .../java/org/apache/qpid/jndi/JNDITest.properties | 28 + .../PropertiesFileInitialContextFactoryTest.java | 95 + .../java/org/apache/qpid/jndi/hello.properties | 27 + .../qpid/test/unit/jndi/JNDIPropertyFileTest.java | 88 - .../apache/qpid/test/unit/jndi/JNDITest.properties | 28 - .../qpid/test/unit/message/TestAMQSession.java | 2 +- java/common.xml | 2 +- java/common/src/main/java/common.bnd | 2 +- .../org/apache/qpid/codec/MarkableDataInput.java | 20 + .../org/apache/qpid/common/AMQPFilterTypes.java | 4 +- .../org/apache/qpid/framing/AMQShortString.java | 5 + .../apache/qpid/framing/ByteArrayDataInput.java | 20 + .../org/apache/qpid/framing/ContentHeaderBody.java | 11 - .../org/apache/qpid/framing/EncodingUtils.java | 3 - .../org/apache/qpid/framing/ExtendedDataInput.java | 20 + .../qpid/properties/ConnectionStartProperties.java | 21 +- .../java/org/apache/qpid/transport/Connection.java | 1 + .../transport/NetworkTransportConfiguration.java | 4 + .../main/java/org/apache/qpid/transport/Range.java | 5 + .../java/org/apache/qpid/transport/RangeSet.java | 2 + .../org/apache/qpid/transport/RangeSetImpl.java | 62 + .../org/apache/qpid/transport/ServerDelegate.java | 8 +- .../java/org/apache/qpid/transport/Session.java | 16 +- .../qpid/transport/codec/AbstractEncoder.java | 2 + .../apache/qpid/transport/network/Assembler.java | 2 +- .../transport/network/io/IoNetworkTransport.java | 2 +- .../org/apache/qpid/test/utils/QpidTestCase.java | 18 +- .../org/apache/qpid/transport/RangeSetTest.java | 114 + java/genpom | 34 +- java/integrationtests/README.txt | 13 - java/integrationtests/bin/interoptests.py | 180 - java/integrationtests/build.xml | 28 - .../docs/RunningSustainedTests.txt | 17 - java/integrationtests/jar-with-dependencies.xml | 47 - .../interop/clienttestcases/TestCase1DummyRun.java | 135 - .../interop/clienttestcases/TestCase2BasicP2P.java | 209 - .../clienttestcases/TestCase3BasicPubSub.java | 239 - .../clienttestcases/TestCase4P2PMessageSize.java | 214 - .../TestCase5PubSubMessageSize.java | 243 - .../testcases/InteropTestCase1DummyRun.java | 84 - .../testcases/InteropTestCase2BasicP2P.java | 90 - .../testcases/InteropTestCase3BasicPubSub.java | 88 - .../testcases/InteropTestCase4P2PMessageSize.java | 193 - .../InteropTestCase5PubSubMessageSize.java | 193 - .../qpid/sustained/SustainedClientTestCase.java | 906 -- .../apache/qpid/sustained/SustainedTestCase.java | 126 - .../src/resources/sustained-log4j.xml | 69 - java/ivy.xml | 2 +- java/jca/.gitignore | 1 - java/jca/README.txt | 127 +- java/jca/example/.gitignore | 19 + java/jca/example/README-EXAMPLE.txt | 235 + java/jca/example/README-GERONIMO.txt | 69 + java/jca/example/README-GLASSFISH.txt | 84 + java/jca/example/README-JBOSS.txt | 107 + java/jca/example/README-JBOSS7.txt | 116 + java/jca/example/README.txt | 277 - java/jca/example/build-geronimo-properties.xml | 21 +- java/jca/example/build-glassfish-properties.xml | 135 + java/jca/example/build-jboss-properties.xml | 7 +- java/jca/example/build-jboss7-properties.xml | 133 + java/jca/example/build.xml | 25 +- java/jca/example/conf/geronimo-application.xml | 2 +- java/jca/example/conf/geronimo-ra.xml | 40 +- java/jca/example/conf/glassfish-ejb-jar.xml | 70 + java/jca/example/conf/glassfish-resources.xml | 74 + java/jca/example/conf/glassfish-web.xml | 26 + java/jca/example/conf/jboss-ejb-client.properties | 12 + java/jca/example/conf/jboss-web.xml | 5 + java/jca/example/conf/log4j.properties | 18 + java/jca/example/conf/qpid-jca-ds.xml | 27 +- java/jca/example/conf/qpid-standalone.xml | 422 + java/jca/example/conf/web.xml | 11 + java/jca/example/qpid-jca-example-properties.xml | 15 +- .../example/client/QpidRequestResponseClient.java | 2 +- .../jca/example/ejb/QpidGoodByeListenerBean.java | 2 +- .../jca/example/ejb/QpidGoodByeSubscriberBean.java | 3 +- .../jca/example/ejb/QpidHelloListenerBean.java | 4 +- .../jca/example/ejb/QpidHelloSubscriberBean.java | 5 +- .../qpid/jca/example/ejb/QpidJMSResponderBean.java | 13 +- .../apache/qpid/jca/example/ejb/QpidTestBean.java | 4 +- .../example/web/QpidRequestResponseServlet.java | 283 + .../qpid/jca/example/web/QpidTestServlet.java | 47 +- .../qpid/ra/ConnectionFactoryProperties.java | 6 +- .../qpid/ra/QpidRAConnectionRequestInfo.java | 36 +- .../apache/qpid/ra/QpidRAManagedConnection.java | 109 +- .../qpid/ra/QpidRAManagedConnectionFactory.java | 4 +- .../java/org/apache/qpid/ra/QpidRAProperties.java | 48 +- .../java/org/apache/qpid/ra/QpidRASession.java | 2 + .../org/apache/qpid/ra/QpidRASessionFactory.java | 2 +- .../apache/qpid/ra/QpidRASessionFactoryImpl.java | 12 +- .../java/org/apache/qpid/ra/QpidRASessionImpl.java | 2 +- .../org/apache/qpid/ra/QpidResourceAdapter.java | 140 +- .../qpid/ra/admin/QpidConnectionFactoryProxy.java | 27 +- .../org/apache/qpid/ra/admin/QpidQueueImpl.java | 25 - .../org/apache/qpid/ra/inflow/QpidActivation.java | 501 +- .../apache/qpid/ra/inflow/QpidActivationSpec.java | 29 +- .../qpid/ra/inflow/QpidExceptionHandler.java | 339 + .../apache/qpid/ra/inflow/QpidMessageHandler.java | 139 +- .../ra/tm/GlassfishTransactionManagerLocator.java | 63 + .../ra/tm/JBoss7TransactionManagerLocator.java | 20 + .../qpid/ra/tm/WLSTransactionManagerLocator.java | 64 + java/jca/src/main/resources/META-INF/ra.xml | 42 +- .../org/apache/qpid/ra/QpidActivationSpecTest.java | 45 + .../apache/qpid/ra/QpidResourceAdapterTest.java | 78 + java/junit-toolkit/build.xml | 26 - .../junit/concurrency/DefaultThreadFactory.java | 48 - .../concurrency/PossibleDeadlockException.java | 46 - .../qpid/junit/concurrency/TestRunnable.java | 239 - .../junit/concurrency/ThreadTestCoordinator.java | 486 - .../qpid/junit/concurrency/ThreadTestExample.java | 145 - .../org/apache/qpid/junit/concurrency/package.html | 28 - .../qpid/junit/extensions/AsymptoticTestCase.java | 303 - .../junit/extensions/AsymptoticTestDecorator.java | 173 - .../apache/qpid/junit/extensions/BaseThrottle.java | 98 - .../qpid/junit/extensions/BatchedThrottle.java | 94 - .../junit/extensions/DurationTestDecorator.java | 205 - .../qpid/junit/extensions/InstrumentedTest.java | 66 - .../qpid/junit/extensions/NullResultPrinter.java | 92 - .../ParameterVariationTestDecorator.java | 175 - .../qpid/junit/extensions/ScaledTestDecorator.java | 391 - .../qpid/junit/extensions/SetupTaskAware.java | 55 - .../qpid/junit/extensions/SetupTaskHandler.java | 92 - .../qpid/junit/extensions/ShutdownHookable.java | 42 - .../qpid/junit/extensions/SleepThrottle.java | 81 - .../apache/qpid/junit/extensions/TKTestResult.java | 654 - .../apache/qpid/junit/extensions/TKTestRunner.java | 694 - .../TestRunnerImprovedErrorHandling.java | 131 - .../qpid/junit/extensions/TestThreadAware.java | 54 - .../org/apache/qpid/junit/extensions/Throttle.java | 73 - .../qpid/junit/extensions/TimingController.java | 198 - .../junit/extensions/TimingControllerAware.java | 43 - .../extensions/WrappedSuiteTestDecorator.java | 134 - .../extensions/listeners/CSVTestListener.java | 572 - .../extensions/listeners/ConsoleTestListener.java | 274 - .../junit/extensions/listeners/TKTestListener.java | 142 - .../extensions/listeners/XMLTestListener.java | 410 - .../qpid/junit/extensions/listeners/package.html | 27 - .../org/apache/qpid/junit/extensions/package.html | 33 - .../junit/extensions/util/CommandLineParser.java | 787 - .../extensions/util/ContextualProperties.java | 494 - .../qpid/junit/extensions/util/MathUtils.java | 428 - .../junit/extensions/util/ParsedProperties.java | 390 - .../apache/qpid/junit/extensions/util/SizeOf.java | 94 - .../qpid/junit/extensions/util/StackQueue.java | 131 - .../extensions/util/TestContextProperties.java | 202 - .../qpid/junit/extensions/util/TestUtils.java | 54 - .../apache/qpid/junit/extensions/util/package.html | 27 - java/lib/gson-2.0.jar | Bin 0 -> 202952 bytes java/lib/jackson-core-asl-1.9.0.jar | Bin 0 -> 228286 bytes java/lib/jackson-mapper-asl-1.9.0.jar | Bin 0 -> 764075 bytes java/lib/jetty-6.1.14.jar | Bin 516429 -> 0 bytes java/lib/jetty-servlet-tester-6.1.14.jar | Bin 9206 -> 0 bytes java/lib/jetty-util-6.1.14.jar | Bin 163122 -> 0 bytes java/lib/mockito-all-1.9.0.jar | Bin 0 -> 1495219 bytes java/lib/org.apache.felix.framework-2.0.5.jar | Bin 391763 -> 0 bytes java/lib/org.apache.felix.main-2.0.5.jar | Bin 0 -> 391763 bytes java/lib/poms/commons-digester-1.8.1.xml | 6 + java/lib/poms/jackson-core-asl-1.9.0.xml | 22 + java/lib/poms/jackson-mapper-asl-1.9.0.xml | 22 + java/lib/poms/org.apache.felix.framework-2.0.5.xml | 22 - java/lib/poms/org.apache.felix.main-2.0.5.xml | 40 + java/lib/poms/org.osgi.core-1.0.0.xml | 22 - java/lib/poms/xalan-2.7.0.xml | 8 + java/lib/servlet-api.jar | Bin 88224 -> 0 bytes .../common/src/main/java/management-common.bnd | 2 +- .../management/eclipse-plugin/META-INF/MANIFEST.MF | 2 +- .../qpid/management/ui/ManagementConsoleTest.java | 4 +- java/module.xml | 6 +- java/perftests/RunningPerformanceTests.txt | 141 - java/perftests/bin/monitoring/monitor-broker.sh | 221 - java/perftests/bin/monitoring/runTests.sh | 148 - .../bin/monitoring/stop-monitored-broker.sh | 124 - java/perftests/bin/processing/process.sh | 388 - java/perftests/bin/processing/processAll.sh | 58 - java/perftests/bin/processing/processTests.py | 850 - java/perftests/bin/run_many.sh | 30 - java/perftests/bin/topicListener.sh | 32 - java/perftests/bin/topicPublisher.sh | 31 - java/perftests/build.xml | 318 +- java/perftests/dist-zip.xml | 45 - .../chartdefs/AcknowledgementModesAutoAck.chartdef | 28 + .../AcknowledgementModesTransacted.chartdef | 28 + java/perftests/etc/chartdefs/BatchSize.chartdef | 28 + .../chartdefs/MessageSizeNonPersistent.chartdef | 27 + .../etc/chartdefs/MessageSizePersistent.chartdef | 29 + java/perftests/etc/chartdefs/QueueTypes.chartdef | 28 + .../chartdefs/VaryingNumberOfConsumers.chartdef | 35 + .../chartdefs/VaryingNumberOfProducers.chartdef | 35 + java/perftests/etc/jndi/activemq.properties | 20 - java/perftests/etc/jndi/failovertest.properties | 19 - java/perftests/etc/jndi/perftests.properties | 19 - java/perftests/etc/jndi/swiftmq.properties | 20 - java/perftests/etc/log4j.properties | 28 + java/perftests/etc/perftests-jndi.properties | 26 + java/perftests/etc/perftests.log4j | 46 - java/perftests/etc/scripts/CTQ-Qpid-1.sh | 21 - java/perftests/etc/scripts/CTQ-Qpid-2.sh | 21 - java/perftests/etc/scripts/CTQ-Qpid-3.sh | 21 - java/perftests/etc/scripts/CTQ-Qpid-4.sh | 21 - java/perftests/etc/scripts/CTQ-Qpid-5.sh | 21 - java/perftests/etc/scripts/CTQ-Qpid-6.sh | 21 - java/perftests/etc/scripts/Connections.sh | 20 - java/perftests/etc/scripts/JobQueue.sh | 20 - java/perftests/etc/scripts/Latency.sh | 21 - java/perftests/etc/scripts/MessageSize.sh | 20 - java/perftests/etc/scripts/PT-Qpid-13.sh | 42 - java/perftests/etc/scripts/PT-Qpid-14.sh | 41 - java/perftests/etc/scripts/Reliability.sh | 20 - java/perftests/etc/scripts/RunAll.sh | 23 - java/perftests/etc/scripts/RunCore.sh | 22 - java/perftests/etc/scripts/Test-ActiveMQ.sh | 32 - java/perftests/etc/scripts/Test-SwiftMQ.sh | 30 - java/perftests/etc/scripts/Throughput.sh | 20 - java/perftests/etc/scripts/drainBroker.sh | 41 - java/perftests/etc/scripts/extractResults.sh | 34 - .../etc/scripts/extractThroughputResults.sh | 51 - java/perftests/etc/scripts/fillBroker.sh | 41 - java/perftests/etc/scripts/sendAndWaitClient.sh | 22 - java/perftests/etc/scripts/testWithPreFill.sh | 41 - .../etc/testdefs/short/AcknowledgementModes.json | 138 + java/perftests/etc/testdefs/short/BatchSize.json | 84 + java/perftests/etc/testdefs/short/MessageSize.json | 213 + java/perftests/etc/testdefs/short/QueueTypes.json | 16198 ++++++++++++++++++ .../short/VaryingNumberOfParticipants.json | 2981 ++++ .../testdefs/standard/AcknowledgementModes.json | 138 + .../perftests/etc/testdefs/standard/BatchSize.json | 84 + .../etc/testdefs/standard/MessageSize.json | 213 + .../etc/testdefs/standard/QueueTypes.json | 16205 +++++++++++++++++++ .../etc/testdefs/standard/QueuesWithSelectors.json | 2036 +++ .../standard/VaryingNumberOfParticipants.json | 2981 ++++ java/perftests/example/PQBT-AA-Qpid-01.json | 795 + java/perftests/example/TQBT-TX-Qpid-01.json | 843 + java/perftests/example/brokerconfig/log4j.xml | 125 + java/perftests/example/brokerconfig/passwd | 23 + .../example/brokerconfig/virtualhosts.xml | 67 + java/perftests/example/config-one-test.json | 55 + .../config-stress-testing-manyp-c1-with-psfc.json | 162 + java/perftests/example/config-stress-testing.json | 84 + java/perftests/example/config-two-tests.json | 117 + java/perftests/example/log4j-client.properties | 29 + java/perftests/example/log4j.properties | 35 + java/perftests/example/perftests-jndi.properties | 26 + java/perftests/example/run-client.sh | 21 + java/perftests/example/run.sh | 22 + java/perftests/generate-scripts | 74 - java/perftests/jar-with-dependencies.xml | 91 - java/perftests/scripts.xml | 328 - .../qpid/client/message/TestMessageFactory.java | 117 - .../config/AMQConnectionFactoryInitialiser.java | 47 - .../org/apache/qpid/config/AbstractConfig.java | 69 - .../qpid/config/ConnectionFactoryInitialiser.java | 29 - .../java/org/apache/qpid/config/Connector.java | 43 - .../org/apache/qpid/config/ConnectorConfig.java | 28 - .../config/JBossConnectionFactoryInitialiser.java | 112 - .../org/apache/qpid/disttest/AbstractRunner.java | 74 + .../org/apache/qpid/disttest/ArgumentParser.java | 44 + .../org/apache/qpid/disttest/ClientRunner.java | 94 + .../org/apache/qpid/disttest/ControllerRunner.java | 238 + .../qpid/disttest/DistributedTestConstants.java | 33 + .../qpid/disttest/DistributedTestException.java | 66 + .../java/org/apache/qpid/disttest/Visitor.java | 76 + .../org/apache/qpid/disttest/client/Client.java | 208 + .../qpid/disttest/client/ClientCommandVisitor.java | 98 + .../apache/qpid/disttest/client/ClientState.java | 25 + .../qpid/disttest/client/ConsumerParticipant.java | 251 + .../qpid/disttest/client/MessageProvider.java | 212 + .../apache/qpid/disttest/client/Participant.java | 31 + .../qpid/disttest/client/ParticipantExecutor.java | 136 + .../client/ParticipantExecutorRegistry.java | 45 + .../disttest/client/ParticipantResultFactory.java | 100 + .../qpid/disttest/client/ProducerParticipant.java | 174 + .../client/property/GeneratedPropertySupport.java | 68 + .../client/property/GeneratedPropertyValue.java | 27 + .../client/property/ListPropertyValue.java | 122 + .../property/NumericGeneratedPropertySupport.java | 179 + .../disttest/client/property/PropertyValue.java | 27 + .../client/property/PropertyValueFactory.java | 46 + .../client/property/RandomPropertyValue.java | 47 + .../client/property/RangePropertyValue.java | 129 + .../client/property/SimplePropertyValue.java | 79 + .../qpid/disttest/controller/ClientRegistry.java | 96 + .../qpid/disttest/controller/CommandForClient.java | 46 + .../qpid/disttest/controller/CommandListener.java | 31 + .../qpid/disttest/controller/Controller.java | 228 + .../disttest/controller/ParticipatingClients.java | 94 + .../disttest/controller/ResultsForAllTests.java | 49 + .../qpid/disttest/controller/TestResult.java | 70 + .../qpid/disttest/controller/TestRunner.java | 342 + .../disttest/controller/TestRunnerFactory.java | 31 + .../disttest/controller/config/ClientConfig.java | 113 + .../qpid/disttest/controller/config/Config.java | 81 + .../disttest/controller/config/ConfigReader.java | 52 + .../controller/config/ConnectionConfig.java | 91 + .../disttest/controller/config/ConsumerConfig.java | 65 + .../disttest/controller/config/IterationValue.java | 86 + .../controller/config/MessageProviderConfig.java | 60 + .../controller/config/ParticipantConfig.java | 64 + .../disttest/controller/config/ProducerConfig.java | 90 + .../disttest/controller/config/QueueConfig.java | 69 + .../disttest/controller/config/SessionConfig.java | 114 + .../disttest/controller/config/TestConfig.java | 117 + .../disttest/controller/config/TestInstance.java | 102 + .../qpid/disttest/jms/ClientJmsDelegate.java | 592 + .../qpid/disttest/jms/ControllerJmsDelegate.java | 210 + .../qpid/disttest/jms/JmsMessageAdaptor.java | 124 + .../apache/qpid/disttest/jms/QpidQueueCreator.java | 97 + .../org/apache/qpid/disttest/jms/QueueCreator.java | 31 + .../org/apache/qpid/disttest/json/JsonHandler.java | 43 + .../qpid/disttest/json/PropertyValueAdapter.java | 147 + .../org/apache/qpid/disttest/message/Command.java | 56 + .../apache/qpid/disttest/message/CommandType.java | 39 + .../message/ConsumerParticipantResult.java | 118 + .../disttest/message/CreateConnectionCommand.java | 58 + .../disttest/message/CreateConsumerCommand.java | 108 + .../message/CreateMessageProviderCommand.java | 54 + .../disttest/message/CreateParticpantCommand.java | 103 + .../disttest/message/CreateProducerCommand.java | 106 + .../disttest/message/CreateResponderCommand.java | 28 + .../disttest/message/CreateSessionCommand.java | 62 + .../apache/qpid/disttest/message/NoOpCommand.java | 30 + .../qpid/disttest/message/OutputAttribute.java | 35 + .../disttest/message/ParticipantAttribute.java | 70 + .../message/ParticipantAttributeExtractor.java | 89 + .../qpid/disttest/message/ParticipantResult.java | 272 + .../message/ProducerParticipantResult.java | 100 + .../disttest/message/RegisterClientCommand.java | 43 + .../org/apache/qpid/disttest/message/Response.java | 80 + .../qpid/disttest/message/StartTestCommand.java | 29 + .../qpid/disttest/message/StopClientCommand.java | 28 + .../qpid/disttest/message/TearDownTestCommand.java | 29 + .../results/aggregation/AggregatedTestResult.java | 97 + .../disttest/results/aggregation/Aggregator.java | 49 + .../disttest/results/aggregation/ITestResult.java | 36 + .../aggregation/ParticipantResultAggregator.java | 143 + .../results/aggregation/TestResultAggregator.java | 106 + .../disttest/results/formatting/CSVFormater.java | 89 + .../CSVOrderParticipantResultComparator.java | 55 + .../main/java/org/apache/qpid/oldtopic/Config.java | 243 - .../java/org/apache/qpid/oldtopic/Listener.java | 141 - .../org/apache/qpid/oldtopic/MessageFactory.java | 153 - .../java/org/apache/qpid/oldtopic/Publisher.java | 178 - .../org/apache/qpid/ping/PingAsyncTestPerf.java | 323 - .../main/java/org/apache/qpid/ping/PingClient.java | 112 - .../org/apache/qpid/ping/PingDurableClient.java | 452 - .../org/apache/qpid/ping/PingLatencyTestPerf.java | 311 - .../org/apache/qpid/ping/PingSendOnlyClient.java | 93 - .../java/org/apache/qpid/ping/PingTestPerf.java | 281 - .../apache/qpid/requestreply/PingPongBouncer.java | 453 - .../apache/qpid/requestreply/PingPongProducer.java | 1818 --- .../apache/qpid/requestreply/PingPongTestPerf.java | 251 - .../main/java/org/apache/qpid/topic/Config.java | 326 - .../main/java/org/apache/qpid/topic/Listener.java | 303 - .../java/org/apache/qpid/topic/MessageFactory.java | 157 - .../main/java/org/apache/qpid/topic/Publisher.java | 186 - .../TopicWithSelectorsTransientVolumeTest.java | 344 - .../apache/qpid/topic/topicselectors.properties | 24 - .../src/main/resources/perftests.properties | 20 + .../apache/qpid/disttest/ArgumentParserTest.java | 96 + .../org/apache/qpid/disttest/ConfigFileHelper.java | 48 + .../java/org/apache/qpid/disttest/VisitorTest.java | 92 + .../disttest/client/ClientCommandVisitorTest.java | 108 + .../apache/qpid/disttest/client/ClientTest.java | 159 + .../disttest/client/ConsumerParticipantTest.java | 180 + .../qpid/disttest/client/MessageProviderTest.java | 107 + .../disttest/client/ParticipantExecutorTest.java | 183 + .../disttest/client/ParticipantRegistryTest.java | 55 + .../client/ParticipantResultFactoryTest.java | 183 + .../disttest/client/ParticipantTestHelper.java | 83 + .../disttest/client/ProducerParticipantTest.java | 219 + .../client/property/ListPropertyValueTest.java | 88 + .../client/property/PropertyValueFactoryTest.java | 73 + .../client/property/RandomPropertyValueTest.java | 76 + .../client/property/RangePropertyValueTest.java | 153 + .../client/property/SimplePropertyValueTest.java | 30 + .../disttest/controller/ClientRegistryTest.java | 99 + .../qpid/disttest/controller/ControllerTest.java | 198 + .../controller/ParticipatingClientsTest.java | 144 + .../qpid/disttest/controller/TestRunnerTest.java | 253 + .../controller/config/ClientConfigTest.java | 111 + .../controller/config/ConfigReaderTest.java | 113 + .../disttest/controller/config/ConfigTest.java | 56 + .../controller/config/ConfigTestUtils.java | 56 + .../controller/config/ConnectionConfigTest.java | 94 + .../controller/config/ConsumerConfigTest.java | 79 + .../controller/config/IterationValueTest.java | 78 + .../config/MessageProviderConfigTest.java | 51 + .../controller/config/ProducerConfigTest.java | 89 + .../controller/config/SessionConfigTest.java | 93 + .../disttest/controller/config/TestConfigTest.java | 113 + .../controller/config/TestInstanceTest.java | 102 + .../disttest/controller/config/sampleConfig.json | 72 + .../qpid/disttest/jms/JmsMessageAdaptorTest.java | 40 + .../qpid/disttest/message/JsonHandlerTest.java | 183 + .../disttest/message/ParticipantResultTest.java | 162 + .../results/aggregation/AggregatorTest.java | 61 + .../ParticipantResultAggregatorTest.java | 272 + .../aggregation/TestResultAggregatorTest.java | 152 + .../results/formatting/CSVFormaterTest.java | 144 + .../CSVOrderParticipantResultComparatorTest.java | 89 + .../disttest/results/formatting/expectedOutput.csv | 2 + .../disttest/DistributedTestSystemTestBase.java | 72 + .../systest/disttest/QpidQueueCreatorTest.java | 116 + .../qpid/systest/disttest/SystemTestConstants.java | 28 + .../clientonly/BasicDistributedClientTest.java | 186 + .../clientonly/ConsumerParticipantTest.java | 156 + .../disttest/clientonly/ControllerQueue.java | 90 + .../disttest/clientonly/DistributedClientTest.java | 323 + .../disttest/clientonly/MessageProviderTest.java | 119 + .../clientonly/ProducerParticipantTest.java | 132 + .../ControllerAndClientTest.java | 249 + .../controllerandclient/iteratingFeature.json | 63 + .../controllerandclient/produceClient.json | 41 + .../producerAndConsumerInSeparateClients.json | 55 + ...producerAndThreeConsumersInSeparateClients.json | 77 + .../controllerandclient/testWithTwoTests.json | 107 + .../controlleronly/DistributedControllerTest.java | 157 + .../controlleronly/distributedControllerTest.json | 17 + .../systest/disttest/endtoend/EndToEndTest.java | 95 + .../qpid/systest/disttest/endtoend/endtoend.json | 65 + .../systest/disttest/perftests.systests.properties | 26 + java/perftests/visualisation-jfc/build.xml | 142 + .../apache/qpid/disttest/charting/ChartType.java | 26 + .../qpid/disttest/charting/ChartingException.java | 46 + .../qpid/disttest/charting/ChartingUtil.java | 135 + .../charting/chartbuilder/BarChartBuilder.java | 47 + .../charting/chartbuilder/ChartBuilder.java | 30 + .../charting/chartbuilder/ChartBuilderFactory.java | 40 + .../charting/chartbuilder/DataPointCallback.java | 27 + .../chartbuilder/DataSetBasedChartBuilder.java | 68 + .../charting/chartbuilder/LineChartBuilder.java | 45 + .../charting/chartbuilder/SeriesBuilder.java | 133 + .../charting/definition/ChartingDefinition.java | 85 + .../definition/ChartingDefinitionCreator.java | 140 + .../charting/definition/SeriesDefinition.java | 50 + .../definition/SeriesDefinitionCreator.java | 60 + .../chartbuilder/ChartBuilderFactoryTest.java | 40 + .../charting/chartbuilder/SeriesBuilderTest.java | 90 + .../definition/ChartingDefinitionCreatorTest.java | 149 + .../definition/SeriesDefinitionCreatorTest.java | 113 + java/systests/build.xml | 6 +- java/systests/etc/bin/testclients.sh | 23 - .../etc/virtualhosts-systests-bdb-settings.xml | 6 +- .../etc/virtualhosts-systests-derby-settings.xml | 8 +- .../etc/virtualhosts-systests-firewall-2.xml | 4 +- .../etc/virtualhosts-systests-firewall-3.xml | 4 +- .../qpid/client/AsynchMessageListenerTest.java | 362 + .../org/apache/qpid/client/DispatcherTest.java | 233 - ...sageListenerMultiConsumerImmediatePrefetch.java | 44 - .../client/MessageListenerMultiConsumerTest.java | 252 - .../apache/qpid/client/MessageListenerTest.java | 258 - .../qpid/client/ResetMessageListenerTest.java | 228 - .../org/apache/qpid/client/SessionCreateTest.java | 7 +- .../org/apache/qpid/client/SynchReceiveTest.java | 133 + .../client/redelivered/RedeliveredMessageTest.java | 20 + .../org/apache/qpid/jms/xa/XAResourceTest.java | 17 +- .../qpid/management/jmx/ManagedQueueMBeanTest.java | 256 +- .../org/apache/qpid/ra/QpidRAConnectionTest.java | 89 + .../qpid/server/SupportedProtocolVersionsTest.java | 3 + .../exchange/MessagingTestConfigProperties.java | 300 - .../ReturnUnroutableMandatoryMessageTest.java | 2 +- .../logging/DerbyMessageStoreLoggingTest.java | 573 - .../logging/MemoryMessageStoreLoggingTest.java | 186 - .../server/logging/SubscriptionLoggingTest.java | 5 +- .../persistent/NoLocalAfterRecoveryTest.java | 78 +- .../qpid/server/queue/PriorityQueueTest.java | 100 + .../qpid/server/queue/ProducerFlowControlTest.java | 36 +- .../apache/qpid/server/store/SlowMessageStore.java | 70 +- .../qpid/server/store/SlowMessageStoreFactory.java | 37 + .../org/apache/qpid/test/client/CancelTest.java | 101 - .../ImmediateAndMandatoryPublishingTest.java | 98 +- .../qpid/test/client/QueueBrowserAutoAckTest.java | 28 +- .../test/client/timeouts/SyncWaitDelayTest.java | 2 +- .../apache/qpid/test/framework/AMQPPublisher.java | 54 - .../org/apache/qpid/test/framework/Assertion.java | 39 - .../apache/qpid/test/framework/AssertionBase.java | 66 - .../qpid/test/framework/BrokerLifecycleAware.java | 70 - .../apache/qpid/test/framework/CauseFailure.java | 42 - .../test/framework/CauseFailureUserPrompt.java | 63 - .../org/apache/qpid/test/framework/Circuit.java | 109 - .../org/apache/qpid/test/framework/CircuitEnd.java | 95 - .../apache/qpid/test/framework/CircuitEndBase.java | 156 - .../org/apache/qpid/test/framework/DropInTest.java | 51 - .../qpid/test/framework/ExceptionMonitor.java | 204 - .../qpid/test/framework/FrameworkBaseCase.java | 299 - .../qpid/test/framework/FrameworkTestContext.java | 48 - .../test/framework/LocalAMQPCircuitFactory.java | 173 - .../qpid/test/framework/LocalCircuitFactory.java | 320 - .../qpid/test/framework/MessageIdentityVector.java | 167 - .../apache/qpid/test/framework/MessageMonitor.java | 104 - .../framework/MessagingTestConfigProperties.java | 684 - .../test/framework/NotApplicableAssertion.java | 112 - .../org/apache/qpid/test/framework/Publisher.java | 74 - .../org/apache/qpid/test/framework/Receiver.java | 92 - .../apache/qpid/test/framework/TestCaseVector.java | 88 - .../qpid/test/framework/TestClientDetails.java | 86 - .../org/apache/qpid/test/framework/TestUtils.java | 200 - .../clocksynch/ClockSynchFailureException.java | 45 - .../framework/clocksynch/ClockSynchThread.java | 124 - .../framework/clocksynch/ClockSynchronizer.java | 69 - .../clocksynch/LocalClockSynchronizer.java | 73 - .../framework/clocksynch/UDPClockReference.java | 169 - .../framework/clocksynch/UDPClockSynchronizer.java | 468 - .../distributedcircuit/DistributedCircuitImpl.java | 472 - .../DistributedPublisherImpl.java | 94 - .../DistributedReceiverImpl.java | 94 - .../distributedcircuit/TestClientCircuitEnd.java | 333 - .../framework/distributedtesting/Coordinator.java | 546 - .../DistributedTestDecorator.java | 164 - .../distributedtesting/FanOutTestDecorator.java | 241 - .../distributedtesting/InteropTestDecorator.java | 210 - .../distributedtesting/OptOutTestCase.java | 69 - .../framework/distributedtesting/TestClient.java | 510 - .../TestClientControlledTest.java | 107 - .../test/framework/listeners/XMLTestListener.java | 414 - .../localcircuit/LocalAMQPPublisherImpl.java | 137 - .../framework/localcircuit/LocalCircuitImpl.java | 313 - .../framework/localcircuit/LocalPublisherImpl.java | 176 - .../framework/localcircuit/LocalReceiverImpl.java | 149 - .../org/apache/qpid/test/framework/package.html | 43 - .../framework/sequencers/BaseCircuitFactory.java | 136 - .../test/framework/sequencers/CircuitFactory.java | 101 - .../framework/sequencers/FanOutCircuitFactory.java | 200 - .../sequencers/InteropCircuitFactory.java | 154 - .../apache/qpid/test/unit/ack/AcknowledgeTest.java | 18 +- .../qpid/test/unit/basic/BytesMessageTest.java | 43 + .../apache/qpid/test/unit/basic/ReceiveTest.java | 82 - .../BrokerClosesClientConnectionTest.java | 17 + .../qpid/test/unit/close/CloseBeforeAckTest.java | 140 - .../test/unit/close/MessageConsumerCloseTest.java | 77 + .../qpid/test/unit/ct/DurableSubscriberTest.java | 19 +- .../test/unit/topic/DurableSubscriptionTest.java | 2 +- .../unit/transacted/TransactionTimeoutTest.java | 35 + .../org/apache/qpid/test/unit/xa/FaultTest.java | 2 +- .../org/apache/qpid/test/unit/xa/QueueTest.java | 6 +- .../org/apache/qpid/test/unit/xa/TopicTest.java | 72 +- .../org/apache/qpid/test/utils/JMXTestUtils.java | 10 +- .../apache/qpid/test/utils/QpidBrokerTestCase.java | 52 +- .../qpid/test/utils/SpawnedBrokerHolder.java | 2 +- java/test-profiles/CPPExcludes | 10 +- java/test-profiles/CPPPrefetchExcludes | 4 +- java/test-profiles/Excludes | 4 +- java/test-profiles/Java010Excludes | 3 + java/test-profiles/JavaBDBExcludes | 1 + java/test-profiles/JavaDerbyExcludes | 4 +- java/test-profiles/JavaExcludes | 4 +- java/test-profiles/JavaPre010Excludes | 16 +- java/test-profiles/JavaTransientExcludes | 13 +- java/test-profiles/java-bdb-spawn.0-10.testprofile | 2 +- java/test-profiles/java-bdb-spawn.0-8.testprofile | 6 +- .../test-profiles/java-bdb-spawn.0-9-1.testprofile | 6 +- java/test-profiles/java-bdb-spawn.0-9.testprofile | 6 +- java/test-profiles/java-bdb.0-10.testprofile | 2 +- java/test-profiles/java-bdb.0-8.testprofile | 6 +- java/test-profiles/java-bdb.0-9-1.testprofile | 6 +- java/test-profiles/java-bdb.0-9.testprofile | 6 +- java/test-profiles/java-dby-spawn.0-10.testprofile | 2 +- java/test-profiles/java-dby-spawn.0-8.testprofile | 6 +- .../test-profiles/java-dby-spawn.0-9-1.testprofile | 6 +- java/test-profiles/java-dby-spawn.0-9.testprofile | 6 +- java/test-profiles/java-dby.0-10.testprofile | 2 +- java/test-profiles/java-dby.0-8.testprofile | 6 +- java/test-profiles/java-dby.0-9-1.testprofile | 6 +- java/test-profiles/java-dby.0-9.testprofile | 6 +- java/test-profiles/java-mms-spawn.0-8.testprofile | 4 +- .../test-profiles/java-mms-spawn.0-9-1.testprofile | 4 +- java/test-profiles/java-mms-spawn.0-9.testprofile | 4 +- java/test-profiles/java-mms.0-8.testprofile | 4 +- java/test-profiles/java-mms.0-9-1.testprofile | 4 +- java/test-profiles/java-mms.0-9.testprofile | 4 +- .../python_tests/Java010PythonExcludes | 59 +- java/test-profiles/testprofile.defaults | 4 +- java/testkit/README.txt | 6 - java/testkit/bin/run_soak_client.sh | 70 - java/testkit/bin/soak_report.sh | 161 - java/testkit/build.xml | 27 - .../apache/qpid/testkit/soak/ResourceLeakTest.java | 180 - java/tools/bin/controller | 132 - java/tools/bin/jms-quick-perf-report | 137 + java/tools/bin/mercury-controller | 132 + java/tools/bin/mercury-start-consumers | 119 + java/tools/bin/mercury-start-producers | 136 + java/tools/bin/perf-report | 137 - java/tools/bin/start-consumers | 119 - java/tools/bin/start-producers | 136 - .../src/main/java/org/apache/qpid/tools/Clock.java | 2 + .../org/apache/qpid/tools/JVMArgConfiguration.java | 411 + .../java/org/apache/qpid/tools/LatencyTest.java | 349 - .../java/org/apache/qpid/tools/MercuryBase.java | 191 + .../qpid/tools/MercuryConsumerController.java | 231 + .../qpid/tools/MercuryProducerController.java | 210 + .../apache/qpid/tools/MercuryTestController.java | 450 + .../main/java/org/apache/qpid/tools/PerfBase.java | 226 - .../java/org/apache/qpid/tools/PerfConsumer.java | 325 - .../java/org/apache/qpid/tools/PerfProducer.java | 358 - .../org/apache/qpid/tools/PerfTestController.java | 442 - .../java/org/apache/qpid/tools/QpidReceive.java | 181 + .../main/java/org/apache/qpid/tools/QpidSend.java | 291 + .../org/apache/qpid/tools/TestConfiguration.java | 126 + .../java/org/apache/qpid/tools/TestParams.java | 214 - .../apache/qpid/tools/report/BasicReporter.java | 113 + .../apache/qpid/tools/report/MercuryReporter.java | 167 + .../org/apache/qpid/tools/report/Reporter.java | 40 + .../org/apache/qpid/tools/report/Statistics.java | 139 + packaging/windows/INSTALL_NOTES.html | 8 +- packaging/windows/installer.proj | 2 +- python/qpid/connection.py | 13 +- python/qpid/messaging/driver.py | 6 +- python/qpid/testlib.py | 12 + python/qpid/tests/messaging/endpoints.py | 10 +- python/setup.py | 2 +- specs/amqp.xsl | 534 + specs/apache-filters.xml | 228 + specs/management-schema.xml | 11 +- tests/setup.py | 2 +- tests/src/py/qpid_tests/broker_0_10/management.py | 43 +- tests/src/py/qpid_tests/broker_0_10/msg_groups.py | 72 +- tests/src/py/qpid_tests/broker_0_10/new_api.py | 5 +- tools/setup.py | 23 +- tools/src/py/qmf-tool | 2 +- tools/src/py/qpid-config | 199 +- tools/src/py/qpid-ha | 153 + tools/src/py/qpid-ha-tool | 183 - tools/src/py/qpid-route | 10 +- tools/src/py/qpid-stat | 195 +- tools/src/py/qpidtoollibs/__init__.py | 4 + tools/src/py/qpidtoollibs/broker.py | 168 +- tools/src/py/qpidtoollibs/disp.py | 41 +- wcf/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp | 7 +- 1908 files changed, 180356 insertions(+), 89300 deletions(-) create mode 100755 bin/install-cpp-python delete mode 100644 cc/LICENSE delete mode 100644 cc/NOTICE delete mode 100644 cc/README.txt delete mode 100644 cc/config.properties delete mode 100644 cc/config.xml delete mode 100644 cc/config/bdbstore-cpp-trunk.xml delete mode 100644 cc/config/cpp-perftests.xml delete mode 100644 cc/config/cpp-trunk.xml delete mode 100644 cc/config/dotnet-trunk.xml delete mode 100644 cc/config/example-automation.xml delete mode 100644 cc/config/java-jmstck.xml delete mode 100644 cc/config/java-perftests.xml delete mode 100644 cc/config/java-trunk.xml delete mode 100644 cc/config/java/cpp.noprefetch.testprofile delete mode 100644 cc/config/java/cpp.testprofile delete mode 100644 cc/config/java/jndi.properties delete mode 100644 cc/dashboard-config.xml delete mode 100755 cc/scripts/bdbstorecppbuild.sh delete mode 100644 cc/scripts/build.xml delete mode 100755 cc/scripts/check_examples.sh delete mode 100755 cc/scripts/cppbuild-perftests.sh delete mode 100755 cc/scripts/cppbuild.sh delete mode 100644 cc/scripts/dotnetbuild.sh delete mode 100755 cc/scripts/javaconfig.sh delete mode 100644 cc/scripts/javajmstck.sh delete mode 100755 cc/scripts/javareport.sh delete mode 100644 cc/scripts/runbroker.sh delete mode 100644 cc/scripts/stopbroker.sh delete mode 100755 cc/scripts/verify delete mode 100755 cc/scripts/verify_all create mode 100644 cpp/etc/cluster.conf-example.xml.in delete mode 100755 cpp/etc/qpidd create mode 100755 cpp/etc/qpidd-primary.in create mode 100755 cpp/etc/qpidd.in delete mode 100644 cpp/include/qpid/sys/MemStat.h create mode 100644 cpp/src/qmf/BrokerImportExport.h create mode 100644 cpp/src/qpid/acl/AclConnectionCounter.cpp create mode 100644 cpp/src/qpid/acl/AclConnectionCounter.h create mode 100644 cpp/src/qpid/broker/QueuedMessage.cpp delete mode 100644 cpp/src/qpid/framing/BodyHandler.cpp delete mode 100644 cpp/src/qpid/framing/BodyHandler.h create mode 100644 cpp/src/qpid/ha/ReplicateLevel.cpp create mode 100644 cpp/src/qpid/ha/ReplicateLevel.h create mode 100644 cpp/src/qpid/sys/MemStat.h create mode 100644 cpp/src/qpid/sys/Probes.h delete mode 100644 cpp/src/qpid/sys/apr/APRBase.cpp delete mode 100644 cpp/src/qpid/sys/apr/APRBase.h delete mode 100644 cpp/src/qpid/sys/apr/APRPool.cpp delete mode 100644 cpp/src/qpid/sys/apr/APRPool.h delete mode 100644 cpp/src/qpid/sys/apr/Condition.h delete mode 100644 cpp/src/qpid/sys/apr/Mutex.h delete mode 100644 cpp/src/qpid/sys/apr/Shlib.cpp delete mode 100644 cpp/src/qpid/sys/apr/Socket.cpp delete mode 100644 cpp/src/qpid/sys/apr/Thread.cpp delete mode 100644 cpp/src/qpid/sys/apr/Thread.h delete mode 100644 cpp/src/qpid/sys/apr/Time.cpp delete mode 100755 cpp/src/tests/ais_check delete mode 100644 cpp/src/tests/amqp_0_10/Map.cpp delete mode 100644 cpp/src/tests/amqp_0_10/ProxyTemplate.cpp delete mode 100644 cpp/src/tests/amqp_0_10/apply.cpp delete mode 100644 cpp/src/tests/amqp_0_10/handlers.cpp delete mode 100644 cpp/src/tests/amqp_0_10/serialize.cpp create mode 100755 cpp/src/tests/cluster_failover create mode 100755 cpp/src/tests/cpg_check.sh.in create mode 100644 cpp/src/tests/qpidd-empty.conf create mode 100644 cpp/src/tests/test_env.ps1.in delete mode 100644 doc/book/README.txt delete mode 100755 doc/book/build-book.sh delete mode 100755 doc/book/build-chapter.sh delete mode 100755 doc/book/build.sh delete mode 100644 doc/book/build.xml delete mode 100644 doc/book/src/ACL.xml delete mode 100644 doc/book/src/AMQP-.NET-Messaging-Client.xml delete mode 100644 doc/book/src/AMQP-C++-Messaging-Client.xml delete mode 100644 doc/book/src/AMQP-Compatibility.xml delete mode 100644 doc/book/src/AMQP-Java-JMS-Messaging-Client.xml delete mode 100644 doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml delete mode 100644 doc/book/src/AMQP-Messaging-Broker-CPP.xml delete mode 100644 doc/book/src/AMQP-Messaging-Broker-Java-Book.xml delete mode 100644 doc/book/src/AMQP-Messaging-Broker-Java.xml delete mode 100644 doc/book/src/AMQP-Python-Messaging-Client.xml delete mode 100644 doc/book/src/AMQP-Ruby-Messaging-Client.xml delete mode 100644 doc/book/src/AMQP.xml delete mode 100644 doc/book/src/Add-New-Users.xml delete mode 100644 doc/book/src/Binding-URL-Format.xml delete mode 100644 doc/book/src/Book-Info.xml delete mode 100644 doc/book/src/Book.xml delete mode 100644 doc/book/src/Broker-CPP.xml delete mode 100644 doc/book/src/Broker-Configuration-Guide.xml delete mode 100644 doc/book/src/Broker-Java.xml delete mode 100644 doc/book/src/Cheat-Sheet-for-configuring-Exchange-Options.xml delete mode 100644 doc/book/src/Cheat-Sheet-for-configuring-Queue-Options.xml delete mode 100644 doc/book/src/Clients.xml delete mode 100644 doc/book/src/Configure-ACLs.xml delete mode 100644 doc/book/src/Configure-Java-Qpid-to-use-a-SSL-connection.xml delete mode 100644 doc/book/src/Configure-Log4j-CompositeRolling-Appender.xml delete mode 100644 doc/book/src/Configure-the-Broker-via-config.xml.xml delete mode 100644 doc/book/src/Configure-the-Virtual-Hosts-via-virtualhosts.xml.xml delete mode 100644 doc/book/src/Configuring-Management-Users.xml delete mode 100644 doc/book/src/Configuring-Qpid-JMX-Management-Console.xml delete mode 100644 doc/book/src/Connection-URL-Format.xml delete mode 100644 doc/book/src/Debug-using-log4j.xml delete mode 100644 doc/book/src/Download.xml delete mode 100644 doc/book/src/Excel-AddIn.xml delete mode 100644 doc/book/src/FAQ.xml delete mode 100644 doc/book/src/Getting-Started.xml delete mode 100644 doc/book/src/How-to-Tune-M3-Java-Broker-Performance.xml delete mode 100644 doc/book/src/How-to-Use-JNDI.xml delete mode 100644 doc/book/src/How-to-Use-SlowConsumerDisconnect.xml delete mode 100644 doc/book/src/InfoPlugin.xml delete mode 100644 doc/book/src/Introduction.xml delete mode 100644 doc/book/src/Java-Broker-Feature-Guide.xml delete mode 100644 doc/book/src/Java-Broker-StatusLogMessages.xml delete mode 100644 doc/book/src/Java-Environment-Variables.xml delete mode 100644 doc/book/src/Java-JMS-Selector-Syntax.xml delete mode 100644 doc/book/src/LVQ.xml create mode 100644 doc/book/src/Makefile.inc delete mode 100644 doc/book/src/Management-Console-Security.xml delete mode 100644 doc/book/src/Management-Design-notes.xml delete mode 100644 doc/book/src/Managing-CPP-Broker.xml delete mode 100644 doc/book/src/Message-Groups-Guide.xml delete mode 100644 doc/book/src/MessageStore-Tool.xml delete mode 100644 doc/book/src/NET-User-Guide.xml delete mode 100644 doc/book/src/Programming-In-Apache-Qpid.xml delete mode 100644 doc/book/src/PythonBrokerTest.xml delete mode 100644 doc/book/src/QMF-Python-Console-Tutorial.xml delete mode 100644 doc/book/src/QMan-Qpid-Management-bridge.xml delete mode 100644 doc/book/src/QmfBook.xml delete mode 100644 doc/book/src/QmfIntroduction.xml delete mode 100644 doc/book/src/Qpid-ACLs.xml delete mode 100644 doc/book/src/Qpid-Book.xml delete mode 100644 doc/book/src/Qpid-Compatibility-And-Interoperability-Book.xml delete mode 100644 doc/book/src/Qpid-Interoperability-Documentation.xml delete mode 100644 doc/book/src/Qpid-JMX-Management-Console-FAQ.xml delete mode 100644 doc/book/src/Qpid-JMX-Management-Console-User-Guide.xml delete mode 100644 doc/book/src/Qpid-JMX-Management-Console.xml delete mode 100644 doc/book/src/Qpid-Java-Broker-Management-CLI.xml delete mode 100644 doc/book/src/Qpid-Java-Build-How-To.xml delete mode 100644 doc/book/src/Qpid-Java-FAQ.xml delete mode 100644 doc/book/src/Qpid-Management-Features.xml delete mode 100644 doc/book/src/Qpid-Management-Framework.xml delete mode 100644 doc/book/src/Qpid-Troubleshooting-Guide.xml delete mode 100644 doc/book/src/Running-CPP-Broker.xml delete mode 100644 doc/book/src/SASL-Compatibility.xml delete mode 100644 doc/book/src/SSL.xml delete mode 100644 doc/book/src/Security-Plugins.xml delete mode 100644 doc/book/src/Security.xml delete mode 100644 doc/book/src/Starting-a-cluster.xml delete mode 100644 doc/book/src/System-Properties.xml delete mode 100644 doc/book/src/Use-Priority-Queues.xml delete mode 100644 doc/book/src/Using-Broker-Federation.xml delete mode 100644 doc/book/src/Using-Qpid-with-other-JNDI-Providers.xml delete mode 100644 doc/book/src/Using-message-groups.xml delete mode 100644 doc/book/src/WCF.xml delete mode 100644 doc/book/src/amqp-advanced-message-queueing-protocol.html create mode 100644 doc/book/src/common/css/style.css create mode 100644 doc/book/src/cpp-broker/AMQP-Compatibility.xml create mode 100644 doc/book/src/cpp-broker/AMQP-Messaging-Broker-CPP-Book.xml create mode 100644 doc/book/src/cpp-broker/Active-Active-Cluster.xml create mode 100644 doc/book/src/cpp-broker/Active-Passive-Cluster.xml create mode 100644 doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Exchange-Options.xml create mode 100644 doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Queue-Options.xml create mode 100644 doc/book/src/cpp-broker/HA-Queue-Replication.xml create mode 100644 doc/book/src/cpp-broker/LVQ.xml create mode 100644 doc/book/src/cpp-broker/Makefile create mode 100644 doc/book/src/cpp-broker/Managing-CPP-Broker.xml create mode 100644 doc/book/src/cpp-broker/QMF-Python-Console-Tutorial.xml create mode 100644 doc/book/src/cpp-broker/Qpid-Interoperability-Documentation.xml create mode 100644 doc/book/src/cpp-broker/Qpid-Management-Framework.xml create mode 100644 doc/book/src/cpp-broker/Running-CPP-Broker.xml create mode 100644 doc/book/src/cpp-broker/Security.xml create mode 100644 doc/book/src/cpp-broker/Using-Broker-Federation.xml create mode 100644 doc/book/src/cpp-broker/Using-message-groups.xml create mode 100644 doc/book/src/cpp-broker/producer-flow-control.xml create mode 100644 doc/book/src/cpp-broker/queue-state-replication.xml delete mode 100644 doc/book/src/css/style.css delete mode 100644 doc/book/src/images/jmx_console/3113098.png delete mode 100644 doc/book/src/images/jmx_console/3113099.png delete mode 100644 doc/book/src/images/jmx_console/3113100.png delete mode 100644 doc/book/src/images/jmx_console/3113101.png delete mode 100644 doc/book/src/images/jmx_console/3113102.png delete mode 100644 doc/book/src/images/jmx_console/3113103.png delete mode 100644 doc/book/src/images/jmx_console/3113104.png delete mode 100644 doc/book/src/images/jmx_console/3113105.png delete mode 100644 doc/book/src/images/jmx_console/3113106.png delete mode 100644 doc/book/src/images/jmx_console/3113107.png delete mode 100644 doc/book/src/images/jmx_console/3113108.png delete mode 100644 doc/book/src/images/jmx_console/3113109.png delete mode 100644 doc/book/src/images/jmx_console/3113110.png delete mode 100644 doc/book/src/images/jmx_console/3113111.png delete mode 100644 doc/book/src/images/jmx_console/3113112.png delete mode 100644 doc/book/src/images/jmx_console/3113113.png delete mode 100644 doc/book/src/images/jmx_console/3113114.png delete mode 100644 doc/book/src/images/jmx_console/3113115.png delete mode 100644 doc/book/src/images/jmx_console/3113116.png delete mode 100644 doc/book/src/images/jmx_console/3113117.png delete mode 100644 doc/book/src/images/jmx_console/3113118.png delete mode 100644 doc/book/src/images/jmx_console/3113119.png create mode 100644 doc/book/src/java-broker/AMQP-Messaging-Broker-Java-Book.xml create mode 100644 doc/book/src/java-broker/Add-New-Users.xml create mode 100644 doc/book/src/java-broker/Broker-Configuration-Guide.xml create mode 100644 doc/book/src/java-broker/Configure-ACLs.xml create mode 100644 doc/book/src/java-broker/Configure-Java-Qpid-to-use-a-SSL-connection.xml create mode 100644 doc/book/src/java-broker/Configure-Log4j-CompositeRolling-Appender.xml create mode 100644 doc/book/src/java-broker/Configure-the-Broker-via-config.xml.xml create mode 100644 doc/book/src/java-broker/Configure-the-Virtual-Hosts-via-virtualhosts.xml.xml create mode 100644 doc/book/src/java-broker/Configuring-Management-Users.xml create mode 100644 doc/book/src/java-broker/Configuring-Qpid-JMX-Management-Console.xml create mode 100644 doc/book/src/java-broker/Debug-using-log4j.xml create mode 100644 doc/book/src/java-broker/How-to-Tune-M3-Java-Broker-Performance.xml create mode 100644 doc/book/src/java-broker/How-to-Use-SlowConsumerDisconnect.xml create mode 100644 doc/book/src/java-broker/Java-Broker-Feature-Guide.xml create mode 100644 doc/book/src/java-broker/Java-Environment-Variables.xml create mode 100644 doc/book/src/java-broker/Makefile create mode 100644 doc/book/src/java-broker/Management-Console-Security.xml create mode 100644 doc/book/src/java-broker/MessageStore-Tool.xml create mode 100644 doc/book/src/java-broker/Qpid-JMX-Management-Console-FAQ.xml create mode 100644 doc/book/src/java-broker/Qpid-JMX-Management-Console-User-Guide.xml create mode 100644 doc/book/src/java-broker/Qpid-JMX-Management-Console.xml create mode 100644 doc/book/src/java-broker/Qpid-Java-Broker-Management-CLI.xml create mode 100644 doc/book/src/java-broker/Qpid-Java-Build-How-To.xml create mode 100644 doc/book/src/java-broker/Qpid-Java-FAQ.xml create mode 100644 doc/book/src/java-broker/Qpid-Management-Features.xml create mode 100644 doc/book/src/java-broker/Qpid-Troubleshooting-Guide.xml create mode 100644 doc/book/src/java-broker/Topic-Configuration.xml create mode 100644 doc/book/src/java-broker/Use-Priority-Queues.xml create mode 100644 doc/book/src/java-broker/images/3113098.png create mode 100644 doc/book/src/java-broker/images/3113099.png create mode 100644 doc/book/src/java-broker/images/3113100.png create mode 100644 doc/book/src/java-broker/images/3113101.png create mode 100644 doc/book/src/java-broker/images/3113102.png create mode 100644 doc/book/src/java-broker/images/3113103.png create mode 100644 doc/book/src/java-broker/images/3113104.png create mode 100644 doc/book/src/java-broker/images/3113105.png create mode 100644 doc/book/src/java-broker/images/3113106.png create mode 100644 doc/book/src/java-broker/images/3113107.png create mode 100644 doc/book/src/java-broker/images/3113108.png create mode 100644 doc/book/src/java-broker/images/3113109.png create mode 100644 doc/book/src/java-broker/images/3113110.png create mode 100644 doc/book/src/java-broker/images/3113111.png create mode 100644 doc/book/src/java-broker/images/3113112.png create mode 100644 doc/book/src/java-broker/images/3113113.png create mode 100644 doc/book/src/java-broker/images/3113114.png create mode 100644 doc/book/src/java-broker/images/3113115.png create mode 100644 doc/book/src/java-broker/images/3113116.png create mode 100644 doc/book/src/java-broker/images/3113117.png create mode 100644 doc/book/src/java-broker/images/3113118.png create mode 100644 doc/book/src/java-broker/images/3113119.png delete mode 100644 doc/book/src/java/broker/configuration/Topic-Configuration.xml create mode 100644 doc/book/src/old/ACL.xml create mode 100644 doc/book/src/old/AMQP-.NET-Messaging-Client.xml create mode 100644 doc/book/src/old/AMQP-C++-Messaging-Client.xml create mode 100644 doc/book/src/old/AMQP-Java-JMS-Messaging-Client.xml create mode 100644 doc/book/src/old/AMQP-Messaging-Broker-CPP.xml create mode 100644 doc/book/src/old/AMQP-Python-Messaging-Client.xml create mode 100644 doc/book/src/old/AMQP-Ruby-Messaging-Client.xml create mode 100644 doc/book/src/old/AMQP.xml create mode 100644 doc/book/src/old/Binding-URL-Format.xml create mode 100644 doc/book/src/old/Book-Info.xml create mode 100644 doc/book/src/old/Book.xml create mode 100644 doc/book/src/old/Broker-CPP.xml create mode 100644 doc/book/src/old/Broker-Java.xml create mode 100644 doc/book/src/old/Clients.xml create mode 100644 doc/book/src/old/Connection-URL-Format.xml create mode 100644 doc/book/src/old/Download.xml create mode 100644 doc/book/src/old/Excel-AddIn.xml create mode 100644 doc/book/src/old/FAQ.xml create mode 100644 doc/book/src/old/Getting-Started.xml create mode 100644 doc/book/src/old/How-to-Use-JNDI.xml create mode 100644 doc/book/src/old/InfoPlugin.xml create mode 100644 doc/book/src/old/Introduction.xml create mode 100644 doc/book/src/old/Java-Broker-StatusLogMessages.xml create mode 100644 doc/book/src/old/Java-JMS-Selector-Syntax.xml create mode 100644 doc/book/src/old/Management-Design-notes.xml create mode 100644 doc/book/src/old/NET-User-Guide.xml create mode 100644 doc/book/src/old/PythonBrokerTest.xml create mode 100644 doc/book/src/old/QMan-Qpid-Management-bridge.xml create mode 100644 doc/book/src/old/Qpid-ACLs.xml create mode 100644 doc/book/src/old/Qpid-Book.xml create mode 100644 doc/book/src/old/Qpid-Compatibility-And-Interoperability-Book.xml create mode 100644 doc/book/src/old/SASL-Compatibility.xml create mode 100644 doc/book/src/old/SSL.xml create mode 100644 doc/book/src/old/Security-Plugins.xml create mode 100644 doc/book/src/old/System-Properties.xml create mode 100644 doc/book/src/old/Using-Qpid-with-other-JNDI-Providers.xml create mode 100644 doc/book/src/old/WCF.xml create mode 100644 doc/book/src/old/schemas.xml delete mode 100644 doc/book/src/producer-flow-control.xml create mode 100644 doc/book/src/programming/Makefile create mode 100644 doc/book/src/programming/Message-Groups-Guide.xml create mode 100644 doc/book/src/programming/Programming-In-Apache-Qpid-Book.xml create mode 100644 doc/book/src/qmf/QmfBook.xml create mode 100644 doc/book/src/qmf/QmfIntroduction.xml delete mode 100644 doc/book/src/queue-state-replication.xml delete mode 100644 doc/book/src/schemas.xml create mode 100644 doc/book/xsl/html-custom.xsl create mode 100644 java/.gitignore create mode 100644 java/amqp-1-0-client-jms/build.xml create mode 100644 java/amqp-1-0-client-jms/example/src/main/java/org/apache/qpid/amqp_1_0/jms/example/Hello.java create mode 100644 java/amqp-1-0-client-jms/example/src/main/java/org/apache/qpid/amqp_1_0/jms/example/hello.properties create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/AmqpMessage.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/BytesMessage.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/Connection.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/ConnectionFactory.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/ConnectionMetaData.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/Destination.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/JavaSerializable.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/MapMessage.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/Message.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/MessageConsumer.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/MessageProducer.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/ObjectMessage.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/Queue.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/QueueBrowser.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/QueueConnection.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/QueueReceiver.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/QueueSender.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/QueueSession.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/Session.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/StreamMessage.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TemporaryDestination.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TemporaryQueue.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TemporaryTopic.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TextMessage.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/Topic.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TopicConnection.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TopicPublisher.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TopicSession.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/TopicSubscriber.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/AmqpMessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/BytesMessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionMetaDataImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MapMessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageFactory.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueConnectionImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueSenderImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueSessionImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/StreamMessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TemporaryQueueImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TemporaryTopicImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TextMessageImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicConnectionImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicPublisherImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSessionImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/NameParserImpl.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/PropertiesFileInitialContextFactory.java create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/ReadOnlyContext.java create mode 100644 java/amqp-1-0-client/build.xml create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/AcknowledgeMode.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ReadBytes.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SendBytes.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Sender.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Transaction.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransactionController.java create mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java create mode 100644 java/amqp-1-0-common/build.xml create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/AbstractDescribedTypeWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/AbstractListWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/AbstractMapWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ArrayTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ArrayWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryString.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BooleanConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BooleanWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ByteArrayWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ByteBufferWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ByteTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ByteWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/CharTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/CharWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/CompoundTypeAssembler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/CompoundTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/CompoundWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DecimalConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DefaultDescribedTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DelegatingValueWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DescribedType.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DescribedTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DescribedTypeConstructorRegistry.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DoubleTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/DoubleWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/Encoder.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FixedEightWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FixedFourWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FixedOneWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FixedSixteenWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FixedTwoWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FloatTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FloatWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FrameWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/IntTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/IntegerWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ListWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/LongTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/LongWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/MapWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/NullTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/NullWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ProtocolHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ProtocolHeaderHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/RestrictedTypeValueWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ShortTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ShortWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SimpleVariableWidthWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SmallIntConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SmallLongConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SmallUIntConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SmallULongConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/StringTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/StringWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolArrayWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/TimestampTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/TimestampWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/TypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UByteTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UIntTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ULongTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UShortTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UUIDTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UUIDWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UnsignedByteWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UnsignedIntegerWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UnsignedLongWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/UnsignedShortWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ValueHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ValueProducingProtocolHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ValueWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/VariableWidthTypeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/VariableWidthWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/WrapperTypeValueWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ZeroListConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ZeroUIntConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/ZeroULongConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/AMQFrame.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/AMQPProtocolHeaderHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameParsingError.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameTypeHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/OversizeFrameException.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/SASLFrame.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/SASLFrameHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/SASLProtocolHeaderHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/TransportFrame.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/messaging/MessageAttributes.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/messaging/SectionDecoder.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/messaging/SectionDecoderImpl.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/messaging/SectionEncoder.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/messaging/SectionEncoderImpl.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/AMQPFrameTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/AMQPTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/BytesProcessor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/BytesTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CircularBytesBuffer.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEventListener.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionState.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Container.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Delivery.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/DeliveryStateHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ErrorHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/FrameOutputHandler.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/FrameTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/LinkEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/LinkEventListener.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Node.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ProtocolHeaderTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkListener.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingSessionHalfEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SASLEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SASLEndpointImpl.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SASLFrameTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SASLTransport.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingLinkEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingLinkListener.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingSessionHalfEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SequenceNumber.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionAttachment.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEventListener.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionHalfEndpoint.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionState.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/StateChangeListener.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/UnsettledTransfer.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/AmqpErrorException.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/Binary.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/DeliveryState.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/DistributionMode.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/ErrorCondition.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/FrameBody.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/GlobalTxId.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/LifetimePolicy.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/Outcome.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/RestrictedType.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/SaslFrameBody.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/Section.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/Source.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/Symbol.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/Target.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/TxnCapability.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/TxnId.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/UnsignedByte.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/UnsignedInteger.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/UnsignedLong.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/UnsignedShort.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/WrapperType.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/codec/AMQPDescribedTypeRegistry.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Accepted.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/AmqpSequence.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/AmqpValue.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/ApplicationProperties.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Data.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/DeleteOnClose.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/DeleteOnNoLinks.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/DeleteOnNoLinksOrMessages.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/DeleteOnNoMessages.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/DeliveryAnnotations.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/ExactSubjectFilter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Filter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Footer.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Header.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/JMSSelectorFilter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/MatchingSubjectFilter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/MessageAnnotations.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Modified.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/NoLocalFilter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Properties.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Received.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Rejected.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Released.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Source.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/StdDistMode.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/Target.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/TerminusDurability.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/TerminusExpiryPolicy.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/AcceptedConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/AcceptedWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/AmqpSequenceConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/AmqpSequenceWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/AmqpValueConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/AmqpValueWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ApplicationPropertiesConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ApplicationPropertiesWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DataConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DataWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnCloseConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnCloseWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnNoLinksConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnNoLinksOrMessagesConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnNoLinksOrMessagesWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnNoLinksWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnNoMessagesConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeleteOnNoMessagesWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeliveryAnnotationsConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/DeliveryAnnotationsWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ExactSubjectFilterConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ExactSubjectFilterWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/FooterConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/FooterWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/HeaderConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/HeaderWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/JMSSelectorFilterConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/JMSSelectorFilterWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/MatchingSubjectFilterConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/MatchingSubjectFilterWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/MessageAnnotationsConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/MessageAnnotationsWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ModifiedConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ModifiedWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/NoLocalFilterConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/NoLocalFilterWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/PropertiesConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/PropertiesWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ReceivedConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ReceivedWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/RejectedConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/RejectedWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ReleasedConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/ReleasedWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/SourceConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/SourceWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/TargetConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/messaging/codec/TargetWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/SaslChallenge.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/SaslCode.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/SaslInit.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/SaslMechanisms.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/SaslOutcome.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/SaslResponse.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslChallengeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslChallengeWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslInitConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslInitWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslMechanismsConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslMechanismsWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslOutcomeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslOutcomeWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslResponseConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/security/codec/SaslResponseWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/Coordinator.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/Declare.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/Declared.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/Discharge.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/TransactionErrors.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/TransactionalState.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/TxnCapabilities.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/TxnCapability.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/CoordinatorConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/CoordinatorWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/DeclareConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/DeclareWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/DeclaredConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/DeclaredWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/DischargeConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/DischargeWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/TransactionalStateConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transaction/codec/TransactionalStateWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/AmqpError.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Attach.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Begin.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Close.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/ConnectionError.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Detach.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Disposition.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/End.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Error.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Flow.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/LinkError.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Open.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/ReceiverSettleMode.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Role.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/SenderSettleMode.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/SessionError.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Transfer.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/AttachConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/AttachWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/BeginConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/BeginWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/CloseConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/CloseWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/DetachConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/DetachWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/DispositionConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/DispositionWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/EndConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/EndWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/ErrorConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/ErrorWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/FlowConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/FlowWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/OpenConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/OpenWriter.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/TransferConstructor.java create mode 100644 java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/codec/TransferWriter.java delete mode 100755 java/bdbstore/bin/storeUpgrade.sh delete mode 100755 java/bdbstore/etc/scripts/bdbtest.sh delete mode 100644 java/bdbstore/src/main/java/BDBStoreUpgrade.log4j.xml delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringTB.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgrade.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ContentTB.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/DatabaseVisitor.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ExchangeTB.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/MessageContentKey.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/QueueEntryKey.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StringMapBinding.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/UUIDTupleBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/PreparedTransaction.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/QueueEntryKey.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/Xid.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_4.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_5.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/BindingRecord.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/ExchangeRecord.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/QueueRecord.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ContentBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/QueueEntryBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/StringMapBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/UUIDTupleBinding.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/XidBinding.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTupleBindingFactory.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple_4.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_4.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_5.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTupleBindingFactory.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_4.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_5.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTupleBindingFactory.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTupleBindingFactory.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_4.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_5.java delete mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/TupleBindingFactory.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractStoreUpgrade.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorOperation.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseCallable.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseEntryCallback.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseRunnable.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplate.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionHandler.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionResponse.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplateTest.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java delete mode 100644 java/bdbstore/src/test/resources/upgrade/bdbstore-to-upgrade/test-store/00000000.jdb create mode 100644 java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb create mode 100644 java/bdbstore/src/test/resources/upgrade/bdbstore-v5/readme.txt create mode 100644 java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb create mode 100644 java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb delete mode 100644 java/broker-plugins/experimental/info/MANIFEST.MF delete mode 100644 java/broker-plugins/experimental/info/build.properties delete mode 100644 java/broker-plugins/experimental/info/build.xml delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Info.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoService.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoServiceImpl.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/SystemInfo.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/HttpPoster.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/IniFileReader.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/SoapClient.java delete mode 100644 java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/XMLWriter.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/HttpPosterTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServiceImplTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServlet.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/IniFileReaderTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SoapClientTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SystemInfoTest.java delete mode 100644 java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/XMLWriterTest.java delete mode 100644 java/broker/bin/create-example-ssl-stores.bat delete mode 100755 java/broker/bin/create-example-ssl-stores.sh create mode 100755 java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Binding.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Consumer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/IllegalStateTransitionException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/LifetimePolicy.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Publisher.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Queue.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/State.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java create mode 100755 java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/Event.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/EventListener.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/State.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/StoreFuture.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/Transaction.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/util/MapJsonSerializer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/EventManagerTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/util/MapJsonSerializerTest.java create mode 100644 java/client/src/test/java/org/apache/qpid/jndi/JNDITest.properties create mode 100644 java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java create mode 100644 java/client/src/test/java/org/apache/qpid/jndi/hello.properties delete mode 100644 java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDIPropertyFileTest.java delete mode 100644 java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDITest.properties delete mode 100644 java/integrationtests/README.txt delete mode 100755 java/integrationtests/bin/interoptests.py delete mode 100644 java/integrationtests/build.xml delete mode 100644 java/integrationtests/docs/RunningSustainedTests.txt delete mode 100644 java/integrationtests/jar-with-dependencies.xml delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase4P2PMessageSize.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase5PubSubMessageSize.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase4P2PMessageSize.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase5PubSubMessageSize.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java delete mode 100644 java/integrationtests/src/resources/sustained-log4j.xml delete mode 100644 java/jca/.gitignore create mode 100644 java/jca/example/README-EXAMPLE.txt create mode 100644 java/jca/example/README-GERONIMO.txt create mode 100644 java/jca/example/README-GLASSFISH.txt create mode 100644 java/jca/example/README-JBOSS.txt create mode 100644 java/jca/example/README-JBOSS7.txt delete mode 100644 java/jca/example/README.txt create mode 100644 java/jca/example/build-glassfish-properties.xml create mode 100644 java/jca/example/build-jboss7-properties.xml create mode 100644 java/jca/example/conf/glassfish-ejb-jar.xml create mode 100644 java/jca/example/conf/glassfish-resources.xml create mode 100644 java/jca/example/conf/glassfish-web.xml create mode 100644 java/jca/example/conf/jboss-ejb-client.properties create mode 100644 java/jca/example/conf/qpid-standalone.xml create mode 100644 java/jca/example/src/main/java/org/apache/qpid/jca/example/web/QpidRequestResponseServlet.java create mode 100644 java/jca/src/main/java/org/apache/qpid/ra/inflow/QpidExceptionHandler.java create mode 100644 java/jca/src/main/java/org/apache/qpid/ra/tm/GlassfishTransactionManagerLocator.java create mode 100644 java/jca/src/main/java/org/apache/qpid/ra/tm/WLSTransactionManagerLocator.java create mode 100644 java/jca/src/test/java/org/apache/qpid/ra/QpidActivationSpecTest.java create mode 100644 java/jca/src/test/java/org/apache/qpid/ra/QpidResourceAdapterTest.java delete mode 100644 java/junit-toolkit/build.xml delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/DefaultThreadFactory.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/PossibleDeadlockException.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/TestRunnable.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestExample.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/package.html delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestCase.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestDecorator.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BaseThrottle.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BatchedThrottle.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/InstrumentedTest.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/NullResultPrinter.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ParameterVariationTestDecorator.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskAware.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskHandler.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ShutdownHookable.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SleepThrottle.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestResult.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestRunner.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestThreadAware.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/Throttle.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingController.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingControllerAware.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/WrappedSuiteTestDecorator.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/CSVTestListener.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/ConsoleTestListener.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/TKTestListener.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/XMLTestListener.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/package.html delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/package.html delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/CommandLineParser.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ContextualProperties.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/MathUtils.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ParsedProperties.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/SizeOf.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/StackQueue.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestContextProperties.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestUtils.java delete mode 100644 java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/package.html create mode 100644 java/lib/gson-2.0.jar create mode 100644 java/lib/jackson-core-asl-1.9.0.jar create mode 100644 java/lib/jackson-mapper-asl-1.9.0.jar delete mode 100644 java/lib/jetty-6.1.14.jar delete mode 100644 java/lib/jetty-servlet-tester-6.1.14.jar delete mode 100644 java/lib/jetty-util-6.1.14.jar create mode 100644 java/lib/mockito-all-1.9.0.jar delete mode 100644 java/lib/org.apache.felix.framework-2.0.5.jar create mode 100644 java/lib/org.apache.felix.main-2.0.5.jar create mode 100644 java/lib/poms/jackson-core-asl-1.9.0.xml create mode 100644 java/lib/poms/jackson-mapper-asl-1.9.0.xml delete mode 100644 java/lib/poms/org.apache.felix.framework-2.0.5.xml create mode 100644 java/lib/poms/org.apache.felix.main-2.0.5.xml delete mode 100644 java/lib/poms/org.osgi.core-1.0.0.xml delete mode 100644 java/lib/servlet-api.jar delete mode 100644 java/perftests/RunningPerformanceTests.txt delete mode 100755 java/perftests/bin/monitoring/monitor-broker.sh delete mode 100755 java/perftests/bin/monitoring/runTests.sh delete mode 100755 java/perftests/bin/monitoring/stop-monitored-broker.sh delete mode 100755 java/perftests/bin/processing/process.sh delete mode 100755 java/perftests/bin/processing/processAll.sh delete mode 100755 java/perftests/bin/processing/processTests.py delete mode 100755 java/perftests/bin/run_many.sh delete mode 100755 java/perftests/bin/topicListener.sh delete mode 100755 java/perftests/bin/topicPublisher.sh delete mode 100644 java/perftests/dist-zip.xml create mode 100644 java/perftests/etc/chartdefs/AcknowledgementModesAutoAck.chartdef create mode 100644 java/perftests/etc/chartdefs/AcknowledgementModesTransacted.chartdef create mode 100644 java/perftests/etc/chartdefs/BatchSize.chartdef create mode 100644 java/perftests/etc/chartdefs/MessageSizeNonPersistent.chartdef create mode 100644 java/perftests/etc/chartdefs/MessageSizePersistent.chartdef create mode 100644 java/perftests/etc/chartdefs/QueueTypes.chartdef create mode 100644 java/perftests/etc/chartdefs/VaryingNumberOfConsumers.chartdef create mode 100644 java/perftests/etc/chartdefs/VaryingNumberOfProducers.chartdef delete mode 100644 java/perftests/etc/jndi/activemq.properties delete mode 100644 java/perftests/etc/jndi/failovertest.properties delete mode 100644 java/perftests/etc/jndi/perftests.properties delete mode 100644 java/perftests/etc/jndi/swiftmq.properties create mode 100644 java/perftests/etc/log4j.properties create mode 100644 java/perftests/etc/perftests-jndi.properties delete mode 100644 java/perftests/etc/perftests.log4j delete mode 100755 java/perftests/etc/scripts/CTQ-Qpid-1.sh delete mode 100755 java/perftests/etc/scripts/CTQ-Qpid-2.sh delete mode 100755 java/perftests/etc/scripts/CTQ-Qpid-3.sh delete mode 100755 java/perftests/etc/scripts/CTQ-Qpid-4.sh delete mode 100755 java/perftests/etc/scripts/CTQ-Qpid-5.sh delete mode 100755 java/perftests/etc/scripts/CTQ-Qpid-6.sh delete mode 100755 java/perftests/etc/scripts/Connections.sh delete mode 100755 java/perftests/etc/scripts/JobQueue.sh delete mode 100755 java/perftests/etc/scripts/Latency.sh delete mode 100755 java/perftests/etc/scripts/MessageSize.sh delete mode 100755 java/perftests/etc/scripts/PT-Qpid-13.sh delete mode 100755 java/perftests/etc/scripts/PT-Qpid-14.sh delete mode 100755 java/perftests/etc/scripts/Reliability.sh delete mode 100755 java/perftests/etc/scripts/RunAll.sh delete mode 100755 java/perftests/etc/scripts/RunCore.sh delete mode 100644 java/perftests/etc/scripts/Test-ActiveMQ.sh delete mode 100644 java/perftests/etc/scripts/Test-SwiftMQ.sh delete mode 100755 java/perftests/etc/scripts/Throughput.sh delete mode 100755 java/perftests/etc/scripts/drainBroker.sh delete mode 100755 java/perftests/etc/scripts/extractResults.sh delete mode 100755 java/perftests/etc/scripts/extractThroughputResults.sh delete mode 100755 java/perftests/etc/scripts/fillBroker.sh delete mode 100755 java/perftests/etc/scripts/sendAndWaitClient.sh delete mode 100755 java/perftests/etc/scripts/testWithPreFill.sh create mode 100644 java/perftests/etc/testdefs/short/AcknowledgementModes.json create mode 100644 java/perftests/etc/testdefs/short/BatchSize.json create mode 100644 java/perftests/etc/testdefs/short/MessageSize.json create mode 100644 java/perftests/etc/testdefs/short/QueueTypes.json create mode 100644 java/perftests/etc/testdefs/short/VaryingNumberOfParticipants.json create mode 100644 java/perftests/etc/testdefs/standard/AcknowledgementModes.json create mode 100644 java/perftests/etc/testdefs/standard/BatchSize.json create mode 100644 java/perftests/etc/testdefs/standard/MessageSize.json create mode 100644 java/perftests/etc/testdefs/standard/QueueTypes.json create mode 100644 java/perftests/etc/testdefs/standard/QueuesWithSelectors.json create mode 100644 java/perftests/etc/testdefs/standard/VaryingNumberOfParticipants.json create mode 100644 java/perftests/example/PQBT-AA-Qpid-01.json create mode 100644 java/perftests/example/TQBT-TX-Qpid-01.json create mode 100644 java/perftests/example/brokerconfig/log4j.xml create mode 100644 java/perftests/example/brokerconfig/passwd create mode 100644 java/perftests/example/brokerconfig/virtualhosts.xml create mode 100644 java/perftests/example/config-one-test.json create mode 100644 java/perftests/example/config-stress-testing-manyp-c1-with-psfc.json create mode 100644 java/perftests/example/config-stress-testing.json create mode 100644 java/perftests/example/config-two-tests.json create mode 100644 java/perftests/example/log4j-client.properties create mode 100644 java/perftests/example/log4j.properties create mode 100644 java/perftests/example/perftests-jndi.properties create mode 100755 java/perftests/example/run-client.sh create mode 100755 java/perftests/example/run.sh delete mode 100644 java/perftests/generate-scripts delete mode 100644 java/perftests/jar-with-dependencies.xml delete mode 100644 java/perftests/scripts.xml delete mode 100644 java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/config/Connector.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/config/ConnectorConfig.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/AbstractRunner.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/ClientRunner.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestException.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/Visitor.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientCommandVisitor.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientState.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/Participant.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutorRegistry.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertySupport.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertyValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/ListPropertyValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/NumericGeneratedPropertySupport.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValueFactory.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RandomPropertyValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RangePropertyValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/client/property/SimplePropertyValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandForClient.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandListener.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/ParticipatingClients.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestResult.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunnerFactory.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ClientConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/Config.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConnectionConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/IterationValue.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/MessageProviderConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/SessionConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestConfig.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestInstance.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/jms/JmsMessageAdaptor.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/json/JsonHandler.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/json/PropertyValueAdapter.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/Command.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CommandType.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConnectionCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateMessageProviderCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateProducerCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateResponderCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateSessionCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/NoOpCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/OutputAttribute.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttributeExtractor.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/RegisterClientCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/Response.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/StartTestCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/StopClientCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/message/TearDownTestCommand.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/AggregatedTestResult.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/Aggregator.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparator.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/oldtopic/Config.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/oldtopic/Listener.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/oldtopic/MessageFactory.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/oldtopic/Publisher.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/ping/PingAsyncTestPerf.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/topic/Config.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/topic/Listener.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/topic/MessageFactory.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/topic/Publisher.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/topic/TopicWithSelectorsTransientVolumeTest.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/topic/topicselectors.properties create mode 100644 java/perftests/src/main/resources/perftests.properties create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/ArgumentParserTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantTestHelper.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTestUtils.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/sampleConfig.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/DistributedTestSystemTestBase.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/BasicDistributedClientTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ConsumerParticipantTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/MessageProviderTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ProducerParticipantTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/iteratingFeature.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/produceClient.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndThreeConsumersInSeparateClients.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/testWithTwoTests.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/distributedControllerTest.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json create mode 100644 java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties create mode 100644 java/perftests/visualisation-jfc/build.xml create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingException.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java delete mode 100755 java/systests/etc/bin/testclients.sh create mode 100644 java/systests/src/main/java/org/apache/qpid/client/AsynchMessageListenerTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/client/SynchReceiveTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/ra/QpidRAConnectionTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/Assertion.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/AssertionBase.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/DropInTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/TestClientDetails.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchThread.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/LocalClockSynchronizer.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockReference.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockSynchronizer.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/package.html delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java delete mode 100644 java/testkit/README.txt delete mode 100644 java/testkit/bin/run_soak_client.sh delete mode 100644 java/testkit/bin/soak_report.sh delete mode 100644 java/testkit/build.xml delete mode 100644 java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java delete mode 100644 java/tools/bin/controller create mode 100755 java/tools/bin/jms-quick-perf-report create mode 100644 java/tools/bin/mercury-controller create mode 100644 java/tools/bin/mercury-start-consumers create mode 100644 java/tools/bin/mercury-start-producers delete mode 100755 java/tools/bin/perf-report delete mode 100644 java/tools/bin/start-consumers delete mode 100644 java/tools/bin/start-producers create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java delete mode 100644 java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/MercuryBase.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/MercuryConsumerController.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/MercuryProducerController.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/MercuryTestController.java delete mode 100644 java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java delete mode 100644 java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java delete mode 100644 java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java delete mode 100644 java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java delete mode 100644 java/tools/src/main/java/org/apache/qpid/tools/TestParams.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/report/BasicReporter.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/report/MercuryReporter.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/report/Reporter.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java create mode 100644 specs/amqp.xsl create mode 100644 specs/apache-filters.xml create mode 100755 tools/src/py/qpid-ha delete mode 100755 tools/src/py/qpid-ha-tool diff --git a/QPID_VERSION.txt b/QPID_VERSION.txt index 2856407c03..50653ad0a6 100644 --- a/QPID_VERSION.txt +++ b/QPID_VERSION.txt @@ -1 +1 @@ -0.15 +0.17 diff --git a/bin/install-cpp-python b/bin/install-cpp-python new file mode 100755 index 0000000000..d43e8e4899 --- /dev/null +++ b/bin/install-cpp-python @@ -0,0 +1,76 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +# +# Install C++ build and python tools to the standard places in a Unix buld +# WARNING: Will destroy any existing installation! +# + +# NOTE: build must be configured like this: +# ../qpid/cpp/configure --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64 +# NOTE: Must run as root. + +usage() { + cat < +-p : Prefix to install python +-s : Skip C++ installation +EOF + + exit 1 +} + +fail() { echo $*; exit 1; } + +while getopts "ps" opt; do + case $opt in + p) PY_PREFIX="--prefix $OPTARG";; + s) SKIP_CPP=1;; + *) usage;; + esac +done +shift `expr $OPTIND - 1` +BUILD=$1 +SRC=$(dirname $0)/.. + +# Install python +cd $SRC || fail "No such directory: $SRC" +for d in python tools extras/qmf; do + ( + cd $d || fail "No such directory: $(pwd)/$d" + ./setup.py install || fail Python install failed in $(pwd) + ) +done + +if test $SKIP_CPP; then exit; fi + +test -n "$BUILD" || { echo "No build directory."; usage; } +test -d "$BUILD" || fail "No such directory: $BUILD" +SRC=$(dirname $BUILD) + + # Install C++ +cd $BUILD +make -j1 install || fail "C++ install failed in $BUILD" + +# NOTE: setup.py does not uninstall, but you can get a list of files installed with: +# setup.py install --record + + diff --git a/cc/LICENSE b/cc/LICENSE deleted file mode 100644 index bc46b77047..0000000000 --- a/cc/LICENSE +++ /dev/null @@ -1,206 +0,0 @@ -========================================================================= -== Apache License == -========================================================================= - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/cc/NOTICE b/cc/NOTICE deleted file mode 100644 index 05f39ba176..0000000000 --- a/cc/NOTICE +++ /dev/null @@ -1,8 +0,0 @@ -// ------------------------------------------------------------------ -// NOTICE file corresponding to the section 4d of The Apache License, -// Version 2.0, in this case for Qpid bin scripts -// ------------------------------------------------------------------ - -Apache Qpid -Copyright 2006-2008 Apache Software Foundation - diff --git a/cc/README.txt b/cc/README.txt deleted file mode 100644 index 8d1286f6d7..0000000000 --- a/cc/README.txt +++ /dev/null @@ -1,84 +0,0 @@ -****************** -Prerequisites -****************** -Check out the source -see http://cwiki.apache.org/qpid/building.html - -****************** -Install CruiseControl -****************** - -Download CruiseControl from: http://cruisecontrol.sourceforge.net/ - - * Unzip the release to a directory, for example ~/cruisecontrol-bin-2.7.2 - * Check that the scripts cruisecontrol-bin-2.7.2/cruisecontrol.sh and cruisecontrol-bin-2.7.2/apache-ant-1.7.0/bin/ant have execution permission. - * Make sure your directory ~/.ant/lib contains the following jars: - o The ant jar files that can be found in cruisecontrol-bin-2.7.2/apache-ant-1.7.0/lib/ - o xalan-2.7.0.jar - -****************** -Set system variables -****************** - -Prior to use CruiseControl you'll need to set three system variables: -Variable Value -CC_HOME path to your qpid project, for example /home/foo/projects/qpid -CPPSTORE_HOME path to your C++ store, for example /home/foo/projects/bdbstore-cpp -NANT_HOME path to the nant directory -- only required for .net client -- - (nant can be downloaded from http://nant.sourceforge.net/) - -Edit the file CC_HOME/config.properties and set the properties so to match your system requirements. -Notes - * the cpp store can be checked out from: https://svn.jboss.org/repos/rhmessaging/store/trunk/cpp - * Only unix scrips are currently provided - * - - -****************** -Installing Mono -****************** -For building the .net client on a Linux platform you need to install Mono. -Mono website is: http://www.mono-project.com/Main_Page -Here are the instruction for a RHEL5 platform: - -Create the file "/etc/yum.repos.d/mono.repo" and add the following lines: - -[Mono] -name=Mono Stack (RHEL_5) -type=rpm-md -baseurl=http://download.opensuse.org/repositories/Mono/RHEL_5/ -gpgcheck=1 -gpgkey=http://download.opensuse.org/repositories/Mono/RHEL_5/repodata/repomd.xml.key -enabled=1 - -Enter the following command to install Mono: - -# yum install mono-complete - - -****************** -Running CruiseControl -****************** - -Run cruisecontrol-bin-2.7.2/cruisecontrol.sh from CC_HOME/cc - -****************** -Running the Sun java TCK -****************** - -If you wish to run the Sun JMS TCK, follow those two steps: -* Extract the TCK -* (As required by the TCK) Set TS_HOME to the location where the JMS TCK has been installed. - -****************** -Projects -****************** - -Project Description -qpid-cpp-trunk Builds and tests the C++ broker -qpid-cpp-trunk-perftests Runs the C++ performance tests -qpid-java-trunk Builds and runs the Java tests with an 0.8 inVM broker, a c++ broker without prefetch and a c++ broker with pre-fetch -bdbstore-cpp-trunk Builds the C++ store (required for the Java tests) -example-automation Runs all the example combinations for python, C++ and java -java-perftests Runs the java performance tests -java-jmstck Runs the java jms tck (see running the tck) \ No newline at end of file diff --git a/cc/config.properties b/cc/config.properties deleted file mode 100644 index 82329722cc..0000000000 --- a/cc/config.properties +++ /dev/null @@ -1,25 +0,0 @@ -# -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# - -mail.subject=CC Report for -mail.host=localhost -mail.returnaddress=my-email -mail.list=list diff --git a/cc/config.xml b/cc/config.xml deleted file mode 100644 index ba89acc511..0000000000 --- a/cc/config.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/bdbstore-cpp-trunk.xml b/cc/config/bdbstore-cpp-trunk.xml deleted file mode 100644 index 254af62170..0000000000 --- a/cc/config/bdbstore-cpp-trunk.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/cpp-perftests.xml b/cc/config/cpp-perftests.xml deleted file mode 100644 index 8a5079b60b..0000000000 --- a/cc/config/cpp-perftests.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/cpp-trunk.xml b/cc/config/cpp-trunk.xml deleted file mode 100644 index 56e1d2bb54..0000000000 --- a/cc/config/cpp-trunk.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/dotnet-trunk.xml b/cc/config/dotnet-trunk.xml deleted file mode 100644 index 0d922967e4..0000000000 --- a/cc/config/dotnet-trunk.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/example-automation.xml b/cc/config/example-automation.xml deleted file mode 100644 index 52dd135c24..0000000000 --- a/cc/config/example-automation.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/java-jmstck.xml b/cc/config/java-jmstck.xml deleted file mode 100644 index 2b10b0c5b5..0000000000 --- a/cc/config/java-jmstck.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/java-perftests.xml b/cc/config/java-perftests.xml deleted file mode 100644 index 45e1b14b9f..0000000000 --- a/cc/config/java-perftests.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/java-trunk.xml b/cc/config/java-trunk.xml deleted file mode 100644 index 99f469725b..0000000000 --- a/cc/config/java-trunk.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cc/config/java/cpp.noprefetch.testprofile b/cc/config/java/cpp.noprefetch.testprofile deleted file mode 100644 index 07c158dd4e..0000000000 --- a/cc/config/java/cpp.noprefetch.testprofile +++ /dev/null @@ -1,22 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -broker.version=0-10 -broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --load-module store_home/lib/.libs/libbdbstore.so --auth no --no-module-dir -max_prefetch=0 -test.excludesfile=${project.root}/010ExcludeList-noPrefetch diff --git a/cc/config/java/cpp.testprofile b/cc/config/java/cpp.testprofile deleted file mode 100644 index 28361c6b40..0000000000 --- a/cc/config/java/cpp.testprofile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -broker.version=0-10 -broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --load-module store_home/lib/.libs/libbdbstore.so --auth no --no-module-dir -test.excludesfile=${project.root}/010ExcludeList-store diff --git a/cc/config/java/jndi.properties b/cc/config/java/jndi.properties deleted file mode 100644 index 9340163622..0000000000 --- a/cc/config/java/jndi.properties +++ /dev/null @@ -1,42 +0,0 @@ -# -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# - -java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory - -connectionfactory.QueueConnectionFactory = amqp://username:password@topicClientid/test?brokerlist='tcp://localhost:qpid_port' -connectionfactory.TopicConnectionFactory = amqp://username:password@topicClientid/test?brokerlist='tcp://localhost:qpid_port' -connectionfactory.jms/DURABLE_SUB_CONNECTION_FACTORY = amqp://username:password@duralbeTopicClientid/test?brokerlist='tcp://localhost:qpid_port' -connectionfactory.jms/MyTopicConnectionFactory = amqp://username:password@myTopicClientid/test?brokerlist='tcp://localhost:qpid_port' -connectionfactory.jms/TopicConnectionFactory = amqp://username:password@jmsTopicClientid/test?brokerlist='tcp://localhost:qpid_port' - -queue.MY_QUEUE=MY_QUEUE -queue.MY_QUEUE2=MY_QUEUE2 -queue.testQ0=testQ0 -queue.testQ1=testQ1 -queue.testQ2=testQ2 -queue.testQueue2=testQueue2 -queue.Q2=Q2 - -topic.MY_TOPIC=MY_TOPIC -topic.MY_TOPIC1=MY_TOPIC1 - -destination.direct = direct://amq.direct//directQueue - diff --git a/cc/dashboard-config.xml b/cc/dashboard-config.xml deleted file mode 100644 index 9304322853..0000000000 --- a/cc/dashboard-config.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - diff --git a/cc/scripts/bdbstorecppbuild.sh b/cc/scripts/bdbstorecppbuild.sh deleted file mode 100755 index 3385c8d2f4..0000000000 --- a/cc/scripts/bdbstorecppbuild.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -if [ -f Makefile ]; then - make distclean -fi - ./bootstrap && ./configure CXXFLAGS="-O3 -DNDEBUG" --with-qpid-checkout=$CC_HOME && make diff --git a/cc/scripts/build.xml b/cc/scripts/build.xml deleted file mode 100644 index 2144020017..0000000000 --- a/cc/scripts/build.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - diff --git a/cc/scripts/check_examples.sh b/cc/scripts/check_examples.sh deleted file mode 100755 index c10936b36c..0000000000 --- a/cc/scripts/check_examples.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -runVerifyScript() -{ - echo "------------------------" - $CC_HOME/cc/scripts/verify_all - echo "-----------------------" - echo "" -} - -cleanup() -{ -rm -f $CC_HOME/script.log -rm -f $CC_HOME/status.log -rm -f $CC_HOME/broker.log -} - -checkErrors() -{ -if test `cat $CC_HOME/script.log | grep -c 'FAIL'` -gt 0 -then - echo "FAILED" - printErrors > $CC_HOME/status.log -fi -} - -printErrors(){ - echo "The following scripts had failures" - cat CC_HOME/script.log | awk '{ - script = "" - while ((getline) == 1) - { - if ($1 == "script:") - { - script = $0 - } - if ($1 == "FAIL") - { - print substr(script,9) - } - }}' - echo "" -} - -echo "*************************************" -echo "Example Automation " -echo "" -cleanup -runVerifyScript -checkErrors -echo "*************************************" diff --git a/cc/scripts/cppbuild-perftests.sh b/cc/scripts/cppbuild-perftests.sh deleted file mode 100755 index 782a472175..0000000000 --- a/cc/scripts/cppbuild-perftests.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -cd $CC_HOME/cpp -svn stat --no-ignore | awk '/^[I?]/{print $2}' | xargs rm -r -./bootstrap && ./configure CXXFLAGS="-O3 -DNDEBUG" && make -j4 all && cd src/tests && make -j4 check diff --git a/cc/scripts/cppbuild.sh b/cc/scripts/cppbuild.sh deleted file mode 100755 index b63feb7141..0000000000 --- a/cc/scripts/cppbuild.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -x -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -make distclean && ./bootstrap && ./configure && make \ No newline at end of file diff --git a/cc/scripts/dotnetbuild.sh b/cc/scripts/dotnetbuild.sh deleted file mode 100644 index 51d2110757..0000000000 --- a/cc/scripts/dotnetbuild.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -x -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -mono $NANT_HOME/bin/NAnt.exe test \ No newline at end of file diff --git a/cc/scripts/javaconfig.sh b/cc/scripts/javaconfig.sh deleted file mode 100755 index 7a1a3a1a7d..0000000000 --- a/cc/scripts/javaconfig.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -# copy the profiles -sed "s#store_home#$CPPSTORE_HOME#g" $CC_HOME/cc/config/java/cpp.noprefetch.testprofile > "$CC_HOME/java/"/cpp.noprefetch.testprofile -sed "s#store_home#$CPPSTORE_HOME#g" $CC_HOME/cc/config/java/cpp.testprofile > "$CC_HOME/java"/cpp.testprofile -QPID_JARS=`find "$CC_HOME/java/build/lib" -name '*.jar' | tr '\n' ":"` -QPID_JARS=local.classes=$QPID_JARS -sed "s#local.classes=.*#$QPID_JARS#g" $TS_HOME/bin/build.properties > "$TS_HOME/bin"/build.properties-new -mv $TS_HOME/bin/build.properties-new $TS_HOME/bin/build.properties \ No newline at end of file diff --git a/cc/scripts/javajmstck.sh b/cc/scripts/javajmstck.sh deleted file mode 100644 index 9d279ed38e..0000000000 --- a/cc/scripts/javajmstck.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -cleanup(){ - echo "kill any existing broker instance" - stopBroker - rm -rf $CC_HOME/jmstck-data/* -} - -runBroker(){ - echo "******************************************************" - echo "Starting C++ broker" - ulimit -c unlimited - $CC_HOME/cpp/src/qpidd -t -d --data-dir $CC_HOME/jmstck-data --load-module=$CPPSTORE_HOME/lib/.libs/libbdbstore.so --port 0 --auth no --log-output $CC_HOME/jmstck-broker.log --no-module-dir - export QPID_PORT=`grep "Listening on TCP port" $CC_HOME/jmstck-broker.log | tail -n 1 | awk '{print $8}'` - echo " broker running on port: " $QPID_PORT - echo "******************************************************" - sed "s/qpid_port/$QPID_PORT/g" $CC_HOME/cc/config/java/jndi.properties > "$TS_HOME/classes"/jndi.properties -} - -runTck(){ - echo "******************************************************" - echo "Starting the TCK for the $1 iteration" - echo "******************************************************" - cd $TS_HOME/bin - $TS_HOME/bin/tsant runclient -Dwork.dir=work -Dreport.dir=report 2&>1 > $TS_HOME/tck$1.log - echo "******************************************************" - echo "TCK finished the $1 iteration" - echo "******************************************************" -} - -printResults(){ - TESTS_STR=`grep -a "\[java\] Completed running [0-9]* tests" $TS_HOME/tck$1.log` - PASSED_STR=`grep -a "\[java\] Number of Tests Passed =" $TS_HOME/tck$1.log` - FAILED_STR=`grep -a "Some tests did not pass" $TS_HOME/tck$1.log` - echo "-----------------------------------------" - echo "TCK run #$1 results:" - echo $TESTS_STR - echo $PASSED_STR - echo $FAILED_STR - if [ "$FAILED_STR" != "" ]; then - echo "SOME TCK FAILURES DETECTED: " - fi - echo "------------------------------------------" -} - -stopBroker(){ - echo "************************" - echo "Stopping the C++ broker" - echo "************************" - $CC_HOME/cpp/src/qpidd -q -p $QPID_PORT -} - -cleanup -counter=0 -runBroker -for j in 1 2 -do - counter=`expr $counter + 1` - runTck $counter - printResults $counter -done -cleanup diff --git a/cc/scripts/javareport.sh b/cc/scripts/javareport.sh deleted file mode 100755 index 2b2469d31d..0000000000 --- a/cc/scripts/javareport.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### -cd "$CC_HOME/java/build" -pwd -if [[ -d report_$1 ]]; then rm -fr report_$1; fi -if [[ -d report ]]; then mv report report_$1; fi -rm -rf ./results/* -rm -rf ./data/* \ No newline at end of file diff --git a/cc/scripts/runbroker.sh b/cc/scripts/runbroker.sh deleted file mode 100644 index 43d9b39056..0000000000 --- a/cc/scripts/runbroker.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -cleanup() -{ - echo "******************************************************" - echo "Cleanup" - echo "******************************************************" - for PID in `ps aux | grep 'qpidd'|grep 'broker.log'|grep -v 'grep'|awk '{ print $2 }'` - do - kill -9 $PID - done -} - -run_broker() -{ - echo "******************************************************" - echo "Starting C++ broker" - echo "******************************************************" - echo "" - $CC_HOME/cpp/src/qpidd -t -d --auth no --no-data-dir --log-output $CC_HOME/broker.log -} - -cleanup -run_broker \ No newline at end of file diff --git a/cc/scripts/stopbroker.sh b/cc/scripts/stopbroker.sh deleted file mode 100644 index f5839e141f..0000000000 --- a/cc/scripts/stopbroker.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - - -stop_broker() -{ - echo "******************************************************" - echo "Stopping the C++ broker" - echo "******************************************************" - echo "" - $CC_HOME/cpp/src/qpidd -q -} - -stop_broker \ No newline at end of file diff --git a/cc/scripts/verify b/cc/scripts/verify deleted file mode 100755 index 35191b17c9..0000000000 --- a/cc/scripts/verify +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/sh -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -export DOTNET_EXAMPLES=$CC_HOME/dotnet/client-010/bin/mono-2.0/debug -export CLASSPATH=`find "$CC_HOME/java/build/lib" -name '*.jar' | tr '\n' ":"` -export CPP=$CC_HOME/cpp/examples -export JAVA=$CC_HOME/java/client/example/src/main/java -export PYTHONPATH=$CC_HOME/python/ -export PYTHON_EXAMPLES=$CC_HOME/python/examples - -cleanup() { - test -n "$QPIDD" && $QPIDD -q # Private broker - kill %% > /dev/null 2>&1 # Leftover background jobs -} - -trap cleanup EXIT - -ARGS="${QPID_HOST:-localhost} $QPID_PORT" - -outfile() { - file=$1 - while [ -f $file.out ]; do file="${file}X"; done - echo $file.out - } - -fail() { test -n "$*" && echo $* 1>&2 ; FAIL=1; return 1; } - -client() -{ - "$@" $ARGS > `outfile $*` || fail; -} - -clients() { for cmd in "$@"; do client $cmd; done; } - -waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; } - -background() { - pattern=$1; shift - out=`outfile $*` - eval "$* $ARGS > $out &" || { fail; return 1; } - waitfor $out "$pattern" -} - -name() { - for x in $*; do name="$name `basename $x`"; done - echo $name; -} - -outputs() { - wait 2> /dev/null # Wait for all backgroud processes to complete - rm -f $script.out - for f in "$@"; do - { echo "==== `name $f`"; eval "cat $f"; } >> $script.out || fail - rm -rf `echo $f| awk '{ print $1 }'` - done -} - -verify() { - FAIL= - if [ -d $1 ]; then dir=$1; script=verify; - else dir=`dirname $1`; script=`basename $1`; fi - cd $dir || return 1 - rm -f *.out - echo "Running: $dir/$script" - { source ./$script && diff -ac $script.out $script.in ; } || fail - test -z "$FAIL" && rm -f *.out - return $FAIL -} - -HEX="[a-fA-F0-9]" -remove_uuid() { - sed "s/$HEX\{8\}-$HEX\{4\}-$HEX\{4\}-$HEX\{4\}-$HEX\{12\}//g" $* -} -remove_uuid64() { - sed 's/[-A-Za-z0-9_]\{22\}==//g' $* -} - - -for example in "$@"; do - echo "Running: $example " - if ( verify $example; ) then echo "PASS"; else echo "FAIL"; RET=1; fi - done -exit $RET diff --git a/cc/scripts/verify_all b/cc/scripts/verify_all deleted file mode 100755 index 8d3ec669a7..0000000000 --- a/cc/scripts/verify_all +++ /dev/null @@ -1,166 +0,0 @@ -#!/bin/sh -########################################################### -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -#http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. -########################################################### - -cleanup() -{ - echo "******************************************************" - echo "Cleanup" - echo "******************************************************" - for PID in `ps aux | grep 'qpidd'|grep 'broker.log'|grep -v 'grep'|awk '{ print $2 }'` - do - kill -9 $PID - done -} - -run_broker() -{ - echo "******************************************************" - echo "Starting C++ broker" - echo "******************************************************" - echo "" - $CC_HOME/cpp/src/qpidd -t -d --auth no --no-data-dir --log-to-file $CC_HOME/broker.log -} - -stop_broker() -{ - echo "******************************************************" - echo "Stopping the C++ broker" - echo "******************************************************" - echo "" - $CC_HOME/cpp/src/qpidd -q -} - -verify() -{ - #echo "arg " $2 " path: " $1 - for dir in $(find $1 -mindepth 1 -maxdepth 1 -type d -not -name '*.svn' -not -name $3 ) - do - echo $dir - for script in $(find $dir -mindepth 1 -maxdepth 1 -type f -name $2 -not -name '*.*') - do - # echo "script:" $script - cleanup - run_broker - $CC_HOME/cc/scripts/verify $script >> $CC_HOME/script.log 2>&1 - killall 'verify' - stop_broker - done -done -} - -run_python_python() -{ -echo "--------------------" -verify $CC_HOME/python/examples "verify" "xml-exchange" -echo "--------------------" -echo "" -} - - -run_cpp_cpp() -{ -echo "--------------------" -verify $CC_HOME/cpp/examples "verify" "*.svn" -echo "-------------------" -echo "" -} - -run_python_cpp_comb() -{ -echo "--------------------" -verify $CC_HOME/cpp/examples "verify_cpp_python" "*.svn" -verify $CC_HOME/cpp/examples "verify_python_cpp" "*.svn" -echo "-------------------" -echo "" -} - - -run_java_java() -{ -echo "--------------------" -verify $CC_HOME/java/client/example/src/main/java/org/apache/qpid/example/jmsexample "verify" "*.svn" -echo "-------------------" -echo "" -} - -run_java_cpp_comb() -{ -echo "--------------------" -verify $CC_HOME/java/client/example/src/main/java/org/apache/qpid/example/jmsexample "verify_java_cpp" "*.svn" -verify $CC_HOME/java/client/example/src/main/java/org/apache/qpid/example/jmsexample "verify_cpp_java" "*.svn" -echo "-------------------" -echo "" -} - -run_java_python_comb() -{ -echo "--------------------" -verify $CC_HOME/java/client/example/src/main/java/org/apache/qpid/example/jmsexample "verify_java_python" "*.svn" -verify $CC_HOME/java/client/example/src/main/java/org/apache/qpid/example/jmsexample "verify_python_java" "*.svn" -echo "-------------------" -echo "" -} - -run_dotnet_dotnet() -{ -echo "--------------------" -verify $CC_HOME/dotnet/client-010/examples/ "verify" "*.svn" -echo "-------------------" -echo "" -} - -run_cpp_dotnet() -{ -echo "--------------------" -verify $CC_HOME/dotnet/client-010/examples/ "verify_cpp_dotnet" "*.svn" -verify $CC_HOME/dotnet/client-010/examples/ "verify_dotnet_cpp" "*.svn" -echo "-------------------" -echo "" -} - -run_java_dotnet() -{ -echo "--------------------" -verify $CC_HOME/dotnet/client-010/examples/ "verify_java_dotnet" "*.svn" -verify $CC_HOME/dotnet/client-010/examples/ "verify_dotnet_java" "*.svn" -echo "-------------------" -echo "" -} - -run_python_dotnet() -{ -echo "--------------------" -verify $CC_HOME/dotnet/client-010/examples/ "verify_python_dotnet" "*.svn" -verify $CC_HOME/dotnet/client-010/examples/ "verify_dotnet_python" "*.svn" -echo "-------------------" -echo "" -} - - -run_python_python -run_python_cpp_comb -run_cpp_cpp -run_java_java -run_java_cpp_comb -run_java_python_comb -run_dotnet_dotnet -run_cpp_dotnet -run_java_dotnet -run_python_dotnet \ No newline at end of file diff --git a/cpp/bindings/qmf/ruby/qmf.rb b/cpp/bindings/qmf/ruby/qmf.rb index 34d3255d8d..9fbd50cbf6 100644 --- a/cpp/bindings/qmf/ruby/qmf.rb +++ b/cpp/bindings/qmf/ruby/qmf.rb @@ -26,18 +26,28 @@ module Qmf # Pull all the TYPE_* constants into Qmf namespace. Maybe there's an easier way? Qmfengine.constants.each do |c| + c = c.to_s if c.index('TYPE_') == 0 or c.index('ACCESS_') == 0 or c.index('DIR_') == 0 or c.index('CLASS_') == 0 or c.index('SEV_') == 0 const_set(c, Qmfengine.const_get(c)) end end + module StringHelpers + def ensure_encoding(str) + enc = (Encoding.default_external.name || "UTF-8" rescue "UTF-8") + str.respond_to?(:force_encoding) ? str.force_encoding(enc) : str + end + end + class Util + include StringHelpers + def qmf_to_native(val) case val.getType when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint when TYPE_UINT64 then val.asUint64 - when TYPE_SSTR, TYPE_LSTR then val.asString + when TYPE_SSTR, TYPE_LSTR then ensure_encoding(val.asString) when TYPE_ABSTIME then val.asInt64 when TYPE_DELTATIME then val.asUint64 when TYPE_REF then ObjectId.new(val.asObjectId) @@ -161,6 +171,7 @@ module Qmf ##============================================================================== class ConnectionSettings + include StringHelpers attr_reader :impl def initialize(url = nil) @@ -192,7 +203,7 @@ module Qmf def get_attr(key) _v = @impl.getAttr(key) if _v.isString() - return _v.asString() + return ensure_encoding(_v.asString()) elsif _v.isUint() return _v.asUint() elsif _v.isBool() @@ -348,7 +359,7 @@ module Qmf @broker = kwargs[:broker] if kwargs.include?(:broker) @allow_sets = :true - if cls: + if cls @event_class = cls @impl = Qmfengine::Event.new(@event_class.impl) elsif kwargs.include?(:impl) @@ -434,7 +445,7 @@ module Qmf @allow_sets = :false @broker = kwargs[:broker] if kwargs.include?(:broker) - if cls: + if cls @object_class = cls @impl = Qmfengine::Object.new(@object_class.impl) elsif kwargs.include?(:impl) @@ -707,6 +718,8 @@ module Qmf end class MethodResponse + include StringHelpers + def initialize(impl) @impl = Qmfengine::MethodResponse.new(impl) end @@ -720,7 +733,7 @@ module Qmf end def text - exception.asString + ensure_encoding(exception.asString) end def args @@ -885,6 +898,7 @@ module Qmf end class SchemaClassKey + include StringHelpers attr_reader :impl def initialize(i) @impl = Qmfengine::SchemaClassKey.new(i) @@ -899,7 +913,7 @@ module Qmf end def to_s - @impl.asString + ensure_encoding(@impl.asString) end end diff --git a/cpp/bindings/qmf/tests/run_interop_tests b/cpp/bindings/qmf/tests/run_interop_tests index 83e7f2593b..c370f211af 100755 --- a/cpp/bindings/qmf/tests/run_interop_tests +++ b/cpp/bindings/qmf/tests/run_interop_tests @@ -24,6 +24,7 @@ MY_DIR=`dirname \`which $0\`` QPID_DIR=${MY_DIR}/../../../.. BUILD_DIR=../../.. PYTHON_DIR=${QPID_DIR}/python +TOOLS_PY_DIR=${QPID_DIR}/tools/src/py QMF_DIR=${QPID_DIR}/extras/qmf QMF_DIR_PY=${QMF_DIR}/src/py BROKER_DIR=${BUILD_DIR}/src @@ -68,7 +69,7 @@ TESTS_FAILED=0 if test -d ${PYTHON_DIR} ; then start_broker echo "Running qmf interop tests using broker on port $BROKER_PORT" - PYTHONPATH=${PYTHON_DIR}:${QMF_DIR_PY}:${MY_DIR} + PYTHONPATH=${PYTHON_DIR}:${QMF_DIR_PY}:${MY_DIR}:${TOOLS_PY_DIR} export PYTHONPATH if test -d ${PYTHON_LIB_DIR} ; then diff --git a/cpp/bindings/qpid/Makefile.am b/cpp/bindings/qpid/Makefile.am index eaf45c2076..ae81696f27 100644 --- a/cpp/bindings/qpid/Makefile.am +++ b/cpp/bindings/qpid/Makefile.am @@ -35,7 +35,7 @@ if HAVE_PERL_DEVEL INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -I$(PERL_INC) -EXTRA_DIST += perl/perl.i +EXTRA_DIST += perl/perl.i perl/CMakeLists.txt BUILT_SOURCES = perl/cqpid_perl.cpp SWIG_FLAGS = -w362,401 diff --git a/cpp/bindings/qpid/dotnet/Makefile.am b/cpp/bindings/qpid/dotnet/Makefile.am index f212a37bbe..82ae315578 100644 --- a/cpp/bindings/qpid/dotnet/Makefile.am +++ b/cpp/bindings/qpid/dotnet/Makefile.am @@ -80,7 +80,6 @@ EXTRA_DIST = configure-windows.ps1 \ examples/msvc9/csharp.map.callback.sender/csharp.map.callback.sender.csproj \ examples/msvc9/csharp.map.receiver/csharp.map.receiver.csproj \ examples/msvc9/csharp.map.sender/csharp.map.sender.csproj \ - extra_dist.txt \ Makefile.am \ msvc10/org.apache.qpid.messaging.sessionreceiver.sln \ msvc10/org.apache.qpid.messaging.sln \ @@ -93,7 +92,6 @@ EXTRA_DIST = configure-windows.ps1 \ src/AssemblyInfo.cpp \ src/Connection.cpp \ src/Connection.h \ - src/Duration.cpp \ src/Duration.h \ src/FailoverUpdates.cpp \ src/FailoverUpdates.h \ diff --git a/cpp/bindings/qpid/python/python.i b/cpp/bindings/qpid/python/python.i index 9d45bf54ee..a53cf3b853 100644 --- a/cpp/bindings/qpid/python/python.i +++ b/cpp/bindings/qpid/python/python.i @@ -132,7 +132,10 @@ static PyObject* pTransportFailure; # equivalent in C++, so we will translate them to sasl_mechanism # when possible. def __init__(self, url=None, **options): - args = [url] if url else [] + if url: + args = [url] + else: + args = [] if options : if "sasl_mechanisms" in options : if ' ' in options.get("sasl_mechanisms",'') : @@ -196,7 +199,7 @@ static PyObject* pTransportFailure; self._acknowledge_all(sync) __swig_getmethods__["connection"] = getConnection - if _newclass: connection = _swig_property(getConnection) + if _newclass: connection = property(getConnection) %} } @@ -205,10 +208,10 @@ static PyObject* pTransportFailure; %pythoncode %{ __swig_getmethods__["capacity"] = getCapacity __swig_setmethods__["capacity"] = setCapacity - if _newclass: capacity = _swig_property(getCapacity, setCapacity) + if _newclass: capacity = property(getCapacity, setCapacity) __swig_getmethods__["session"] = getSession - if _newclass: session = _swig_property(getSession) + if _newclass: session = property(getSession) %} %pythoncode %{ @@ -233,10 +236,10 @@ static PyObject* pTransportFailure; __swig_getmethods__["capacity"] = getCapacity __swig_setmethods__["capacity"] = setCapacity - if _newclass: capacity = _swig_property(getCapacity, setCapacity) + if _newclass: capacity = property(getCapacity, setCapacity) __swig_getmethods__["session"] = getSession - if _newclass: session = _swig_property(getSession) + if _newclass: session = property(getSession) %} } @@ -298,24 +301,23 @@ static PyObject* pTransportFailure; self.setContent(content) __swig_getmethods__["content"] = _get_content __swig_setmethods__["content"] = _set_content - if _newclass: content = _swig_property(_get_content, _set_content) + if _newclass: content = property(_get_content, _set_content) __swig_getmethods__["content_type"] = getContentType __swig_setmethods__["content_type"] = setContentType - if _newclass: content_type = _swig_property(getContentType, - setContentType) + if _newclass: content_type = property(getContentType, setContentType) __swig_getmethods__["id"] = getMessageId __swig_setmethods__["id"] = setMessageId - if _newclass: id = _swig_property(getMessageId, setMessageId) + if _newclass: id = property(getMessageId, setMessageId) __swig_getmethods__["subject"] = getSubject __swig_setmethods__["subject"] = setSubject - if _newclass: subject = _swig_property(getSubject, setSubject) + if _newclass: subject = property(getSubject, setSubject) __swig_getmethods__["priority"] = getPriority __swig_setmethods__["priority"] = setPriority - if _newclass: priority = _swig_property(getPriority, setPriority) + if _newclass: priority = property(getPriority, setPriority) def getTtl(self) : return self._getTtl().getMilliseconds()/1000.0 @@ -323,28 +325,26 @@ static PyObject* pTransportFailure; self._setTtl(Duration(int(1000*duration))) __swig_getmethods__["ttl"] = getTtl __swig_setmethods__["ttl"] = setTtl - if _newclass: ttl = _swig_property(getTtl, setTtl) + if _newclass: ttl = property(getTtl, setTtl) __swig_getmethods__["user_id"] = getUserId __swig_setmethods__["user_id"] = setUserId - if _newclass: user_id = _swig_property(getUserId, setUserId) + if _newclass: user_id = property(getUserId, setUserId) __swig_getmethods__["correlation_id"] = getCorrelationId __swig_setmethods__["correlation_id"] = setCorrelationId - if _newclass: correlation_id = _swig_property(getCorrelationId, - setCorrelationId) + if _newclass: correlation_id = property(getCorrelationId, setCorrelationId) __swig_getmethods__["redelivered"] = getRedelivered __swig_setmethods__["redelivered"] = setRedelivered - if _newclass: redelivered = _swig_property(getRedelivered, - setRedelivered) + if _newclass: redelivered = property(getRedelivered, setRedelivered) __swig_getmethods__["durable"] = getDurable __swig_setmethods__["durable"] = setDurable - if _newclass: durable = _swig_property(getDurable, setDurable) + if _newclass: durable = property(getDurable, setDurable) __swig_getmethods__["properties"] = getProperties - if _newclass: properties = _swig_property(getProperties) + if _newclass: properties = property(getProperties) def getReplyTo(self) : return self._getReplyTo().str() @@ -352,7 +352,7 @@ static PyObject* pTransportFailure; self._setReplyTo(Address(address_str)) __swig_getmethods__["reply_to"] = getReplyTo __swig_setmethods__["reply_to"] = setReplyTo - if _newclass: reply_to = _swig_property(getReplyTo, setReplyTo) + if _newclass: reply_to = property(getReplyTo, setReplyTo) def __repr__(self): args = [] diff --git a/cpp/bindings/qpid/ruby/README.rdoc b/cpp/bindings/qpid/ruby/README.rdoc index 0ae7e5cbed..478fc939d9 100644 --- a/cpp/bindings/qpid/ruby/README.rdoc +++ b/cpp/bindings/qpid/ruby/README.rdoc @@ -2,7 +2,7 @@ Qpid is an cross-platform enterprise messaging system. -Version :: 0.10.0.alpha.0 +Version :: 0.17.0 = Links diff --git a/cpp/bindings/qpid/ruby/Rakefile b/cpp/bindings/qpid/ruby/Rakefile index df0b3970b6..99c3e13c83 100644 --- a/cpp/bindings/qpid/ruby/Rakefile +++ b/cpp/bindings/qpid/ruby/Rakefile @@ -120,7 +120,9 @@ spec = Gem::Specification.new do |s| "lib/**/*.rb", "test/**/*.rb", "examples/**/*.rb", - "ext/**/*"] + "ext/**/*", + "features/**/*", + "spec/**/*"] end Gem::PackageTask.new(spec) do |pkg| diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb index e5071ca4e6..845cc2b116 100644 --- a/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb +++ b/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb @@ -1,3 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + Given /^an Address with the name "([^"]*)" and subject "([^"]*)" and option "([^"]*)" set to "([^"]*)"$/ do |name, subject, key, value| options = Hash.new options["#{key}"] = "#{value}" diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/connection_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/connection_steps.rb index b4146ac1fb..3fe3e6941f 100644 --- a/cpp/bindings/qpid/ruby/features/step_definitions/connection_steps.rb +++ b/cpp/bindings/qpid/ruby/features/step_definitions/connection_steps.rb @@ -1,3 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + # close all connections After do @connection.close if @connection diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb index 8157fb7735..a8c8aa4a43 100644 --- a/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb +++ b/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb @@ -1,3 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + Given /^an existing receiver for "([^"]*)"$/ do |address| steps %Q{ Given an open session diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/sender_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/sender_steps.rb index 3ff081c7d2..93dbd2d5c0 100644 --- a/cpp/bindings/qpid/ruby/features/step_definitions/sender_steps.rb +++ b/cpp/bindings/qpid/ruby/features/step_definitions/sender_steps.rb @@ -1,3 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + Given /^the message "([^"]*)" is sent$/ do |content| @sender.send Qpid::Messaging::Message.new :content => "#{content}" end diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/session_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/session_steps.rb index f97e423ee9..cf775d917d 100644 --- a/cpp/bindings/qpid/ruby/features/step_definitions/session_steps.rb +++ b/cpp/bindings/qpid/ruby/features/step_definitions/session_steps.rb @@ -1,3 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + Given /^a closed session/ do steps %Q{ Given an open connection diff --git a/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb b/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb index 7b9130156d..2f20fab18e 100644 --- a/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb +++ b/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb @@ -45,8 +45,10 @@ module Qpid content_type = message.content_type unless content_type case content_type - when "amqp/map": Cqpid.decodeMap message.message_impl - when "amqp/list": Cqpid.decodeList message.message_impl + when "amqp/map" + Cqpid.decodeMap message.message_impl + when "amqp/list" + Cqpid.decodeList message.message_impl end message.content diff --git a/cpp/bindings/qpid/ruby/lib/qpid/version.rb b/cpp/bindings/qpid/ruby/lib/qpid/version.rb index f387ba98dc..39524e428f 100644 --- a/cpp/bindings/qpid/ruby/lib/qpid/version.rb +++ b/cpp/bindings/qpid/ruby/lib/qpid/version.rb @@ -22,7 +22,7 @@ module Qpid module Version NUMBERS = [MAJOR = 0, - MINOR = 13, + MINOR = 17, BUILD = 0] end diff --git a/cpp/bindings/swig_python_typemaps.i b/cpp/bindings/swig_python_typemaps.i index e99ce65254..25a4e46b18 100644 --- a/cpp/bindings/swig_python_typemaps.i +++ b/cpp/bindings/swig_python_typemaps.i @@ -25,7 +25,11 @@ static PyObject* pUuidModule; %} %init %{ - pUuidModule = PyImport_ImportModule("uuid"); + /* Instead of directly referencing the uuid module (which is not available + * on older versions of Python), reference the wrapper defined in + * qpid.datatypes. + */ + pUuidModule = PyImport_ImportModule("qpid.datatypes"); /* Although it is not required, we'll publish the uuid module in our * module, as if this module was a python module and we called diff --git a/cpp/configure.ac b/cpp/configure.ac index 8729ace169..c68fed932e 100644 --- a/cpp/configure.ac +++ b/cpp/configure.ac @@ -27,7 +27,7 @@ AC_PROG_CC_STDC AM_PROG_CC_C_O AC_PROG_CXX AC_USE_SYSTEM_EXTENSIONS -AC_LANG([C++]) +AC_LANG([C++]) # Check for optional use of help2man AC_CHECK_PROG([HELP2MAN], [help2man], [help2man]) @@ -83,14 +83,14 @@ if test x$GXX = xyes; then gl_COMPILER_FLAGS(-Wvolatile-register-var) gl_COMPILER_FLAGS(-Winvalid-pch) gl_COMPILER_FLAGS(-Wno-system-headers) - gl_COMPILER_FLAGS(-Woverloaded-virtual) + gl_COMPILER_FLAGS(-Woverloaded-virtual) AC_SUBST([WARNING_CFLAGS], [$COMPILER_FLAGS]) AC_DEFINE([lint], 1, [Define to 1 if the compiler is checking for lint.]) COMPILER_FLAGS= fi else AC_CHECK_DECL([__SUNPRO_CC], [SUNCC=yes], [SUNCC=no]) - + # Set up for sun CC compiler if test x$SUNCC = xyes; then if test "${enableval}" = yes; then @@ -118,7 +118,7 @@ LIBS=$gl_saved_libs gl_CLOCK_TIME -# Enable Valgrind +# Enable Valgrind AC_ARG_ENABLE([valgrind], [AS_HELP_STRING([--enable-valgrind], [run valgrind memory checker on tests, if available (default yes)])], @@ -203,13 +203,26 @@ AM_CONDITIONAL([HAVE_RUBY_DEVEL], [test -f $RUBY_INC/ruby.h && test -n "$SWIG"]) # Python bindings: To build python wrappers, the python-devel files must be present. AM_PATH_PYTHON() AS_IF([test -n "$PYTHON"], [ - PKG_CHECK_MODULES([PYTHON], [python], [have_python_dev=yes],[ + PKG_CHECK_MODULES([PYTHON], [python-$PYTHON_VERSION], [have_python_dev=yes],[ + # We didn't find pkg-config information for python-2.7 this + # may mean we have an earlier python version: + # Try to find the include and library files directly in the default + # location + AC_MSG_WARN([Didn't find Python 2.7 developer libs - looking for older version]) + PYTHON_INC=$($PYTHON -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_inc()') + AC_CHECK_LIB([python$PYTHON_VERSION],[Py_Initialize]) + AC_CHECK_FILE(["$PYTHON_INC/Python.h"],[ + PYTHON_CFLAGS="-I$PYTHON_INC" + PYTHON_LIBS="-lpython$PYTHON_VERSION" + have_python_dev=yes + ],[ if test yes = "$with_python" ; then AC_MSG_ERROR([Couldn't find Python developer libs - you probably need to install a python-dev or python-devel package]) else AC_MSG_WARN([Couldn't find Python developer libs - you probably don't have a python-dev or python-devel package installed]) fi ]) + ]) AC_SUBST(PYTHON_CFLAGS) AC_SUBST(PYTHON_LIBS) ]) @@ -249,7 +262,7 @@ tmp_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -L/usr/lib/openais -L/usr/lib64/openais -L/usr/lib/corosync -L/usr/lib64/corosync" AC_CHECK_LIB([cpg],[cpg_local_get],[have_libcpg=yes],) AC_CHECK_HEADERS([openais/cpg.h corosync/cpg.h],[have_cpg_h=yes],) -AC_ARG_WITH([cpg], +AC_ARG_WITH([cpg], [AS_HELP_STRING([--with-cpg], [Build with CPG support for clustering.])], [case "${withval}" in yes) # yes - require dependencies @@ -257,7 +270,7 @@ AC_ARG_WITH([cpg], test x$have_cpg_h = xyes || AC_MSG_ERROR([cpg.h not found, install openais-devel or corosync-devel]) with_cpg=yes ;; - no) with_cpg=no ;; + no) with_cpg=no ;; *) AC_MSG_ERROR([Bad value ${withval} for --with-cpg option]) ;; esac], [ # not specified - use if present @@ -265,12 +278,14 @@ AC_ARG_WITH([cpg], ] ) AM_CONDITIONAL([HAVE_LIBCPG], [test x$with_cpg = xyes]) +AC_SUBST(USE_CPG, [$with_cpg]) + # Clean up unnceccassary flags if we don't use clustering AS_IF([test ! x$with_cpg = xyes], [LDFLAGS=$tmp_LDFLAGS]) AC_CHECK_LIB([cman],[cman_is_quorate],have_libcman=yes,) AC_CHECK_HEADERS([libcman.h],have_libcman_h=yes,) -AC_ARG_WITH([libcman], +AC_ARG_WITH([libcman], [AS_HELP_STRING([--with-libcman], [Integration with libcman quorum service.])], [case "${withval}" in yes) # yes - require dependencies @@ -278,7 +293,7 @@ AC_ARG_WITH([libcman], test x$have_libcman_h = xyes || AC_MSG_ERROR([libcman.h not found, install cman-devel or cmanlib-devel]) with_libcman=yes ;; - no) with_libcman=no ;; + no) with_libcman=no ;; *) AC_MSG_ERROR([Bad value ${withval} for --with-libcman option]) ;; esac], [ # not specified - use if present and we're using with_cpg @@ -430,9 +445,9 @@ AC_ARG_WITH([ssl], [ with_SSL=yes AC_PATH_PROG([NSPR_CONFIG], [nspr-config]) - AS_IF([test x$NSPR_CONFIG = x], [with_SSL=no], + AS_IF([test x$NSPR_CONFIG = x], [with_SSL=no], [AC_PATH_PROG([NSS_CONFIG], [nss-config]) - AS_IF([test x$NSS_CONFIG = x], [with_SSL=no], + AS_IF([test x$NSS_CONFIG = x], [with_SSL=no], [SSL_CFLAGS="`$NSPR_CONFIG --cflags` `$NSS_CONFIG --cflags`" SSL_LDFLAGS="`$NSPR_CONFIG --libs` `$NSS_CONFIG --libs`"])]) ] @@ -448,7 +463,7 @@ AC_ARG_WITH([poller], [AS_HELP_STRING([--with-poller], [The low level poller implementation: poll/solaris-ecf/epoll])], [case ${withval} in poll) - AC_CHECK_HEADERS([sys/poll.h],[poller=no],[AC_MSG_ERROR([Can't find poll.h header file for poll])]) + AC_CHECK_HEADERS([sys/poll.h],[poller=poll],[AC_MSG_ERROR([Can't find poll.h header file for poll])]) ;; solaris-ecf) AC_CHECK_HEADERS([port.h],[poller=solaris-ecf],[AC_MSG_ERROR([Can't find port.h header file for solaris-ecf])]) @@ -458,14 +473,17 @@ AC_ARG_WITH([poller], ;; esac], [ - AC_CHECK_HEADERS([sys/poll.h],[poller=no],) - AC_CHECK_HEADERS([port.h],[poller=solaris-ecf],) + # We check for poll first so that it is overridden + AC_CHECK_HEADERS([sys/poll.h],[poller=poll],) + # Not currently supported - WIP + #AC_CHECK_HEADERS([port.h],[poller=solaris-ecf],) AC_CHECK_HEADERS([sys/epoll.h],[poller=epoll],) ] ) -AM_CONDITIONAL([HAVE_ECF], [test x$poller = xsolaris-ecf]) -AM_CONDITIONAL([HAVE_EPOLL], [test x$poller = xepoll]) +AM_CONDITIONAL([USE_ECF], [test x$poller = xsolaris-ecf]) +AM_CONDITIONAL([USE_POLL], [test x$poller = xpoll]) +AM_CONDITIONAL([USE_EPOLL], [test x$poller = xepoll]) #Filter not implemented or invalid mechanisms if test $poller = xno; then @@ -480,12 +498,30 @@ case "$host" in esac AM_CONDITIONAL([SUNOS], [test x$arch = xsolaris]) +# Check whether we've got the header for dtrace static probes +AC_ARG_WITH([probes], + [AS_HELP_STRING([--with-probes], [Build with dtrace/systemtap static probes])], + [case ${withval} in + yes) + AC_CHECK_HEADERS([sys/sdt.h]) + ;; + no) + ;; + *) + AC_MSG_ERROR([Bad value for --with-probes: ${withval}]) + ;; + esac], + [ + AC_CHECK_HEADERS([sys/sdt.h]) + ] +) + # Check for some syslog capabilities not present in all systems -AC_TRY_COMPILE([#include ], +AC_TRY_COMPILE([#include ], [int v = LOG_AUTHPRIV;], [AC_DEFINE([HAVE_LOG_AUTHPRIV], [1], [Set to 1 whether LOG_AUTHPRIV is supported.])],) -AC_TRY_COMPILE([#include ], +AC_TRY_COMPILE([#include ], [int v = LOG_FTP;], [AC_DEFINE([HAVE_LOG_FTP], [1], [Set to 1 whether LOG_FTP is supported.])],) @@ -503,8 +539,6 @@ AC_CHECK_LIB([nsl],[getipnodebyname],[NSL_LIB="-lnsl"],[NSL_LIB=""],[]) SOCKLIBS="$SOCKET_LIB $NSL_LIB" AC_SUBST([SOCKLIBS]) -AM_PATH_PYTHON() - # Used by env scripts to find libraries in cmake or autoconf builds. builddir_lib_suffix="/.libs" AC_SUBST([builddir_lib_suffix]) @@ -539,6 +573,7 @@ AC_CONFIG_FILES([ managementgen/Makefile etc/Makefile src/Makefile + src/tests/cpg_check.sh src/tests/Makefile src/tests/test_env.sh src/tests/install_env.sh diff --git a/cpp/design_docs/new-ha-design.txt b/cpp/design_docs/new-ha-design.txt index 3272b1315f..acca1720b4 100644 --- a/cpp/design_docs/new-ha-design.txt +++ b/cpp/design_docs/new-ha-design.txt @@ -257,20 +257,24 @@ Broker startup with store: - When connecting as backup, check UUID matches primary, shut down if not. - Empty: start ok, no UUID check with primary. -** Current Limitations +* Current Limitations (In no particular order at present) For message replication: -LM1 - The re-synchronisation does not handle the case where a newly elected -primary is *behind* one of the other backups. To address this I propose -a new event for restting the sequence that the new primary would send -out on detecting that a replicating browser is ahead of it, requesting -that the replica revert back to a particular sequence number. The -replica on receiving this event would then discard (i.e. dequeue) all -the messages ahead of that sequence number and reset the counter to -correctly sequence any subsequently delivered messages. +LM1a - On failover, backups delete their queues and download the full queue state from the +primary. There was code to use messags already on the backup for re-synchronisation, it +was removed in early development (r1214490) to simplify the logic while getting basic +replication working. It needs to be re-introduced. + +LM1b - This re-synchronisation does not handle the case where a newly elected primary is *behind* +one of the other backups. To address this I propose a new event for restting the sequence +that the new primary would send out on detecting that a replicating browser is ahead of +it, requesting that the replica revert back to a particular sequence number. The replica +on receiving this event would then discard (i.e. dequeue) all the messages ahead of that +sequence number and reset the counter to correctly sequence any subsequently delivered +messages. LM2 - There is a need to handle wrap-around of the message sequence to avoid confusing the resynchronisation where a replica has been disconnected @@ -288,12 +292,12 @@ confirmed to the publisher before they are replicated, leaving them vulnerable to a loss of the new primary before they are replicated. LM6 - persistence: In the event of a total cluster failure there are -no tools to automatically identify the "latest" store. Once this -is manually identfied, all other stores belonging to cluster members -must be erased and the latest node must started as primary. +no tools to automatically identify the "latest" store. -LM6 - persistence: In the event of a single node failure, that nodes -store must be erased before it can re-join the cluster. +LM7 - persistence: In the event of a persistent broker being +re-started (due to failure or admin) it should be able to use its +stored messages to reduce the download required from the +primary. This means storing message IDs persistently. For configuration propagation: @@ -349,6 +353,12 @@ LC6 - The events and query responses are not fully synchronized. It is not possible to miss a create event and yet not to have the object in question in the query response however. +LC7 Federated links from the primary will be lost in failover, they will not be re-connected on +the new primary. Federation links to the primary can fail over. + +LC8 Only plain FIFO queues can be replicated. LVQs and ring queues are not yet supported. + +LC9 The "last man standing" feature of the old cluster is not available. * Benefits compared to previous cluster implementation. @@ -359,58 +369,3 @@ LC6 - The events and query responses are not fully synchronized. - Can take advantage of resource manager features, e.g. virtual IP addresses. - Fewer inconsistent errors (store failures) that can be handled without killing brokers. - Improved performance -* User Documentation Notes - -Notes to seed initial user documentation. Loosely tracking the implementation, -some points mentioned in the doc may not be implemented yet. - -** High Availability Overview - -HA is implemented using a 'hot standby' approach. Clients are directed -to a single "primary" broker. The primary executes client requests and -also replicates them to one or more "backup" brokers. If the primary -fails, one of the backups takes over the role of primary carrying on -from where the primary left off. Clients will fail over to the new -primary automatically and continue their work. - -TODO: at least once, deduplication. - -** Enabling replication on the client. - -To enable replication set the qpid.replicate argument when creating a -queue or exchange. - -This can have one of 3 values -- none: the object is not replicated -- configuration: queues, exchanges and bindings are replicated but messages are not. -- messages: configuration and messages are replicated. - -TODO: examples -TODO: more options for default value of qpid.replicate - -A HA client connection has multiple addresses, one for each broker. If -the it fails to connect to an address, or the connection breaks, -it will automatically fail-over to another address. - -Only the primary broker accepts connections, the backup brokers -redirect connection attempts to the primary. If the primary fails, one -of the backups is promoted to primary and clients fail-over to the new -primary. - -TODO: using multiple-address connections, examples c++, python, java. - -TODO: dynamic cluster addressing? - -TODO: need de-duplication. - -** Enabling replication on the broker. - -Network topology: backup links, separate client/broker networks. -Describe failover mechanisms. -- Client view: URLs, failover, exclusion & discovery. -- Broker view: similar. -Role of rmganager - -** Configuring rgmanager - -** Configuring qpidd diff --git a/cpp/etc/Makefile.am b/cpp/etc/Makefile.am index 1e4db561a7..b154a105d4 100644 --- a/cpp/etc/Makefile.am +++ b/cpp/etc/Makefile.am @@ -20,9 +20,10 @@ SASL_CONF = sasl2/qpidd.conf EXTRA_DIST = \ $(SASL_CONF) \ - qpidd qpidd.conf qpidc.conf CMakeLists.txt + qpidd qpidd-primary qpidd.conf qpidc.conf CMakeLists.txt \ + cluster.conf-example.xml -confdir=$(sysconfdir)/qpid +confdir = $(sysconfdir)/qpid nobase_conf_DATA=\ qpidc.conf @@ -32,5 +33,23 @@ nobase_sysconf_DATA = \ if HAVE_SASL nobase_sysconf_DATA += \ $(SASL_CONF) - endif + +# Substitute values for directories in init scripts. +# +# We can't use autoconf substitution directly because it leaves +# ${prefix} and ${exec_prefix} unexpanded. Substitute with sed +# scripts. +SUBST="s|!!sysconfdir!!|${sysconfdir}|;s|!!sbindir!!|${sbindir}|;s|!!bindir!!|${bindir}|" +qpidd: qpidd.in + sed $(SUBST) $< > $@ +qpidd-primary: qpidd-primary.in + sed $(SUBST) $< > $@ +cluster.conf-example.xml: cluster.conf-example.xml.in + sed $(SUBST) $< > $@ + +CLEANFILES = qpidd qpidd-primary cluster.conf-example.xml + +initddir = $(sysconfdir)/init.d +nobase_initd_SCRIPTS = qpidd qpidd-primary + diff --git a/cpp/etc/cluster.conf-example.xml.in b/cpp/etc/cluster.conf-example.xml.in new file mode 100644 index 0000000000..14b961a363 --- /dev/null +++ b/cpp/etc/cluster.conf-example.xml.in @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Apache Qpid: Open Source AMQP Messaging - AMQP (Advanced Message Queueing Protocol) - - - - - - - -
-  Apache Qpid > Index > AMQP (Advanced Message Queueing Protocol) - -
- - - - - - -
-
- -
- - - - - - -
-
-

What is AMQP?

- -

AMQP Advanced Message Queuing Protocol is an open standard designed to support reliable, high-performance messaging over the Internet. AMQP can be used for any distributed or business application, and supports common messaging paradigms like point-to-point, fanout, publish-subscribe, and request-response.

- -

Apache Qpid implements AMQP, including transaction management, queuing, clustering, federation, security, management and multi-platform support.

- - -

Apache Qpid implements the latest AMQP specification, providing transaction management, queuing, distribution, security, management, clustering, federation and heterogeneous multi-platform support and a lot more.

- -

Apache Qpid is highly optimized, and aims to be 100% AMQP Compliant.

- -

Download the AMQP Specifications

- -

AMQP version 0-10

- - - - - -

AMQP version 0-9-1

- - - - -

AMQP version 0-9

- - - - -

AMQP version 0-8

- - - -
- - - -
- - - - diff --git a/doc/book/src/common/css/style.css b/doc/book/src/common/css/style.css new file mode 100644 index 0000000000..c681596592 --- /dev/null +++ b/doc/book/src/common/css/style.css @@ -0,0 +1,279 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +ul { + list-style-type:square; +} + +th { + font-weight: bold; +} + +.navfooter td { + font-size:10pt; +} + +.navheader td { + font-size:10pt; +} + +body { + margin:0; + background:#FFFFFF; + font-family:"Verdana", sans-serif; + font-size:10pt; +} + +.container { + width:950px; + margin:0 auto; +} + +body a { + color:#000000; +} + + +div.book { + margin-left:10pt; + margin-right:10pt; +} + +div.preface { + margin-left:10pt; + margin-right:10pt; +} + +div.chapter { + margin-left:10pt; + margin-right:10pt; +} + +div.section { + margin-left:10pt; + margin-right:10pt; +} + +div.titlepage { + margin-left:-10pt; + margin-right:-10pt; +} + +.calloutlist td { + font-size:10pt; +} + +.table-contents table { + border-spacing: 0px; +} + +.table-contents td { + font-size:10pt; + padding-left:6px; + padding-right:6px; +} + +div.breadcrumbs { + font-size:9pt; + margin-right:10pt; + padding-bottom:16px; +} + +.chapter h2.title { + font-size:20pt; + color:#0c3b82; +} + +.chapter .section h2.title { + font-size:18pt; + color:#0c3b82; +} + +.section h2.title { + font-size:16pt; + color:#0c3b82; +} + +.section h3.title { + font-size:14pt; + color:#0c3b82; +} + +.section h4.title { + font-size:12pt; + color:#0c3b82; +} + +.section h5.title { + font-size:12pt; + color:#0c3b82; +} + +.section h6.title { + font-size:12pt; + color:#0c3b82; +} + +.toc a { + font-size:9pt; +} + +.header { + height:100px; + width:950px; + background:url(http://qpid.apache.org/images/header.png) +} + +.logo { + text-align:center; + font-weight:600; + padding:0 0 0 0; + font-size:14px; + font-family:"Verdana", cursive; +} + +.logo a { + color:#000000; + text-decoration:none; +} + +.main_text_area { + margin-left:200px; +} + +.main_text_area_top { + height:14px; + font-size:1px; +} + +.main_text_area_bottom { + display:none; +/* height:14px; + margin-bottom:4px;*/ +} + +.main_text_area_body { + padding:5px 24px; +} + +.main_text_area_body p { + text-align:justify; +} + +.main_text_area br { + line-height:10px; +} + +.main_text_area h1 { + font-size:28px; + font-weight:600; + margin:0 0 24px 0; + color:#0c3b82; + font-family:"Verdana", Times, serif; +} + +.main_text_area h2 { + font-size:24px; + font-weight:600; + margin:24px 0 8px 0; + color:#0c3b82; + font-family:"Verdana",Times, serif; +} + +.main_text_area ol, .main_text_area ul { + padding:0; + margin:10px 0; + margin-left:20px; +} + +.main_text_area li { +/* margin-left:40px; */ +} + +.main_text_area, .menu_box { + font-size:13px; + line-height:17px; + color:#000000; +} + +.main_text_area { + font-size:14px; +} + +.main_text_area a { + color:#000000; +} + +.main_text_area a:hover { + color:#000000; +} + +.menu_box { + width:196px; + float:left; + margin-left:4px; +} + +.menu_box_top { + background:url(http://qpid.apache.org/images/menu_top.png) no-repeat; + height:14px; + font-size:1px; +} + +.menu_box_body { + background:url(http://qpid.apache.org/images/menu_body.png) repeat-y; + padding:5px 24px 5px 24px; +} + +.menu_box_bottom { + background:url(http://qpid.apache.org/images/menu_bottom.png) no-repeat; + height:14px; + font-size:1px; + margin-bottom:1px; +} + +.menu_box h3 { + font-size:20px; + font-weight:500; + margin:0 0 8px 0; + color:#0c3b82; + font-family:"Verdana",Times, serif; +} + +.menu_box ul { + margin:12px; + padding:0px; +} + +.menu_box li { + list-style:square; +} + +.menu_box a { + color:#000000; + text-decoration:none; +} + +.menu_box a:hover { + color:#000000; + text-decoration:underline; +} + + diff --git a/doc/book/src/cpp-broker/AMQP-Compatibility.xml b/doc/book/src/cpp-broker/AMQP-Compatibility.xml new file mode 100644 index 0000000000..e5aa98cf96 --- /dev/null +++ b/doc/book/src/cpp-broker/AMQP-Compatibility.xml @@ -0,0 +1,713 @@ + + + +
+ + AMQP compatibility + + + Qpid provides the most complete and compatible implementation + of AMQP. And is the most aggressive in implementing the latest + version of the specification. + + + There are two brokers: + + + + C++ with support for AMQP 0-10 + Java with support for AMQP 0-8 and 0-9 (0-10 planned) + + + There are client libraries for C++, Java (JMS), .Net (written in + C#), python and ruby. + + + All clients support 0-10 and interoperate with the C++ + broker. + + + + The JMS client supports 0-8, 0-9 and 0-10 and interoperates + with both brokers. + + + + The python and ruby clients will also support all versions, + but the API is dynamically driven by the specification used and + so differs between versions. To work with the Java broker you + must use 0-8 or 0-9, to work with the C++ broker you must use + 0-10. + + + + There are two separate C# clients, one for 0-8 that + interoperates with the Java broker, one for 0-10 that + inteoperates with the C++ broker. + + + + QMF Management is supported in Ruby, Python, C++, and via QMan + for Java JMX & WS-DM. + +
+ + AMQP + Compatibility of Qpid releases: + + + Qpid implements the AMQP Specification, and as the specification + has progressed Qpid is keeping up with the updates. This means + that different Qpid versions support different versions of AMQP. + Here is a simple guide on what use. + + + Here is a matrix that describes the different versions supported + by each release. The status symbols are interpreted as follows: + + + + + Y + supported + + + N + unsupported + + + IP + in progress + + + P + planned + + + + + AMQP Version Support by Qpid Release + + + + + Component + + + Spec + + +   + + +   + + +   + + +   + + + + +   + + +   + + + M2.1 + + + M3 + + + M4 + + + 0.5 + + + + + java client + + + 0-10 + + +   + + + Y + + + Y + + + Y + + + + +   + + + 0-9 + + + Y + + + Y + + + Y + + + Y + + + + +   + + + 0-8 + + + Y + + + Y + + + Y + + + Y + + + + + java broker + + + 0-10 + + +   + + +   + + +   + + + P + + + + +   + + + 0-9 + + + Y + + + Y + + + Y + + + Y + + + + +   + + + 0-8 + + + Y + + + Y + + + Y + + + Y + + + + + c++ client/broker + + + 0-10 + + +   + + + Y + + + Y + + + Y + + + + +   + + + 0-9 + + + Y + + +   + + +   + + +   + + + + + python client + + + 0-10 + + +   + + + Y + + + Y + + + Y + + + + +   + + + 0-9 + + + Y + + + Y + + + Y + + + Y + + + + +   + + + 0-8 + + + Y + + + Y + + + Y + + + Y + + + + + ruby client + + + 0-10 + + +   + + +   + + + Y + + + Y + + + + +   + + + 0-8 + + + Y + + + Y + + + Y + + + Y + + + + + C# client + + + 0-10 + + +   + + +   + + + Y + + + Y + + + + +   + + + 0-8 + + + Y + + + Y + + + Y + + + Y + + + + +
+ +
+ +
+ + Interop + table by AMQP specification version + + + Above table represented in another format. + + + AMQP Version Support - alternate format + + + + +   + + + release + + + 0-8 + + + 0-9 + + + 0-10 + + + + + java client + + + M3 M4 0.5 + + + Y + + + Y + + + Y + + + + + java client + + + M2.1 + + + Y + + + Y + + + N + + + + + java broker + + + M3 M4 0.5 + + + Y + + + Y + + + N + + + + + java broker + + + trunk + + + Y + + + Y + + + P + + + + + java broker + + + M2.1 + + + Y + + + Y + + + N + + + + + c++ client/broker + + + M3 M4 0.5 + + + N + + + N + + + Y + + + + + c++ client/broker + + + M2.1 + + + N + + + Y + + + N + + + + + python client + + + M3 M4 0.5 + + + Y + + + Y + + + Y + + + + + python client + + + M2.1 + + + Y + + + Y + + + N + + + + + ruby client + + + M3 M4 0.5 + + + Y + + + Y + + + N + + + + + ruby client + + + trunk + + + Y + + + Y + + + P + + + + + C# client + + + M3 M4 0.5 + + + Y + + + N + + + N + + + + + C# client + + + trunk + + + Y + + + N + + + Y + + + + +
+ +
+ +
diff --git a/doc/book/src/cpp-broker/AMQP-Messaging-Broker-CPP-Book.xml b/doc/book/src/cpp-broker/AMQP-Messaging-Broker-CPP-Book.xml new file mode 100644 index 0000000000..228c6a5e15 --- /dev/null +++ b/doc/book/src/cpp-broker/AMQP-Messaging-Broker-CPP-Book.xml @@ -0,0 +1,75 @@ + + + + + AMQP Messaging Broker (Implemented in C++) + + Introduction + + Qpid provides two AMQP messaging brokers: + + + Implemented in C++ - high performance, low latency, and RDMA support. + Implemented in Java - Fully JMS compliant, runs on any Java platform. + + + Both AMQP messaging brokers support clients in multiple + languages, as long as the messaging client and the messaging + broker use the same version of AMQP. See AMQP Compatibility to see + which messaging clients work with each broker. + + This manual contains information specific to the broker that is implemented in C++. + + + + + Running the AMQP Messaging Broker + + + + + + + + + + + + + + + + + + + + + + Managing the AMQP Messaging Broker + + + + + + + diff --git a/doc/book/src/cpp-broker/Active-Active-Cluster.xml b/doc/book/src/cpp-broker/Active-Active-Cluster.xml new file mode 100644 index 0000000000..28db3876e2 --- /dev/null +++ b/doc/book/src/cpp-broker/Active-Active-Cluster.xml @@ -0,0 +1,561 @@ + + + +
+ Active-active Messaging Clusters + + Active-active Messaging Clusters provide fault tolerance by ensuring that every broker in a cluster has the same queues, exchanges, messages, and bindings, and allowing a client to fail over to a new broker and continue without any loss of messages if the current broker fails or becomes unavailable. Active-active refers to the fact that all brokers in the cluster can actively serve clients. Because all brokers are automatically kept in a consistent state, clients can connect to and use any broker in a cluster. Any number of messaging brokers can be run as one cluster, and brokers can be added to or removed from a cluster while it is in use. + + + High Availability Messaging Clusters are implemented using using the OpenAIS Cluster Framework. + + + An OpenAIS daemon runs on every machine in the cluster, and these daemons communicate using multicast on a particular address. Every qpidd process in a cluster joins a named group that is automatically synchronized using OpenAIS Closed Process Groups (CPG) — the qpidd processes multicast events to the named group, and CPG ensures that each qpidd process receives all the events in the same sequence. All members get an identical sequence of events, so they can all update their state consistently. + + + Two messaging brokers are in the same cluster if + + + + They run on hosts in the same OpenAIS cluster; that is, OpenAIS is configured with the same mcastaddr, mcastport and bindnetaddr, and + + + + + + They use the same cluster name. + + + + + + + + + High Availability Clustering has a cost: in order to allow each broker in a cluster to continue the work of any other broker, a cluster must replicate state for all brokers in the cluster. Because of this, the brokers in a cluster should normally be on a LAN; there should be fast and reliable connections between brokers. Even on a LAN, using multiple brokers in a cluster is somewhat slower than using a single broker without clustering. This may be counter-intuitive for people who are used to clustering in the context of High Performance Computing or High Throughput Computing, where clustering increases performance or throughput. + + + + High Availability Messaging Clusters should be used together with Red Hat Clustering Services (RHCS); without RHCS, clusters are vulnerable to the "split-brain" condition, in which a network failure splits the cluster into two sub-clusters that cannot communicate with each other. See the documentation on the --cluster-cman option for details on running using RHCS with High Availability Messaging Clusters. See the CMAN Wiki for more detail on CMAN and split-brain conditions. Use the --cluster-cman option to enable RHCS when starting the broker. + +
+ Starting a Broker in a Cluster + + Clustering is implemented using the cluster.so module, which is loaded by default when you start a broker. To run brokers in a cluster, make sure they all use the same OpenAIS mcastaddr, mcastport, and bindnetaddr. All brokers in a cluster must also have the same cluster name — specify the cluster name in qpidd.conf: + + + cluster-name="local_test_cluster" + + + On RHEL6, you must create the file /etc/corosync/uidgid.d/qpidd to tell Corosync the name of the user running the broker.By default, the user is qpidd: + + + + uidgid { + uid: qpidd + gid: qpidd + } + + + On RHEL5, the primary group for the process running qpidd must be the ais group. If you are running qpidd as a service, it is run as the qpidd user, which is already in the ais group. If you are running the broker from the command line, you must ensure that the primary group for the user running qpidd is ais. You can set the primary group using newgrp: + + + $ newgrp ais + + + You can then run the broker from the command line, specifying the cluster name as an option. + + + [jonathan@localhost]$ qpidd --cluster-name="local_test_cluster" + + + All brokers in a cluster must have identical configuration, with a few exceptions noted below. They must load the same set of plug-ins, and have matching configuration files and command line arguments. The should also have identical ACL files and SASL databases if these are used. If one broker uses persistence, all must use persistence — a mix of transient and persistent brokers is not allowed. Differences in configuration can cause brokers to exit the cluster. For instance, if different ACL settings allow a client to access a queue on broker A but not on broker B, then publishing to the queue will succeed on A and fail on B, so B will exit the cluster to prevent inconsistency. + + + The following settings can differ for brokers on a given cluster: + + + + + logging options + + + + + + cluster-url — if set, it will be different for each broker. + + + + + + port — brokers can listen on different ports. + + + + + + + The qpid log contains entries that record significant clustering events, e.g. when a broker becomes a member of a cluster, the membership of a cluster is changed, or an old journal is moved out of the way. For instance, the following message states that a broker has been added to a cluster as the first node: + + + + 2009-07-09 18:13:41 info 127.0.0.1:1410(READY) member update: 127.0.0.1:1410(member) + 2009-07-09 18:13:41 notice 127.0.0.1:1410(READY) first in cluster + + + + If you are using SELinux, the qpidd process and OpenAIS must have the same SELinux context, or else SELinux must be set to permissive mode. If both qpidd and OpenAIS are run as services, they have the same SELinux context. If both OpenAIS and qpidd are run as user processes, they have the same SELinux context. If one is run as a service, and the other is run as a user process, they have different SELinux contexts. + + + + + The following options are available for clustering: + + + Options for High Availability Messaging Cluster + + + + + + + Options for High Availability Messaging Cluster + + + + + + + + + --cluster-name NAME + + + Name of the Messaging Cluster to join. A Messaging Cluster consists of all brokers started with the same cluster-name and openais configuration. + + + + + + --cluster-size N + + + Wait for at least N initial members before completing cluster initialization and serving clients. Use this option in a persistent cluster so all brokers in a persistent cluster can exchange the status of their persistent store and do consistency checks before serving clients. + + + + + + --cluster-url URL + + + An AMQP URL containing the local address that the broker advertizes to clients for fail-over connections. This is different for each host. By default, all local addresses for the broker are advertized. You only need to set this if + + + + Your host has more than one active network interface, and + + + + + + You want to restrict client fail-over to a specific interface or interfaces. + + + + + + Each broker in the cluster is specified using the following form: + + url = ["amqp:"][ user ["/" password] "@" ] protocol_addr + ("," protocol_addr)* + protocol_addr = tcp_addr / rmda_addr / ssl_addr / ... + tcp_addr = ["tcp:"] host [":" port] + rdma_addr = "rdma:" host [":" port] + ssl_addr = "ssl:" host [":" port] + + In most cases, only one address is advertized, but more than one address can be specified in if the machine running the broker has more than one network interface card, and you want to allow clients to connect using multiple network interfaces. Use a comma delimiter (",") to separate brokers in the URL. Examples: + + + + amqp:tcp:192.168.1.103:5672 advertizes a single address to the broker for failover. + + + + + + amqp:tcp:192.168.1.103:5672,tcp:192.168.1.105:5672 advertizes two different addresses to the broker for failover, on two different network interfaces. + + + + + + + + + + + + --cluster-cman + + + + CMAN protects against the "split-brain" condition, in which a network failure splits the cluster into two sub-clusters that cannot communicate with each other. When "split-brain" occurs, each of the sub-clusters can access shared resources without knowledge of the other sub-cluster, resulting in corrupted cluster integrity. + + + To avoid "split-brain", CMAN uses the notion of a "quorum". If more than half the cluster nodes are active, the cluster has quorum and can act. If half (or fewer) nodes are active, the cluster does not have quorum, and all cluster activity is stopped. There are other ways to define the quorum for particular use cases (e.g. a cluster of only 2 members), see the CMAN Wiki + for more detail. + + + When enabled, the broker will wait until it belongs to a quorate cluster before accepting client connections. It continually monitors the quorum status and shuts down immediately if the node it runs on loses touch with the quorum. + + + + + + + + --cluster-username + + + SASL username for connections between brokers. + + + + + + --cluster-password + + + SASL password for connections between brokers. + + + + + + --cluster-mechanism + + + SASL authentication mechanism for connections between brokers + + + + + + + + +
+ + If a broker is unable to establish a connection to another broker in the cluster, the log will contain SASL errors, e.g: + + + 2009-aug-04 10:17:37 info SASL: Authentication failed: SASL(-13): user not found: Password verification failed + + + You can set the SASL user name and password used to connect to other brokers using the cluster-username and cluster-password properties when you start the broker. In most environment, it is easiest to create an account with the same user name and password on each broker in the cluster, and use these as the cluster-username and cluster-password. You can also set the SASL mode using cluster-mechanism. Remember that any mechanism you enable for broker-to-broker communication can also be used by a client, so do not enable cluster-mechanism=ANONYMOUS in a secure environment. + + + Once the cluster is running, run qpid-cluster to make sure that the brokers are running as one cluster. See the following section for details. + + + If the cluster is correctly configured, queues and messages are replicated to all brokers in the cluster, so an easy way to test the cluster is to run a program that routes messages to a queue on one broker, then to a different broker in the same cluster and read the messages to make sure they have been replicated. The drain and spout programs can be used for this test. + + +
+ +
+ qpid-cluster + + qpid-cluster is a command-line utility that allows you to view information on a cluster and its brokers, disconnect a client connection, shut down a broker in a cluster, or shut down the entire cluster. You can see the options using the --help option: + + + $ ./qpid-cluster --help + + + Usage: qpid-cluster [OPTIONS] [broker-addr] + + broker-addr is in the form: [username/password@] hostname | ip-address [:<port>] + ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost + + Options: + -C [--all-connections] View client connections to all cluster members + -c [--connections] ID View client connections to specified member + -d [--del-connection] HOST:PORT + Disconnect a client connection + -s [--stop] ID Stop one member of the cluster by its ID + -k [--all-stop] Shut down the whole cluster + -f [--force] Suppress the 'are-you-sure?' prompt + -n [--numeric] Don't resolve names + + + Let's connect to a cluster and display basic information about the cluser and its brokers. When you connect to the cluster using qpid-tool, you can use the host and port for any broker in the cluster. For instance, if a broker in the cluster is running on localhost on port 6664, you can start qpid-tool like this: + + + + $ qpid-cluster localhost:6664 + + + Here is the output: + + + + Cluster Name: local_test_cluster + Cluster Status: ACTIVE + Cluster Size: 3 + Members: ID=127.0.0.1:13143 URL=amqp:tcp:192.168.1.101:6664,tcp:192.168.122.1:6664,tcp:10.16.10.62:6664 + : ID=127.0.0.1:13167 URL=amqp:tcp:192.168.1.101:6665,tcp:192.168.122.1:6665,tcp:10.16.10.62:6665 + : ID=127.0.0.1:13192 URL=amqp:tcp:192.168.1.101:6666,tcp:192.168.122.1:6666,tcp:10.16.10.62:6666 + + + The ID for each broker in cluster is given on the left. For instance, the ID for the first broker in the cluster is 127.0.0.1:13143. The URL in the output is the broker's advertized address. Let's use the ID to shut the broker down using the --stop command: + + + $ ./qpid-cluster localhost:6664 --stop 127.0.0.1:13143 + + +
+ +
+ Failover in Clients + + If a client is connected to a broker, the connection fails if the broker crashes or is killed. If heartbeat is enabled for the connection, a connection also fails if the broker hangs, the machine the broker is running on fails, or the network connection to the broker is lost — the connection fails no later than twice the heartbeat interval. + + + When a client's connection to a broker fails, any sent messages that have been acknowledged to the sender will have been replicated to all brokers in the cluster, any received messages that have not yet been acknowledged by the receiving client requeued to all brokers, and the client API notifies the application of the failure by throwing an exception. + + + Clients can be configured to automatically reconnect to another broker when it receives such an exception. Any messages that have been sent by the client, but not yet acknowledged as delivered, are resent. Any messages that have been read by the client, but not acknowledged, are delivered to the client. + + + TCP is slow to detect connection failures. A client can configure a connection to use a heartbeat to detect connection failure, and can specify a time interval for the heartbeat. If heartbeats are in use, failures will be detected no later than twice the heartbeat interval. The Java JMS client enables hearbeat by default. See the sections on Failover in Java JMS Clients and Failover in C++ Clients for the code to enable heartbeat. + +
+ Failover in Java JMS Clients + + In Java JMS clients, client failover is handled automatically if it is enabled in the connection. Any messages that have been sent by the client, but not yet acknowledged as delivered, are resent. Any messages that have been read by the client, but not acknowledged, are sent to the client. + + + You can configure a connection to use failover using the failover property: + + + + connectionfactory.qpidConnectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'&failover='failover_exchange' + + + This property can take three values: + + + Failover Modes + + failover_exchange + + + If the connection fails, fail over to any other broker in the cluster. + + + + + + + roundrobin + + + If the connection fails, fail over to one of the brokers specified in the brokerlist. + + + + + + + singlebroker + + + Failover is not supported; the connection is to a single broker only. + + + + + + + + + In a Connection URL, heartbeat is set using the idle_timeout property, which is an integer corresponding to the heartbeat period in seconds. For instance, the following line from a JNDI properties file sets the heartbeat time out to 3 seconds: + + + + connectionfactory.qpidConnectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672',idle_timeout=3 + + +
+ +
+ Failover and the Qpid Messaging API + + The Qpid Messaging API also supports automatic reconnection in the event a connection fails. . Senders can also be configured to replay any in-doubt messages (i.e. messages whice were sent but not acknowleged by the broker. See "Connection Options" and "Sender Capacity and Replay" in Programming in Apache Qpid for details. + + + In C++ and python clients, heartbeats are disabled by default. You can enable them by specifying a heartbeat interval (in seconds) for the connection via the 'heartbeat' option. + + + See "Cluster Failover" in Programming in Apache Qpid for details on how to keep the client aware of cluster membership. + + +
+ + +
+ +
+ Error handling in Clusters + + If a broker crashes or is killed, or a broker machine failure, broker connection failure, or a broker hang is detected, the other brokers in the cluster are notified that it is no longer a member of the cluster. If a new broker is joined to the cluster, it synchronizes with an active broker to obtain the current cluster state; if this synchronization fails, the new broker exit the cluster and aborts. + + + If a broker becomes extremely busy and stops responding, it stops accepting incoming work. All other brokers continue processing, and the non-responsive node caches all AIS traffic. When it resumes, the broker completes processes all cached AIS events, then accepts further incoming work. + + + Broker hangs are only detected if the watchdog plugin is loaded and the --watchdog-interval option is set. The watchdog plug-in kills the qpidd broker process if it becomes stuck for longer than the watchdog interval. In some cases, e.g. certain phases of error resolution, it is possible for a stuck process to hang other cluster members that are waiting for it to send a message. Using the watchdog, the stuck process is terminated and removed from the cluster, allowing other members to continue and clients of the stuck process to fail over to other members. + + + Redundancy can also be achieved directly in the AIS network by specifying more than one network interface in the AIS configuration file. This causes Totem to use a redundant ring protocol, which makes failure of a single network transparent. + + + Redundancy can be achieved at the operating system level by using NIC bonding, which combines multiple network ports into a single group, effectively aggregating the bandwidth of multiple interfaces into a single connection. This provides both network load balancing and fault tolerance. + + + If any broker encounters an error, the brokers compare notes to see if they all received the same error. If not, the broker removes itself from the cluster and shuts itself down to ensure that all brokers in the cluster have consistent state. For instance, a broker may run out of disk space; if this happens, the broker shuts itself down. Examining the broker's log can help determine the error and suggest ways to prevent it from occuring in the future. + + +
+ +
+ Persistence in High Availability Message Clusters + + Persistence and clustering are two different ways to provide reliability. Most systems that use a cluster do not enable persistence, but you can do so if you want to ensure that messages are not lost even if the last broker in a cluster fails. A cluster must have all transient or all persistent members, mixed clusters are not allowed. Each broker in a persistent cluster has it's own independent replica of the cluster's state it its store. + +
+ Clean and Dirty Stores + + When a broker is an active member of a cluster, its store is marked "dirty" because it may be out of date compared to other brokers in the cluster. If a broker leaves a running cluster because it is stopped, it crashes or the host crashes, its store continues to be marked "dirty". + + + If the cluster is reduced to a single broker, its store is marked "clean" since it is the only broker making updates. If the cluster is shut down with the command qpid-cluster -k then all the stores are marked clean. + + + When a cluster is initially formed, brokers with clean stores read from their stores. Brokers with dirty stores, or brokers that join after the cluster is running, discard their old stores and initialize a new store with an update from one of the running brokers. The --truncate option can be used to force a broker to discard all existing stores even if they are clean. (A dirty store is discarded regardless.) + + + Discarded stores are copied to a back up directory. The active store is in <data-dir>/rhm. Back-up stores are in <data-dir>/_cluster.bak.<nnnn>/rhm, where <nnnn> is a 4 digit number. A higher number means a more recent backup. + + +
+ +
+ Starting a persistent cluster + + When starting a persistent cluster broker, set the cluster-size option to the number of brokers in the cluster. This allows the brokers to wait until the entire cluster is running so that they can synchronize their stored state. + + + The cluster can start if: + + + + + + all members have empty stores, or + + + + + + at least one member has a clean store + + + + + + + + + All members of the new cluster will be initialized with the state from a clean store. + + +
+ +
+ Stopping a persistent cluster + + To cleanly shut down a persistent cluster use the command qpid-cluster -k. This causes all brokers to synchronize their state and mark their stores as "clean" so they can be used when the cluster restarts. + + +
+ +
+ Starting a persistent cluster with no clean store + + If the cluster has previously had a total failure and there are no clean stores then the brokers will fail to start with the log message Cannot recover, no clean store. If this happens you can start the cluster by marking one of the stores "clean" as follows: + + + + + Move the latest store backup into place in the brokers data-directory. The backups end in a 4 digit number, the latest backup is the highest number. + + + + cd <data-dir> + mv rhm rhm.bak + cp -a _cluster.bak.<nnnn>/rhm . + + + + + + Mark the store as clean: + qpid-cluster-store -c <data-dir> + + + + + + + + + Now you can start the cluster, all members will be initialized from the store you marked as clean. + + +
+ +
+ Isolated failures in a persistent cluster + + A broker in a persistent cluster may encounter errors that other brokers in the cluster do not; if this happens, the broker shuts itself down to avoid making the cluster state inconsistent. For example a disk failure on one node will result in that node shutting down. Running out of storage capacity can also cause a node to shut down because because the brokers may not run out of storage at exactly the same point, even if they have similar storage configuration. To avoid unnecessary broker shutdowns, make sure the queue policy size of each durable queue is less than the capacity of the journal for the queue. + + +
+ + +
+ + +
diff --git a/doc/book/src/cpp-broker/Active-Passive-Cluster.xml b/doc/book/src/cpp-broker/Active-Passive-Cluster.xml new file mode 100644 index 0000000000..5f5823bdd2 --- /dev/null +++ b/doc/book/src/cpp-broker/Active-Passive-Cluster.xml @@ -0,0 +1,661 @@ + + + +
+ + Active-passive Messaging Clusters (Preview) + +
+ Overview + + This release provides a preview of a new module for High Availability (HA). The new module is + not yet complete or ready for production use. It being made available so that users can + experiment with the new approach and provide feedback early in the development process. + Feedback should go to dev@qpid.apache.org. + + + The old cluster module takes an active-active approach, i.e. all the + brokers in a cluster are able to handle client requests simultaneously. The new HA module + takes an active-passive, hot-standby approach. + + + In an active-passive cluster only one broker, known as the primary, is + active and serving clients at a time. The other brokers are standing by as + backups. Changes on the primary are immediately replicated to all the + backups so they are always up-to-date or "hot". If the primary fails, one of the backups is + promoted to take over as the new primary. Clients fail-over to the new primary + automatically. If there are multiple backups, the backups also fail-over to become backups of + the new primary. Backup brokers reject connection attempts, to enforce the requirement that + only the primary be active. + + + This approach depends on an external cluster resource manager to detect + failures and choose the primary. Rgmanager is supported + initially, but others may be supported in the future. + +
+ Why the new approach? + + The new active-passive approach has several advantages compared to the + existing active-active cluster module. + + + It does not depend directly on openais or corosync. It does not use multicast + which simplifies deployment. + + + It is more portable: in environments that don't support corosync, it can be + integrated with a resource manager available in that environment. + + + Replication to a disaster recovery site can be handled as + simply another node in the cluster, it does not require a separate replication + mechanism. + + + It can take advantage of features provided by the resource manager, for example + virtual IP addresses. + + + Improved performance and scalability due to better use of multiple CPU s + + + +
+
+ Limitations + + + There are a number of known limitations in the current preview implementation. These + will be fixed in the production versions. + + + + + Transactional changes to queue state are not replicated atomically. If the primary crashes + during a transaction, it is possible that the backup could contain only part of the + changes introduced by a transaction. + + + During a fail-over one backup is promoted to primary and any other backups switch to + the new primary. Messages sent to the new primary before all the backups have + switched could be lost if the new primary itself fails before all the backups have + switched. + + + Acknowledgments are confirmed to clients before the message has been dequeued + from replicas or indeed from the local store if that is asynchronous. + + + When used with a persistent store: if the entire cluster fails, there are no tools to help + identify the most recent store. + + + A persistent broker must have its store erased before joining an existing cluster. + In the production version a persistent broker will be able to load its store and + avoid downloading messages that are in the store from the primary. + + + Configuration changes (creating or deleting queues, exchanges and bindings) are + replicated asynchronously. Management tools used to make changes will consider the + change complete when it is complete on the primary, it may not yet be replicated + to all the backups. + + + Deletions made immediately after a failure (before all the backups are ready) may + be lost on a backup. Queues, exchange or bindings that were deleted on the primary could + re-appear if that backup is promoted to primary on a subsequent failure. + + + Better control is needed over which queues/exchanges are replicated and which are not. + + + There are some known issues affecting performance, both the throughput of + replication and the time taken for backups to fail-over. Performance will improve + in the production version. + + + Federated links from the primary will be lost in fail over, they will not be + re-connected on the new primary. Federation links to the primary can fail over. + + + Only plain FIFO queues can be replicated. LVQ and ring queues are not yet supported. + + +
+
+ +
+ Virtual IP Addresses + + Some resource managers (including rgmanager) support + virtual IP addresses. A virtual IP address is an IP + address that can be relocated to any of the nodes in a cluster. The + resource manager associates this address with the primary node in the + cluster, and relocates it to the new primary when there is a failure. This + simplifies configuration as you can publish a single IP address rather + than a list. + + + A virtual IP address can be used by clients and backup brokers to connect + to the primary. The following sections will explain how to configure + virtual IP addresses for clients or brokers. + +
+ +
+ Configuring the Brokers + + The broker must load the ha module, it is loaded by + default. The following broker options are available for the HA module. + + + Options for High Availability Messaging Cluster + + + + + + + Options for High Availability Messaging Cluster + + + + + + + --ha-cluster yes|no + + + Set to "yes" to have the broker join a cluster. + + + + + --ha-brokers URL + + + + The URL + + + The full format of the URL is given by this grammar: + + url = ["amqp:"][ user ["/" password] "@" ] addr ("," addr)* + addr = tcp_addr / rmda_addr / ssl_addr / ... + tcp_addr = ["tcp:"] host [":" port] + rdma_addr = "rdma:" host [":" port] + ssl_addr = "ssl:" host [":" port]' + + + + used by brokers to connect to each other. If you use a virtual IP address + then this is a single address, for example + amqp:20.0.20.200. If you do not use a virtual IP + address then the URL must list all the addresses of brokers in the + cluster, for example amqp:node1,node2,node3 + + + + + --ha-public-brokers URL + + + The URL used by clients to connect to the brokers. This has the same + format as the --ha-brokers URL above. + + + If this option is not set, clients will use the same URL as brokers. + This option allows you to put client traffic on a different network from + broker traffic, which is recommended. + + + + + --ha-replicate + + + + Specifies whether queues and exchanges are replicated by default. + For details see + + + + + + --ha-username USER + --ha-password PASS + --ha-mechanism MECH + + + Authentication settings used by brokers to connect to each other. + + + + +
+ + To configure a HA cluster you must set at least ha-cluster and + ha-brokers. + +
+ +
+ The Cluster Resource Manager + + Broker fail-over is managed by a cluster resource + manager. An integration with rgmanager is + provided, but it is possible to integrate with other resource managers. + + + The resource manager is responsible for starting the qpidd broker + on each node in the cluster. The resource manager promotes + one of the brokers to be the primary. The other brokers connect to the primary as + backups, using the URL provided in the ha-brokers configuration + option. + + + Once connected, the backup brokers synchronize their state with the + primary. When a backup is synchronized, or "hot", it is ready to take + over if the primary fails. Backup brokers continually receive updates + from the primary in order to stay synchronized. + + + If the primary fails, backup brokers go into fail-over mode. The resource + manager must detect the failure and promote one of the backups to be the + new primary. The other backups connect to the new primary and synchronize + their state with it. + + + The resource manager is also responsible for protecting the cluster from + split-brain conditions resulting from a network partition. A + network partition divide a cluster into two sub-groups which cannot see each other. + Usually a quorum voting algorithm is used that disables nodes + in the inquorate sub-group. + +
+ +
+ Configuring <command>rgmanager</command> as resource manager + + This section assumes that you are already familiar with setting up and configuring + clustered services using cman and + rgmanager. It will show you how to configure an active-passive, + hot-standby qpidd HA cluster with rgmanager. + + + You must provide a cluster.conf file to configure + cman and rgmanager. Here is + an example cluster.conf file for a cluster of 3 nodes named + node1, node2 and node3. We will go through the configuration step-by-step. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java b/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java deleted file mode 100644 index d94ca5592b..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.client.message; - -import javax.jms.JMSException; -import javax.jms.Session; -import javax.jms.ObjectMessage; -import javax.jms.StreamMessage; -import javax.jms.BytesMessage; -import javax.jms.TextMessage; -import javax.jms.DeliveryMode; -import javax.jms.Destination; - -public class TestMessageFactory -{ - private static final String MESSAGE_DATA_BYTES = "-message payload-message paylaod-message payload-message paylaod"; - - public static TextMessage newTextMessage(Session session, int size) throws JMSException - { - return session.createTextMessage(createMessagePayload(size)); - } - - public static TextMessage newJMSTextMessage(Session session, int size, String encoding) throws JMSException - { - - TextMessage message = session.createTextMessage(); - message.clearBody(); - message.setText(createMessagePayload(size)); - return message; - } - - public static BytesMessage newBytesMessage(Session session, int size) throws JMSException - { - BytesMessage message = session.createBytesMessage(); - message.writeUTF(createMessagePayload(size)); - return message; - } - - public static StreamMessage newStreamMessage(Session session, int size) throws JMSException - { - StreamMessage message = session.createStreamMessage(); - message.writeString(createMessagePayload(size)); - return message; - } - - public static ObjectMessage newObjectMessage(Session session, int size) throws JMSException - { - if (size == 0) - { - return session.createObjectMessage(); - } - else - { - return session.createObjectMessage(createMessagePayload(size)); - } - } - - /** - * Creates an ObjectMessage with given size and sets the JMS properties (JMSReplyTo and DeliveryMode) - * @param session - * @param replyDestination - * @param size - * @param persistent - * @return the new ObjectMessage - * @throws JMSException - */ - public static ObjectMessage newObjectMessage(Session session, Destination replyDestination, int size, boolean persistent) throws JMSException - { - ObjectMessage msg = newObjectMessage(session, size); - - // Set the messages persistent delivery flag. - msg.setJMSDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); - - // Ensure that the temporary reply queue is set as the reply to destination for the message. - if (replyDestination != null) - { - msg.setJMSReplyTo(replyDestination); - } - - return msg; - } - - public static String createMessagePayload(int size) - { - StringBuffer buf = new StringBuffer(size); - int count = 0; - while (count <= (size - MESSAGE_DATA_BYTES.length())) - { - buf.append(MESSAGE_DATA_BYTES); - count += MESSAGE_DATA_BYTES.length(); - } - if (count < size) - { - buf.append(MESSAGE_DATA_BYTES, 0, size - count); - } - - return buf.toString(); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java b/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java deleted file mode 100644 index 76fd318625..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.config; - -import org.apache.qpid.client.AMQConnectionFactory; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.config.ConnectionFactoryInitialiser; -import org.apache.qpid.config.ConnectorConfig; -import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.url.URLSyntaxException; - -import javax.jms.ConnectionFactory; - -class AMQConnectionFactoryInitialiser implements ConnectionFactoryInitialiser -{ - public ConnectionFactory getFactory(ConnectorConfig config) - { - try - { - final ConnectionURL connectionUrl = new AMQConnectionURL(ConnectionURL.AMQ_PROTOCOL + - "://guest:guest@/test_path?brokerlist='tcp://" + config.getHost() + ":" + config.getPort() + "'"); - return new AMQConnectionFactory(connectionUrl); - } - catch (URLSyntaxException e) - { - throw new RuntimeException("Problem building URL", e); - } - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java b/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java deleted file mode 100644 index 14db74438f..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.config; - -public abstract class AbstractConfig -{ - public boolean setOptions(String[] argv) - { - try - { - for(int i = 0; i < argv.length - 1; i += 2) - { - String key = argv[i]; - String value = argv[i+1]; - setOption(key, value); - } - return true; - } - catch(Exception e) - { - System.out.println(e.getMessage()); - } - return false; - } - - protected int parseInt(String msg, String i) - { - try - { - return Integer.parseInt(i); - } - catch(NumberFormatException e) - { - throw new RuntimeException(msg + ": " + i, e); - } - } - - protected long parseLong(String msg, String i) - { - try - { - return Long.parseLong(i); - } - catch(NumberFormatException e) - { - throw new RuntimeException(msg + ": " + i, e); - } - } - - public abstract void setOption(String key, String value); -} diff --git a/java/perftests/src/main/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java b/java/perftests/src/main/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java deleted file mode 100644 index a9984eb09a..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.config; - -import javax.jms.ConnectionFactory; -import javax.jms.JMSException; - -public interface ConnectionFactoryInitialiser -{ - public ConnectionFactory getFactory(ConnectorConfig config) throws JMSException; -} diff --git a/java/perftests/src/main/java/org/apache/qpid/config/Connector.java b/java/perftests/src/main/java/org/apache/qpid/config/Connector.java deleted file mode 100644 index 81541a3260..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/config/Connector.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.config; - -import javax.jms.Connection; -import javax.jms.ConnectionFactory; - -public class Connector -{ - public Connection createConnection(ConnectorConfig config) throws Exception - { - return getConnectionFactory(config).createConnection(); - } - - ConnectionFactory getConnectionFactory(ConnectorConfig config) throws Exception - { - String factory = config.getFactory(); - if(factory == null) - { - factory = AMQConnectionFactoryInitialiser.class.getName(); - } - System.out.println("Using " + factory); - return ((ConnectionFactoryInitialiser) Class.forName(factory).newInstance()).getFactory(config); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/config/ConnectorConfig.java b/java/perftests/src/main/java/org/apache/qpid/config/ConnectorConfig.java deleted file mode 100644 index b120ed3f12..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/config/ConnectorConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.config; - -public interface ConnectorConfig -{ - public String getHost(); - public int getPort(); - public String getFactory(); -} diff --git a/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java b/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java deleted file mode 100644 index a0248a8f79..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.config; - -import org.apache.qpid.config.ConnectionFactoryInitialiser; -import org.apache.qpid.config.ConnectorConfig; -import org.apache.qpid.client.JMSAMQException; - -import javax.jms.ConnectionFactory; -import javax.jms.JMSException; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import javax.management.MBeanException; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.naming.NameNotFoundException; -import java.util.Hashtable; - -public class JBossConnectionFactoryInitialiser implements ConnectionFactoryInitialiser -{ - public ConnectionFactory getFactory(ConnectorConfig config) throws JMSException - { - ConnectionFactory cf = null; - InitialContext ic = null; - Hashtable ht = new Hashtable(); - ht.put(InitialContext.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); - String jbossHost = System.getProperty("jboss.host", "eqd-lxamq01"); - String jbossPort = System.getProperty("jboss.port", "1099"); - ht.put(InitialContext.PROVIDER_URL, "jnp://" + jbossHost + ":" + jbossPort); - ht.put(InitialContext.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); - - try - { - ic = new InitialContext(ht); - if (!doesDestinationExist("topictest.messages", ic)) - { - deployTopic("topictest.messages", ic); - } - if (!doesDestinationExist("topictest.control", ic)) - { - deployTopic("topictest.control", ic); - } - - cf = (ConnectionFactory) ic.lookup("/ConnectionFactory"); - return cf; - } - catch (NamingException e) - { - throw new JMSAMQException("Unable to lookup object: " + e, e); - } - catch (Exception e) - { - throw new JMSAMQException("Error creating topic: " + e, e); - } - } - - private boolean doesDestinationExist(String name, InitialContext ic) throws Exception - { - try - { - ic.lookup("/" + name); - } - catch (NameNotFoundException e) - { - return false; - } - return true; - } - - private void deployTopic(String name, InitialContext ic) throws Exception - { - MBeanServerConnection mBeanServer = lookupMBeanServerProxy(ic); - - ObjectName serverObjectName = new ObjectName("jboss.messaging:service=ServerPeer"); - - String jndiName = "/" + name; - try - { - mBeanServer.invoke(serverObjectName, "createTopic", - new Object[]{name, jndiName}, - new String[]{"java.lang.String", "java.lang.String"}); - } - catch (MBeanException e) - { - System.err.println("Error: " + e); - System.err.println("Cause: " + e.getCause()); - } - } - - private MBeanServerConnection lookupMBeanServerProxy(InitialContext ic) throws NamingException - { - return (MBeanServerConnection) ic.lookup("jmx/invoker/RMIAdaptor"); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/AbstractRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/AbstractRunner.java new file mode 100644 index 0000000000..9e865010f8 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/AbstractRunner.java @@ -0,0 +1,74 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import java.io.FileInputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.naming.Context; +import javax.naming.InitialContext; + +public class AbstractRunner +{ + public static final String JNDI_CONFIG_PROP = "jndi-config"; + public static final String JNDI_CONFIG_DEFAULT = "perftests-jndi.properties"; + + private Map _cliOptions = new HashMap(); + { + getCliOptions().put(JNDI_CONFIG_PROP, JNDI_CONFIG_DEFAULT); + } + + protected Context getContext() + { + Context context = null; + + try + { + final Properties properties = new Properties(); + properties.load(new FileInputStream(getJndiConfig())); + context = new InitialContext(properties); + } + catch (Exception e) + { + throw new DistributedTestException("Exception while loading JNDI properties", e); + } + + return context; + } + + public void parseArgumentsIntoConfig(String[] args) + { + ArgumentParser argumentParser = new ArgumentParser(); + argumentParser.parseArgumentsIntoConfig(getCliOptions(), args); + } + + protected String getJndiConfig() + { + return getCliOptions().get(AbstractRunner.JNDI_CONFIG_PROP); + } + + protected Map getCliOptions() + { + return _cliOptions; + } +} \ No newline at end of file diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java new file mode 100644 index 0000000000..8c1f8675e3 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import java.util.Map; + +public class ArgumentParser +{ + public void parseArgumentsIntoConfig(Map initialValues, String[] args) + { + for(String arg: args) + { + String[] splitArg = arg.split("="); + if(splitArg.length != 2) + { + throw new IllegalArgumentException("arguments must have format =: " + arg); + } + + if(initialValues.put(splitArg[0], splitArg[1]) == null) + { + throw new IllegalArgumentException("not a valid configuration property: " + arg); + } + } + + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ClientRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ClientRunner.java new file mode 100644 index 0000000000..9c2f4a3d95 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ClientRunner.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClientRunner extends AbstractRunner +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ClientRunner.class); + + public static final String NUM_OF_CLIENTS_PROP = "number-of-clients"; + + public static final String NUM_OF_CLIENTS_DEFAULT = "1"; + + public ClientRunner() + { + getCliOptions().put(NUM_OF_CLIENTS_PROP, NUM_OF_CLIENTS_DEFAULT); + } + + public static void main(String[] args) + { + ClientRunner runner = new ClientRunner(); + runner.parseArgumentsIntoConfig(args); + runner.runClients(); + } + + public void setJndiPropertiesFileLocation(String jndiConfigFileLocation) + { + getCliOptions().put(JNDI_CONFIG_PROP, jndiConfigFileLocation); + } + + /** + * Run the clients in the background + */ + public void runClients() + { + int numClients = Integer.parseInt(getCliOptions().get(NUM_OF_CLIENTS_PROP)); + + Context context = getContext(); + + for(int i = 1; i <= numClients; i++) + { + createBackgroundClient(context); + } + } + + private void createBackgroundClient(Context context) + { + try + { + final Client client = new Client(new ClientJmsDelegate(context)); + + final Thread clientThread = new Thread(new Runnable() + { + @Override + public void run() + { + LOGGER.info("Starting client " + client.getClientName()); + client.start(); + client.waitUntilStopped(); + LOGGER.info("Stopped client " + client.getClientName()); + } + }); + clientThread.start(); + } + catch (NamingException e) + { + throw new DistributedTestException("Exception while creating client instance", e); + } + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java new file mode 100644 index 0000000000..aa9c582bf8 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java @@ -0,0 +1,238 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.naming.Context; + +import org.apache.qpid.disttest.controller.Controller; +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.controller.config.Config; +import org.apache.qpid.disttest.controller.config.ConfigReader; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.results.aggregation.Aggregator; +import org.apache.qpid.disttest.results.formatting.CSVFormater; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ControllerRunner extends AbstractRunner +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ControllerRunner.class); + + public static final String TEST_CONFIG_PROP = "test-config"; + public static final String DISTRIBUTED_PROP = "distributed"; + public static final String OUTPUT_DIR_PROP = "outputdir"; + + private static final String TEST_CONFIG_DEFAULT = "perftests-config.json"; + private static final String DISTRIBUTED_DEFAULT = "false"; + private static final String OUTPUT_DIR_DEFAULT = "."; + + private final Aggregator _aggregator = new Aggregator(); + + + public ControllerRunner() + { + getCliOptions().put(TEST_CONFIG_PROP, TEST_CONFIG_DEFAULT); + getCliOptions().put(DISTRIBUTED_PROP, DISTRIBUTED_DEFAULT); + getCliOptions().put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); + } + + public static void main(String[] args) throws Exception + { + ControllerRunner runner = new ControllerRunner(); + runner.parseArgumentsIntoConfig(args); + runner.runController(); + } + + public void runController() throws Exception + { + Context context = getContext(); + + ControllerJmsDelegate jmsDelegate = new ControllerJmsDelegate(context); + + try + { + runTests(jmsDelegate); + } + finally + { + jmsDelegate.closeConnections(); + } + } + + private void runTests(ControllerJmsDelegate jmsDelegate) + { + Controller controller = new Controller(jmsDelegate, DistributedTestConstants.REGISTRATION_TIMEOUT, DistributedTestConstants.COMMAND_RESPONSE_TIMEOUT); + + final List testConfigFiles = getTestConfigFiles(); + createClientsIfNotDistributed(testConfigFiles); + + try + { + for (String testConfigFile : testConfigFiles) + { + final Config testConfig = buildTestConfigFrom(testConfigFile); + controller.setConfig(testConfig); + + controller.awaitClientRegistrations(); + + LOGGER.info("Running test : " + testConfigFile); + runTest(controller, testConfigFile); + } + } + finally + { + controller.stopAllRegisteredClients(); + } + + } + + private void runTest(Controller controller, String testConfigFile) + { + final Config testConfig = buildTestConfigFrom(testConfigFile); + controller.setConfig(testConfig); + + ResultsForAllTests rawResultsForAllTests = controller.runAllTests(); + ResultsForAllTests resultsForAllTests = _aggregator.aggregateResults(rawResultsForAllTests); + + final String outputFile = generateOutputCsvNameFrom(testConfigFile); + writeResultsToFile(resultsForAllTests, outputFile); + } + + private void createClientsIfNotDistributed(final List testConfigFiles) + { + if(!isDistributed()) + { + int maxNumberOfClients = 0; + for (String testConfigFile : testConfigFiles) + { + final Config testConfig = buildTestConfigFrom(testConfigFile); + final int numClients = testConfig.getTotalNumberOfClients(); + maxNumberOfClients = Math.max(numClients, maxNumberOfClients); + } + + //we must create the required test clients, running in single-jvm mode + for (int i = 1; i <= maxNumberOfClients; i++) + { + ClientRunner clientRunner = new ClientRunner(); + clientRunner.setJndiPropertiesFileLocation(getJndiConfig()); + clientRunner.runClients(); + } + } + } + + private void writeResultsToFile(ResultsForAllTests resultsForAllTests, String outputFile) + { + FileWriter writer = null; + try + { + final String outputCsv = new CSVFormater().format(resultsForAllTests); + writer = new FileWriter(outputFile); + writer.write(outputCsv); + LOGGER.info("Wrote " + resultsForAllTests.getTestResults().size() + " test result(s) to output file " + outputFile); + } + catch (IOException e) + { + throw new DistributedTestException("Unable to write output file " + outputFile, e); + } + finally + { + if (writer != null) + { + try + { + writer.close(); + } + catch (IOException e) + { + LOGGER.error("Failed to close stream for file " + outputFile, e); + } + } + } + } + + private String generateOutputCsvNameFrom(String testConfigFile) + { + final String filenameOnlyWithExtension = new File(testConfigFile).getName(); + final String cvsFile = filenameOnlyWithExtension.replaceFirst(".?\\w*$", ".csv"); + final String outputDir = String.valueOf(getCliOptions().get(ControllerRunner.OUTPUT_DIR_PROP)); + + return new File(outputDir, cvsFile).getAbsolutePath(); + } + + private List getTestConfigFiles() + { + final List testConfigFile = new ArrayList(); + final File configFileOrDirectory = new File(getCliOptions().get(ControllerRunner.TEST_CONFIG_PROP)); + + if (configFileOrDirectory.isDirectory()) + { + final String[] configFiles = configFileOrDirectory.list(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return new File(dir, name).isFile() && name.endsWith(".json"); + } + }); + + for (String configFile : configFiles) + { + testConfigFile.add(new File(configFileOrDirectory, configFile).getAbsolutePath()); + } + } + else + { + testConfigFile.add(configFileOrDirectory.getAbsolutePath()); + } + + return testConfigFile; + } + + private Config buildTestConfigFrom(String testConfigFile) + { + ConfigReader configReader = new ConfigReader(); + Config testConfig; + try + { + testConfig = configReader.getConfigFromFile(testConfigFile); + } + catch (FileNotFoundException e) + { + throw new DistributedTestException("Exception while loading test config from " + testConfigFile, e); + } + return testConfig; + } + + private boolean isDistributed() + { + return Boolean.valueOf(getCliOptions().get(ControllerRunner.DISTRIBUTED_PROP)); + } + + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java b/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java new file mode 100644 index 0000000000..c4892edca9 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +public abstract class DistributedTestConstants +{ + public static final String PERF_TEST_PROPERTIES_FILE = "perftests.properties"; + + public static final String MSG_COMMAND_PROPERTY = "COMMAND"; + public static final String MSG_JSON_PROPERTY = "JSON"; + + public static final long REGISTRATION_TIMEOUT = 60000; + public static final long COMMAND_RESPONSE_TIMEOUT = 10000; + + public static final String CONTROLLER_QUEUE_JNDI_NAME = "controllerqueue"; +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestException.java b/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestException.java new file mode 100644 index 0000000000..d1d24dcfff --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestException.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import org.apache.qpid.disttest.message.Command; + +public class DistributedTestException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + private final Command causeCommand; + + public DistributedTestException(final String message) + { + this(message, (Command) null); + } + + public DistributedTestException(final Throwable cause) + { + this(cause, null); + } + + public DistributedTestException(final String message, final Throwable cause) + { + this(message, cause, null); + } + + public DistributedTestException(final String message, final Command commandCause) + { + super(message); + causeCommand = commandCause; + } + + public DistributedTestException(final Throwable cause, final Command commandCause) + { + super(cause); + causeCommand = commandCause; + } + + public DistributedTestException(final String message, final Throwable cause, final Command commandCause) + { + super(message, cause); + causeCommand = commandCause; + } + + public Command getCauseCommand() + { + return causeCommand; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/Visitor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/Visitor.java new file mode 100644 index 0000000000..52dad9aa4d --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/Visitor.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A variation of the visitor pattern that uses reflection to call the correct + * visit method. By convention, subclasses should provide public + *
visit(SpecificClass)
methods. + */ +public abstract class Visitor +{ + + private static final String VISITOR_METHOD_NAME = "visit"; + + public void visit(Object targetObject) + { + Class targetObjectClass = targetObject.getClass(); + final Method method = findVisitMethodForTargetObjectClass(targetObjectClass); + invokeVisitMethod(targetObject, method); + } + + private Method findVisitMethodForTargetObjectClass( + Class targetObjectClass) + { + final Method method; + try + { + method = getClass().getDeclaredMethod(VISITOR_METHOD_NAME, targetObjectClass); + } + catch (Exception e) + { + throw new DistributedTestException("Failed to find method " + VISITOR_METHOD_NAME + " on object of class " + targetObjectClass, e); + } + return method; + } + + private void invokeVisitMethod(Object targetObject, final Method method) + { + try + { + method.invoke(this, targetObject); + } + catch (IllegalArgumentException e) + { + throw new DistributedTestException(e); + } + catch (IllegalAccessException e) + { + throw new DistributedTestException(e); + } + catch (InvocationTargetException e) + { + throw new DistributedTestException(e.getCause()); + } + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java new file mode 100644 index 0000000000..1d2d862301 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.naming.NamingException; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.Visitor; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Client +{ + private static final Logger LOGGER = LoggerFactory.getLogger(Client.class); + + private final ClientJmsDelegate _clientJmsDelegate; + + private final CountDownLatch _latch = new CountDownLatch(1); + private Visitor _visitor; + private final AtomicReference _state; + private ParticipantExecutorRegistry _participantRegistry = new ParticipantExecutorRegistry(); + + public Client(final ClientJmsDelegate delegate) throws NamingException + { + _clientJmsDelegate = delegate; + _state = new AtomicReference(ClientState.CREATED); + _visitor = new ClientCommandVisitor(this, _clientJmsDelegate); + } + + /** + * Register with the controller + */ + public void start() + { + _clientJmsDelegate.setInstructionListener(this); + _clientJmsDelegate.sendRegistrationMessage(); + _state.set(ClientState.READY); + } + + public void stop() + { + _state.set(ClientState.STOPPED); + _latch.countDown(); + } + + public void addParticipantExecutor(final ParticipantExecutor participant) + { + _participantRegistry.add(participant); + } + + public void waitUntilStopped() + { + waitUntilStopped(0); + } + + public void waitUntilStopped(final long timeout) + { + try + { + if (timeout == 0) + { + _latch.await(); + } + else + { + _latch.await(timeout, TimeUnit.MILLISECONDS); + } + } + catch (final InterruptedException ie) + { + Thread.currentThread().interrupt(); + } + + _clientJmsDelegate.destroy(); + } + + public void processInstruction(final Command command) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Client " + getClientName() + " received command: " + command); + } + String responseMessage = null; + try + { + command.accept(_visitor); + } + catch (final Exception e) + { + LOGGER.error("Error processing instruction", e); + responseMessage = e.getMessage(); + } + finally + { + _clientJmsDelegate.sendResponseMessage(new Response(_clientJmsDelegate.getClientName(), command.getType(), responseMessage)); + } + } + + public ClientState getState() + { + return _state.get(); + } + + public String getClientName() + { + return _clientJmsDelegate.getClientName(); + } + + public void setClientCommandVisitor(final ClientCommandVisitor visitor) + { + _visitor = visitor; + } + + public void startTest() + { + if (_state.compareAndSet(ClientState.READY, ClientState.RUNNING_TEST)) + { + try + { + _clientJmsDelegate.startConnections(); + for (final ParticipantExecutor executor : _participantRegistry.executors()) + { + executor.start(this); + } + } + catch (final Exception e) + { + try + { + tearDownTest(); + } + catch (final Exception e2) + { + // ignore + } + throw new DistributedTestException("Error starting test: " + _clientJmsDelegate.getClientName(), e); + } + } + else + { + throw new DistributedTestException("Client '" + _clientJmsDelegate.getClientName() + + "' is not in READY state:" + _state.get()); + } + } + + public void tearDownTest() + { + if (_state.compareAndSet(ClientState.RUNNING_TEST, ClientState.READY)) + { + LOGGER.info("Tearing down test on client: " + _clientJmsDelegate.getClientName()); + + _clientJmsDelegate.closeTestConnections(); + } + else + { + throw new DistributedTestException("Client '" + _clientJmsDelegate.getClientName() + "' is not in RUNNING_TEST state! Ignoring tearDownTest"); + } + + + _participantRegistry.clear(); + } + + public void sendResults(ParticipantResult testResult) + { + _clientJmsDelegate.sendResponseMessage(testResult); + LOGGER.info("Sent test results " + testResult); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("clientJmsDelegate", _clientJmsDelegate).toString(); + } + + void setParticipantRegistry(ParticipantExecutorRegistry participantRegistry) + { + _participantRegistry = participantRegistry; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientCommandVisitor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientCommandVisitor.java new file mode 100644 index 0000000000..791897323e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientCommandVisitor.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import org.apache.qpid.disttest.Visitor; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.disttest.message.StartTestCommand; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.apache.qpid.disttest.message.TearDownTestCommand; + +public class ClientCommandVisitor extends Visitor +{ + private final Client _client; + private final ClientJmsDelegate _clientJmsDelegate; + + public ClientCommandVisitor(final Client client, final ClientJmsDelegate clientJmsDelegate) + { + super(); + _client = client; + _clientJmsDelegate = clientJmsDelegate; + } + + public void visit(final StopClientCommand command) + { + _client.stop(); + } + + public void visit(final NoOpCommand command) + { + // no-op + } + + public void visit(final CreateConnectionCommand command) + { + _clientJmsDelegate.createConnection(command); + } + + public void visit(final CreateSessionCommand command) + { + _clientJmsDelegate.createSession(command); + } + + public void visit(final CreateProducerCommand command) + { + + final ProducerParticipant participant = new ProducerParticipant(_clientJmsDelegate, command); + _clientJmsDelegate.createProducer(command); + final ParticipantExecutor executor = new ParticipantExecutor(participant); + _client.addParticipantExecutor(executor); + } + + public void visit(final CreateConsumerCommand command) + { + final ConsumerParticipant participant = new ConsumerParticipant(_clientJmsDelegate, command); + _clientJmsDelegate.createConsumer(command); + final ParticipantExecutor executor = new ParticipantExecutor(participant); + _client.addParticipantExecutor(executor); + } + + public void visit(final StartTestCommand command) + { + _client.startTest(); + } + + public void visit(final TearDownTestCommand command) + { + _client.tearDownTest(); + } + + public void visit(final CreateMessageProviderCommand command) + { + _clientJmsDelegate.createMessageProvider(command); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientState.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientState.java new file mode 100644 index 0000000000..c88c0a6c86 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ClientState.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +public enum ClientState +{ + CREATED, READY, STOPPED, RUNNING_TEST; +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java new file mode 100644 index 0000000000..1b5e8276c2 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java @@ -0,0 +1,251 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + + +import java.util.Date; +import java.util.NavigableSet; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import javax.jms.Message; +import javax.jms.MessageListener; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConsumerParticipant implements Participant +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerParticipant.class); + + private final AtomicInteger _totalNumberOfMessagesReceived = new AtomicInteger(0); + private final NavigableSet _allConsumedPayloadSizes = new ConcurrentSkipListSet(); + private final AtomicLong _totalPayloadSizeOfAllMessagesReceived = new AtomicLong(0); + private final CountDownLatch _asyncRunHasFinished = new CountDownLatch(1); + private final ClientJmsDelegate _jmsDelegate; + private final CreateConsumerCommand _command; + private final ParticipantResultFactory _resultFactory; + + private long _startTime; + + private volatile Exception _asyncMessageListenerException; + + public ConsumerParticipant(final ClientJmsDelegate delegate, final CreateConsumerCommand command) + { + _jmsDelegate = delegate; + _command = command; + _resultFactory = new ParticipantResultFactory(); + } + + @Override + public ParticipantResult doIt(String registeredClientName) throws Exception + { + final Date start = new Date(); + final int acknowledgeMode = _jmsDelegate.getAcknowledgeMode(_command.getSessionName()); + + if (_command.getMaximumDuration() == 0 && _command.getNumberOfMessages() == 0) + { + throw new DistributedTestException("number of messages and duration cannot both be zero"); + } + + if (_command.isSynchronous()) + { + synchronousRun(); + } + else + { + _jmsDelegate.registerListener(_command.getParticipantName(), new MessageListener(){ + + @Override + public void onMessage(Message message) + { + processAsynchMessage(message); + } + + }); + + waitUntilMsgListenerHasFinished(); + rethrowAnyAsyncMessageListenerException(); + } + + Date end = new Date(); + int numberOfMessagesSent = _totalNumberOfMessagesReceived.get(); + long totalPayloadSize = _totalPayloadSizeOfAllMessagesReceived.get(); + int payloadSize = getPayloadSizeForResultIfConstantOrZeroOtherwise(_allConsumedPayloadSizes); + + ConsumerParticipantResult result = _resultFactory.createForConsumer( + getName(), + registeredClientName, + _command, + acknowledgeMode, + numberOfMessagesSent, + payloadSize, + totalPayloadSize, + start, end); + + return result; + } + + private void synchronousRun() + { + LOGGER.debug("entered synchronousRun: " + this); + + _startTime = System.currentTimeMillis(); + + Message message = null; + + do + { + message = _jmsDelegate.consumeMessage(_command.getParticipantName(), + _command.getReceiveTimeout()); + } while (processMessage(message)); + } + + /** + * @return whether to continue running (ie returns false if the message quota has been reached) + */ + private boolean processMessage(Message message) + { + int messageCount = _totalNumberOfMessagesReceived.incrementAndGet(); + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("message " + messageCount + " received by " + this); + } + int messagePayloadSize = _jmsDelegate.calculatePayloadSizeFrom(message); + _allConsumedPayloadSizes.add(messagePayloadSize); + _totalPayloadSizeOfAllMessagesReceived.addAndGet(messagePayloadSize); + + boolean batchEnabled = _command.getBatchSize() > 0; + boolean batchComplete = batchEnabled && messageCount % _command.getBatchSize() == 0; + + if (!batchEnabled || batchComplete) + { + if (LOGGER.isTraceEnabled() && batchEnabled) + { + LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); + } + _jmsDelegate.commitOrAcknowledgeMessage(message, _command.getSessionName()); + } + + boolean reachedExpectedNumberOfMessages = _command.getNumberOfMessages() > 0 && messageCount >= _command.getNumberOfMessages(); + boolean reachedMaximumDuration = _command.getMaximumDuration() > 0 && System.currentTimeMillis() - _startTime >= _command.getMaximumDuration(); + boolean finishedConsuming = reachedExpectedNumberOfMessages || reachedMaximumDuration; + + if (finishedConsuming) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("message " + messageCount + + " reachedExpectedNumberOfMessages " + reachedExpectedNumberOfMessages + + " reachedMaximumDuration " + reachedMaximumDuration); + } + + if (batchEnabled && !batchComplete) + { + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); + } + + // commit/acknowledge remaining messages if necessary + _jmsDelegate.commitOrAcknowledgeMessage(message, _command.getSessionName()); + } + return false; + } + + return true; + } + + + /** + * Intended to be called from a {@link MessageListener}. Updates {@link #_asyncRunHasFinished} if + * no more messages should be processed, causing {@link #doIt(String)} to exit. + */ + public void processAsynchMessage(Message message) + { + boolean continueRunning = true; + try + { + if (_startTime == 0) + { + // reset counter and start time on receiving of first message + _startTime = System.currentTimeMillis(); + } + + continueRunning = processMessage(message); + } + catch (Exception e) + { + LOGGER.error("Error occured consuming message " + _totalNumberOfMessagesReceived, e); + continueRunning = false; + _asyncMessageListenerException = e; + } + + if(!continueRunning) + { + _asyncRunHasFinished.countDown(); + } + } + + @Override + public void releaseResources() + { + _jmsDelegate.closeTestConsumer(_command.getParticipantName()); + } + + private int getPayloadSizeForResultIfConstantOrZeroOtherwise(NavigableSet allSizes) + { + return allSizes.size() == 1 ? _allConsumedPayloadSizes.first() : 0; + } + + private void rethrowAnyAsyncMessageListenerException() + { + if (_asyncMessageListenerException != null) + { + throw new DistributedTestException(_asyncMessageListenerException); + } + } + + private void waitUntilMsgListenerHasFinished() throws Exception + { + LOGGER.debug("waiting until message listener has finished for " + this); + _asyncRunHasFinished.await(); + LOGGER.debug("Message listener has finished for " + this); + } + + @Override + public String getName() + { + return _command.getParticipantName(); + } + + @Override + public String toString() + { + return "ConsumerParticipant [_command=" + _command + ", _startTime=" + _startTime + "]"; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java new file mode 100644 index 0000000000..2dcf8940b6 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java @@ -0,0 +1,212 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.message.CreateProducerCommand; + +public class MessageProvider +{ + public static final String TTL = "ttl"; + + public static final String DELIVERY_MODE = "deliveryMode"; + + public static final String PRIORITY = "priority"; + + public static final String[] STANDARD_JMS_PROPERTIES = { "correlationID", DELIVERY_MODE, + "expiration", "messageID", PRIORITY, "redelivered", "replyTo", "timestamp", "type", TTL }; + + private Map _messageProperties; + private ConcurrentMap> _payloads; + + public MessageProvider(Map messageProperties) + { + _messageProperties = messageProperties; + _payloads = new ConcurrentHashMap>(); + } + + public Message nextMessage(Session session, CreateProducerCommand command) throws JMSException + { + Message message = createTextMessage(session, command); + setMessageProperties(message); + return message; + } + + public boolean isPropertySet(String name) + { + return _messageProperties != null && _messageProperties.containsKey(name); + } + + public void setMessageProperties(Message message) throws JMSException + { + if (_messageProperties != null) + { + for (Entry entry : _messageProperties.entrySet()) + { + String propertyName = entry.getKey(); + Object propertyValue = entry.getValue().getValue(); + if (isStandardProperty(propertyName)) + { + setStandardProperty(message, propertyName, propertyValue); + } + else + { + setCustomProperty(message, propertyName, propertyValue); + } + } + } + } + + protected void setCustomProperty(Message message, String propertyName, Object propertyValue) throws JMSException + { + if (propertyValue instanceof Integer) + { + message.setIntProperty(propertyName, ((Integer) propertyValue).intValue()); + } + else if (propertyValue instanceof Long) + { + message.setLongProperty(propertyName, ((Long) propertyValue).longValue()); + } + else if (propertyValue instanceof Boolean) + { + message.setBooleanProperty(propertyName, ((Boolean) propertyValue).booleanValue()); + } + else if (propertyValue instanceof Byte) + { + message.setByteProperty(propertyName, ((Byte) propertyValue).byteValue()); + } + else if (propertyValue instanceof Double) + { + message.setDoubleProperty(propertyName, ((Double) propertyValue).doubleValue()); + } + else if (propertyValue instanceof Float) + { + message.setFloatProperty(propertyName, ((Float) propertyValue).floatValue()); + } + else if (propertyValue instanceof Short) + { + message.setShortProperty(propertyName, ((Short) propertyValue).shortValue()); + } + else if (propertyValue instanceof String) + { + message.setStringProperty(propertyName, (String) propertyValue); + } + else + { + message.setObjectProperty(propertyName, propertyValue); + } + } + + protected void setStandardProperty(Message message, String property, Object propertyValue) throws JMSException + { + String propertyName = "JMS" + StringUtils.capitalize(property); + try + { + BeanUtils.setProperty(message, propertyName, propertyValue); + } + catch (IllegalAccessException e) + { + throw new DistributedTestException("Unable to set property " + propertyName + " :" + e.getMessage(), e); + } + catch (InvocationTargetException e) + { + if (e.getCause() instanceof JMSException) + { + throw ((JMSException) e.getCause()); + } + else + { + throw new DistributedTestException("Unable to set property " + propertyName + " :" + e.getMessage(), e); + } + } + } + + protected boolean isStandardProperty(String propertyName) + { + for (int i = 0; i < STANDARD_JMS_PROPERTIES.length; i++) + { + if (propertyName.equals(STANDARD_JMS_PROPERTIES[i])) + { + return true; + } + } + return false; + } + + protected Message createTextMessage(Session ssn, final CreateProducerCommand command) throws JMSException + { + String payload = getMessagePayload(command); + TextMessage msg = ssn.createTextMessage(); + msg.setText(payload); + return msg; + } + + protected String getMessagePayload(final CreateProducerCommand command) + { + FutureTask createTextFuture = new FutureTask(new Callable() + { + @Override + public String call() throws Exception + { + return StringUtils.repeat("a", command.getMessageSize()); + } + }); + + Future future = _payloads.putIfAbsent(command.getMessageSize(), createTextFuture); + if (future == null) + { + createTextFuture.run(); + future = createTextFuture; + } + String payload = null; + try + { + payload = future.get(); + } + catch (Exception e) + { + throw new DistributedTestException("Unable to create message payload :" + e.getMessage(), e); + } + return payload; + } + + @Override + public String toString() + { + return "MessageProvider [_messageProperties=" + _messageProperties + "]"; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/Participant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/Participant.java new file mode 100644 index 0000000000..941ec90565 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/Participant.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import org.apache.qpid.disttest.message.ParticipantResult; + +public interface Participant +{ + ParticipantResult doIt(String registeredClientName) throws Exception; + + void releaseResources(); + + String getName(); + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java new file mode 100644 index 0000000000..d5e307d50f --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ParticipantExecutor +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantExecutor.class); + + private static final ExecutorService SHARED_UNBOUNDED_THREAD_POOL = Executors.newCachedThreadPool(new DaemonThreadFactory()); + + private Executor _executor = SHARED_UNBOUNDED_THREAD_POOL; + + private Client _client; + + private final Participant _participant; + + private final ParticipantResultFactory _factory; + + public ParticipantExecutor(Participant participant) + { + _participant = participant; + _factory = new ParticipantResultFactory(); + } + + /** + * Schedules the test participant to be run in a background thread. + */ + public void start(Client client) + { + _client = client; + + LOGGER.info("Starting test participant in background thread: " + this); + _executor.execute(new ParticipantRunnable()); + } + + public String getParticipantName() + { + return _participant.getName(); + } + + void setExecutor(Executor executor) + { + _executor = executor; + } + + private class ParticipantRunnable implements Runnable + { + @Override + public final void run() + { + Thread currentThread = Thread.currentThread(); + final String initialThreadName = currentThread.getName(); + currentThread.setName(initialThreadName + "-" + getParticipantName()); + + try + { + runParticipantAndSendResults(); + } + finally + { + currentThread.setName(initialThreadName); + } + } + + private void runParticipantAndSendResults() + { + ParticipantResult result = null; + try + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("About to run participant " + _participant); + } + result = _participant.doIt(_client.getClientName()); + } + catch (Throwable t) + { + String errorMessage = "Unhandled error: " + t.getMessage(); + LOGGER.error(errorMessage, t); + result = _factory.createForError(_participant.getName(), _client.getClientName(), errorMessage); + } + finally + { + _client.sendResults(result); + _participant.releaseResources(); + } + } + } + + private static final class DaemonThreadFactory implements ThreadFactory + { + @Override + public Thread newThread(Runnable r) + { + Thread thread = new Thread(r); + thread.setDaemon(true); + return thread; + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("participantName", getParticipantName()) + .append("client", _client) + .toString(); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutorRegistry.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutorRegistry.java new file mode 100644 index 0000000000..3d9780e640 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutorRegistry.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class ParticipantExecutorRegistry +{ + private final Set _participantExecutors = Collections.synchronizedSet(new HashSet()); + + public void add(ParticipantExecutor participantExecutor) + { + _participantExecutors.add(participantExecutor); + } + + public void clear() + { + _participantExecutors.clear(); + } + + public Collection executors() + { + return Collections.unmodifiableSet(_participantExecutors); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java new file mode 100644 index 0000000000..7f6b96b87c --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import java.util.Date; + +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateParticpantCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; + +public class ParticipantResultFactory +{ + public ConsumerParticipantResult createForConsumer(String participantName, String clientRegisteredName, CreateConsumerCommand command, int acknowledgeMode, int numberOfMessagesReceived, int payloadSize, long totalPayloadReceived, Date start, Date end) + { + ConsumerParticipantResult consumerParticipantResult = new ConsumerParticipantResult(); + + setTestProperties(consumerParticipantResult, command, participantName, clientRegisteredName, acknowledgeMode); + setTestResultProperties(consumerParticipantResult, numberOfMessagesReceived, payloadSize, totalPayloadReceived, start, end); + + consumerParticipantResult.setTopic(command.isTopic()); + consumerParticipantResult.setDurableSubscription(command.isDurableSubscription()); + consumerParticipantResult.setBrowsingSubscription(command.isBrowsingSubscription()); + consumerParticipantResult.setSelector(command.getSelector() != null); + consumerParticipantResult.setNoLocal(command.isNoLocal()); + consumerParticipantResult.setSynchronousConsumer(command.isSynchronous()); + consumerParticipantResult.setTotalNumberOfConsumers(1); + consumerParticipantResult.setTotalNumberOfProducers(0); + + return consumerParticipantResult; + } + + public ProducerParticipantResult createForProducer(String participantName, String clientRegisteredName, CreateProducerCommand command, int acknowledgeMode, int numberOfMessagesSent, int payloadSize, long totalPayloadSent, Date start, Date end) + { + final ProducerParticipantResult producerParticipantResult = new ProducerParticipantResult(); + + producerParticipantResult.setStartDelay(command.getStartDelay()); + producerParticipantResult.setDeliveryMode(command.getDeliveryMode()); + producerParticipantResult.setPriority(command.getPriority()); + producerParticipantResult.setInterval(command.getInterval()); + producerParticipantResult.setTimeToLive(command.getTimeToLive()); + producerParticipantResult.setTotalNumberOfConsumers(0); + producerParticipantResult.setTotalNumberOfProducers(1); + + + setTestProperties(producerParticipantResult, command, participantName, clientRegisteredName, acknowledgeMode); + + setTestResultProperties(producerParticipantResult, numberOfMessagesSent, payloadSize, totalPayloadSent, start, end); + + return producerParticipantResult; + } + + private void setTestResultProperties(final ParticipantResult participantResult, int numberOfMessagesSent, int payloadSize, long totalPayloadReceived, Date start, Date end) + { + participantResult.setNumberOfMessagesProcessed(numberOfMessagesSent); + participantResult.setPayloadSize(payloadSize); + participantResult.setTotalPayloadProcessed(totalPayloadReceived); + participantResult.setStartDate(start); + participantResult.setEndDate(end); + } + + private void setTestProperties(final ParticipantResult participantResult, CreateParticpantCommand command, String participantName, String clientRegisteredName, int acknowledgeMode) + { + participantResult.setParticipantName(participantName); + participantResult.setRegisteredClientName(clientRegisteredName); + participantResult.setBatchSize(command.getBatchSize()); + participantResult.setMaximumDuration(command.getMaximumDuration()); + participantResult.setAcknowledgeMode(acknowledgeMode); + + } + + public ParticipantResult createForError(String participantName, String clientRegisteredName, String errorMessage) + { + ParticipantResult result = new ParticipantResult(); + result.setParticipantName(participantName); + result.setRegisteredClientName(clientRegisteredName); + result.setErrorMessage(errorMessage); + + return result; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java new file mode 100644 index 0000000000..bcad81b4aa --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import java.util.Date; +import java.util.NavigableSet; +import java.util.TreeSet; + +import javax.jms.Message; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ProducerParticipant implements Participant +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ProducerParticipant.class); + + private final ClientJmsDelegate _jmsDelegate; + + private final CreateProducerCommand _command; + + private ParticipantResultFactory _resultFactory; + + public ProducerParticipant(final ClientJmsDelegate jmsDelegate, final CreateProducerCommand command) + { + _jmsDelegate = jmsDelegate; + _command = command; + _resultFactory = new ParticipantResultFactory(); + } + + @Override + public ParticipantResult doIt(String registeredClientName) throws Exception + { + if (_command.getMaximumDuration() == 0 && _command.getNumberOfMessages() == 0) + { + throw new DistributedTestException("number of messages and duration cannot both be zero"); + } + + int acknowledgeMode = _jmsDelegate.getAcknowledgeMode(_command.getSessionName()); + + long expectedDuration = _command.getMaximumDuration() - _command.getStartDelay(); + + doSleepForStartDelay(); + + final long startTime = System.currentTimeMillis(); + + Message lastPublishedMessage = null; + int numberOfMessagesSent = 0; + long totalPayloadSizeOfAllMessagesSent = 0; + NavigableSet allProducedPayloadSizes = new TreeSet(); + + while (true) + { + numberOfMessagesSent++; + + lastPublishedMessage = _jmsDelegate.sendNextMessage(_command); + + int lastPayloadSize = _jmsDelegate.calculatePayloadSizeFrom(lastPublishedMessage); + totalPayloadSizeOfAllMessagesSent += lastPayloadSize; + allProducedPayloadSizes.add(lastPayloadSize); + + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("message " + numberOfMessagesSent + " sent by " + this); + } + + final boolean batchLimitReached = _command.getBatchSize() <= 0 + || numberOfMessagesSent % _command.getBatchSize() == 0; + + if (batchLimitReached) + { + if (LOGGER.isTraceEnabled() && _command.getBatchSize() > 0) + { + LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); + } + _jmsDelegate.commitOrAcknowledgeMessage(lastPublishedMessage, _command.getSessionName()); + + if (_command.getInterval() > 0) + { + // sleep for given time + Thread.sleep(_command.getInterval()); + } + } + + if (_command.getNumberOfMessages() > 0 && numberOfMessagesSent >= _command.getNumberOfMessages() + || expectedDuration > 0 && System.currentTimeMillis() - startTime >= expectedDuration) + { + break; + } + } + + // commit the remaining batch messages + if (_command.getBatchSize() > 0 && numberOfMessagesSent % _command.getBatchSize() != 0) + { + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); + } + _jmsDelegate.commitOrAcknowledgeMessage(lastPublishedMessage, _command.getSessionName()); + } + + Date start = new Date(startTime); + Date end = new Date(); + int payloadSize = getPayloadSizeForResultIfConstantOrZeroOtherwise(allProducedPayloadSizes); + + return _resultFactory.createForProducer( + getName(), + registeredClientName, + _command, + acknowledgeMode, + numberOfMessagesSent, + payloadSize, totalPayloadSizeOfAllMessagesSent, start, end); + } + + private int getPayloadSizeForResultIfConstantOrZeroOtherwise(NavigableSet allPayloadSizes) + { + return allPayloadSizes.size() == 1 ? allPayloadSizes.first() : 0; + } + + private void doSleepForStartDelay() + { + if (_command.getStartDelay() > 0) + { + // start delay is specified. Sleeping... + try + { + Thread.sleep(_command.getStartDelay()); + } + catch (final InterruptedException e) + { + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void releaseResources() + { + _jmsDelegate.closeTestProducer(_command.getParticipantName()); + } + + @Override + public String getName() + { + return _command.getParticipantName(); + } + + @Override + public String toString() + { + return "ProducerParticipant [command=" + _command + "]"; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertySupport.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertySupport.java new file mode 100644 index 0000000000..a49ebf756e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertySupport.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +/** + * Provides support to generate message property values. + */ +public abstract class GeneratedPropertySupport implements GeneratedPropertyValue +{ + private Object _lastValue; + + public GeneratedPropertySupport() + { + super(); + _lastValue = null; + } + + @Override + public Object getValue() + { + Object result = nextValue(); + result = evaluate(result); + synchronized(this) + { + _lastValue = result; + } + return result; + } + + protected Object evaluate(Object result) + { + while (result instanceof PropertyValue) + { + result = ((PropertyValue)result).getValue(); + } + return result; + } + + public abstract Object nextValue(); + + public synchronized Object getLastValue() + { + return _lastValue; + } + + @Override + public String toString() + { + return "GeneratedPropertyValue [value=" + getLastValue() + ", @def=" + getDefinition() + "]"; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertyValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertyValue.java new file mode 100644 index 0000000000..39c093fac5 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/GeneratedPropertyValue.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +/** + * Provides operations to generate message property values. + */ +public interface GeneratedPropertyValue extends PropertyValue +{ + public String getDefinition(); +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/ListPropertyValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/ListPropertyValue.java new file mode 100644 index 0000000000..4444351976 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/ListPropertyValue.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Provides property values from the underlining list of items. + */ +public class ListPropertyValue extends GeneratedPropertySupport +{ + public static final String DEF_VALUE = "list"; + private List _items; + private boolean _cyclic; + private int _currentIndex; + + public ListPropertyValue() + { + super(); + _cyclic = true; + _currentIndex = 0; + _items = new ArrayList(); + } + + public synchronized void setItems(List items) + { + _items = new ArrayList(items); + } + + public synchronized List getItems() + { + return Collections.unmodifiableList(_items); + } + + public synchronized void setCyclic(boolean cyclic) + { + _cyclic = cyclic; + } + + public synchronized boolean isCyclic() + { + return _cyclic; + } + + @Override + public synchronized Object nextValue() + { + if (_currentIndex >= _items.size()) + { + if (_cyclic) + { + _currentIndex = 0; + } + else + { + _currentIndex = _items.size() -1; + } + } + Object nextValue = _items.get(_currentIndex); + _currentIndex++; + return nextValue; + } + + @Override + public String getDefinition() + { + return DEF_VALUE; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + _currentIndex; + result = prime * result + (_cyclic ? 1231 : 1237); + result = prime * result + ((_items == null) ? 0 : _items.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null || !(obj instanceof ListPropertyValue)) + { + return false; + } + ListPropertyValue other = (ListPropertyValue) obj; + if (_cyclic != other._cyclic) + { + return false; + } + if (_items == null && other._items != null) + { + return false; + } + return _items.equals(other._items); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/NumericGeneratedPropertySupport.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/NumericGeneratedPropertySupport.java new file mode 100644 index 0000000000..e0ae137c35 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/NumericGeneratedPropertySupport.java @@ -0,0 +1,179 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import java.util.Arrays; + +/** + * Provides support for numeric generators with lower and upper boundaries. + */ +public abstract class NumericGeneratedPropertySupport extends GeneratedPropertySupport +{ + public static final Class[] SUPPORTED_TYPES = { double.class, float.class, int.class, long.class, short.class, + byte.class }; + + private String _type; + private double _upper; + private double _lower; + + + public NumericGeneratedPropertySupport() + { + super(); + _type = SUPPORTED_TYPES[0].getName(); + _upper = Double.MAX_VALUE; + _lower = 0.0; + } + + public synchronized String getType() + { + return _type; + } + + public synchronized double getUpper() + { + return _upper; + } + + public synchronized double getLower() + { + return _lower; + } + + public synchronized void setUpper(double upper) + { + _upper = upper; + } + + public synchronized void setLower(double lower) + { + _lower = lower; + } + + public synchronized void setType(String type) + { + _type = toClass(type).getName(); + } + + protected Class toClass(String type) + { + Class t = null; + for (int i = 0; i < SUPPORTED_TYPES.length; i++) + { + if (SUPPORTED_TYPES[i].getName().equals(type)) + { + t = SUPPORTED_TYPES[i]; + break; + } + } + if (t == null) + { + throw new IllegalArgumentException("Type " + type + " is not supported: " + + Arrays.toString(SUPPORTED_TYPES)); + } + return t; + } + + @Override + public Object nextValue() + { + double result = nextDouble(); + return doubleToNumber(result, toClass(_type)); + } + + protected Number doubleToNumber(double value, Class targetType) + { + Number result = null; + if (targetType == double.class) + { + result = new Double(value); + } + else if (targetType == float.class) + { + result = new Float(value); + } + else if (targetType == int.class) + { + result = new Integer((int) value); + } + else if (targetType == long.class) + { + result = new Long((long) value); + } + else if (targetType == short.class) + { + result = new Short((short) value); + } + else if (targetType == byte.class) + { + result = new Byte((byte) value); + } + else + { + throw new IllegalArgumentException("Type " + targetType + " is not supported: " + + Arrays.toString(SUPPORTED_TYPES)); + } + return result; + } + + protected abstract double nextDouble(); + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + long temp; + temp = Double.doubleToLongBits(_lower); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((_type == null) ? 0 : _type.hashCode()); + temp = Double.doubleToLongBits(_upper); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null || !(obj instanceof NumericGeneratedPropertySupport)) + { + return false; + } + NumericGeneratedPropertySupport other = (NumericGeneratedPropertySupport) obj; + if (Double.doubleToLongBits(_lower) != Double.doubleToLongBits(other._lower) + || Double.doubleToLongBits(_upper) != Double.doubleToLongBits(other._upper)) + { + return false; + } + if (_type == null && other._type != null) + { + return false; + } + else if (!_type.equals(other._type)) + { + return false; + } + return true; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValue.java new file mode 100644 index 0000000000..97adc0cee1 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValue.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +/** + * Provides operations to get a message property value. + */ +public interface PropertyValue +{ + public Object getValue(); +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValueFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValueFactory.java new file mode 100644 index 0000000000..fa44b2da1e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/PropertyValueFactory.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.disttest.DistributedTestException; + +/** + * Creates property value instances using given alias (type) value. + */ +public class PropertyValueFactory +{ + public PropertyValue createPropertyValue(String type) + { + try + { + return (PropertyValue)getPropertyValueClass(type).newInstance(); + } + catch(Exception e) + { + throw new DistributedTestException("Unable to create a generator for a type:" + type, e); + } + } + + public Class getPropertyValueClass(String type) throws ClassNotFoundException + { + String className = "org.apache.qpid.disttest.client.property." + StringUtils.capitalize(type) + "PropertyValue"; + return Class.forName(className); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RandomPropertyValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RandomPropertyValue.java new file mode 100644 index 0000000000..4f44a4bca8 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RandomPropertyValue.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +/** + * Generates random property values in a given lower and upper boundaries. + */ +public class RandomPropertyValue extends NumericGeneratedPropertySupport +{ + public static final String DEF_VALUE = "random"; + + public RandomPropertyValue() + { + super(); + } + + @Override + protected double nextDouble() + { + double lower = getLower(); + double upper = getUpper(); + return lower + Math.random() * (upper - lower); + } + + @Override + public String getDefinition() + { + return DEF_VALUE; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RangePropertyValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RangePropertyValue.java new file mode 100644 index 0000000000..3aca4d4bca --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/RangePropertyValue.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +/** + * Generates property values from a range with given lower and upper boundaries. + */ +public class RangePropertyValue extends NumericGeneratedPropertySupport +{ + public static final String DEF_VALUE = "range"; + private double _step; + private double _currentValue; + private boolean _cyclic; + + public RangePropertyValue() + { + super(); + _cyclic = true; + _currentValue = 0.0; + _step = 1.0; + } + + public synchronized double getStep() + { + return _step; + } + + public synchronized boolean isCyclic() + { + return _cyclic; + } + + public synchronized void setCyclic(boolean cyclic) + { + _cyclic = cyclic; + } + + public synchronized void setStep(double step) + { + _step = step; + } + + @Override + public synchronized double nextDouble() + { + double result = 0.0; + double lower = getLower(); + double upper = getUpper(); + if (_currentValue < lower) + { + _currentValue = lower; + } + else if (_currentValue > upper) + { + if (_cyclic) + { + _currentValue = lower; + } + else + { + _currentValue = upper; + } + } + result = _currentValue; + _currentValue += _step; + return result; + } + + @Override + public String getDefinition() + { + return DEF_VALUE; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + long temp; + temp = Double.doubleToLongBits(_currentValue); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + (_cyclic ? 1231 : 1237); + temp = Double.doubleToLongBits(_step); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RangePropertyValue)) + { + return false; + } + if (!super.equals(obj)) + { + return false; + } + RangePropertyValue other = (RangePropertyValue) obj; + if (Double.doubleToLongBits(_currentValue) != Double.doubleToLongBits(other._currentValue) + || Double.doubleToLongBits(_step) != Double.doubleToLongBits(other._step) || _cyclic != other._cyclic) + { + return false; + } + + return true; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/SimplePropertyValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/SimplePropertyValue.java new file mode 100644 index 0000000000..9141e68656 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/property/SimplePropertyValue.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +/** + * Simple property value holder for a constant properties. + */ +public class SimplePropertyValue implements PropertyValue +{ + private Object _value; + + public SimplePropertyValue() + { + super(); + } + + public SimplePropertyValue(Object value) + { + super(); + this._value = value; + } + + @Override + public Object getValue() + { + return _value; + } + + @Override + public String toString() + { + return "SimplePropertyValue [value=" + _value + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((_value == null) ? 0 : _value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null || getClass() != obj.getClass()) + { + return false; + } + SimplePropertyValue other = (SimplePropertyValue) obj; + if (_value == null && other._value != null) + { + return false; + } + return _value.equals(other._value); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java new file mode 100644 index 0000000000..eaccb54f0e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; + +import org.apache.qpid.disttest.DistributedTestException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClientRegistry +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ClientRegistry.class); + + private final Set _registeredClientNames = new ConcurrentSkipListSet(); + + private final Object _lock = new Object(); + + public void registerClient(String clientName) + { + final boolean alreadyContainsClient = !_registeredClientNames.add(clientName); + if (alreadyContainsClient) + { + throw new DistributedTestException("Duplicate client name " + clientName); + } + + notifyAllWaiters(); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Client registered: " + clientName); + } + } + + + public Collection getClients() + { + return Collections.unmodifiableSet(_registeredClientNames); + } + + public int awaitClients(int numberOfClientsToAwait, long timeout) + { + final long endTime = System.currentTimeMillis() + timeout; + + int numberOfClientsAbsent = numberOfClientsToAwait - _registeredClientNames.size(); + long remainingTimeout = endTime - System.currentTimeMillis(); + + while(numberOfClientsAbsent > 0 && remainingTimeout > 0) + { + synchronized (_lock) + { + try + { + _lock.wait(remainingTimeout); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + } + } + + numberOfClientsAbsent = numberOfClientsToAwait - _registeredClientNames.size(); + remainingTimeout = endTime - System.currentTimeMillis(); + } + + return numberOfClientsAbsent < 0 ? 0 : numberOfClientsAbsent; + } + + private void notifyAllWaiters() + { + synchronized (_lock) + { + _lock.notifyAll(); + } + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandForClient.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandForClient.java new file mode 100644 index 0000000000..6c0c253807 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandForClient.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller; + +import org.apache.qpid.disttest.message.Command; + +public class CommandForClient +{ + private String _clientName; + private Command _command; + + public CommandForClient(String clientName, Command command) + { + _clientName = clientName; + _command = command; + } + + public String getClientName() + { + return _clientName; + } + + public Command getCommand() + { + return _command; + } + + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandListener.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandListener.java new file mode 100644 index 0000000000..e2f40bebe8 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/CommandListener.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller; + +import org.apache.qpid.disttest.message.Command; + +public interface CommandListener +{ + + public abstract void processCommand(Command command); + + public boolean supports(Command command); + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java new file mode 100644 index 0000000000..7c935065f0 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller; + +import java.util.Collection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.config.Config; +import org.apache.qpid.disttest.controller.config.TestInstance; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Controller +{ + private static final Logger LOGGER = LoggerFactory.getLogger(Controller.class); + + private final long _registrationTimeout; + private final long _commandResponseTimeout; + + private final ControllerJmsDelegate _jmsDelegate; + + private volatile CountDownLatch _stopClientsResponseLatch = null; + + private Config _config; + private TestRunnerFactory _testRunnerFactory; + private ClientRegistry _clientRegistry; + + private long _testResultTimeout = TestRunner.WAIT_FOREVER; + + public Controller(final ControllerJmsDelegate jmsDelegate, long registrationTimeout, long commandResponseTimeout) + { + _jmsDelegate = jmsDelegate; + _registrationTimeout = registrationTimeout; + _commandResponseTimeout = commandResponseTimeout; + _testRunnerFactory = new TestRunnerFactory(); + _clientRegistry = new ClientRegistry(); + + _jmsDelegate.addCommandListener(new RegisterClientCommandListener()); + _jmsDelegate.addCommandListener(new StopClientResponseListener()); + _jmsDelegate.start(); + } + + public void setConfig(Config config) + { + _config = config; + validateConfiguration(); + } + + public void awaitClientRegistrations() + { + LOGGER.info("Awaiting client registrations"); + + final int numberOfAbsentClients = _clientRegistry.awaitClients(_config.getTotalNumberOfClients(), _registrationTimeout); + if (numberOfAbsentClients > 0) + { + String formattedMessage = String.format("Timed out waiting for registrations. Expecting %d more registrations", numberOfAbsentClients); + throw new DistributedTestException(formattedMessage); + } + + } + + private void validateConfiguration() + { + if (_config == null || _config.getTotalNumberOfClients() == 0) + { + throw new DistributedTestException("No controller config or no clients specified in test config"); + } + } + + private void awaitLatch(CountDownLatch latch, long timeout, String messageWithOneDecimalPlaceholder) + { + try + { + final boolean countedDownOK = latch.await(timeout, TimeUnit.MILLISECONDS); + if (!countedDownOK) + { + final long latchCount = latch.getCount(); + String formattedMessage = String.format(messageWithOneDecimalPlaceholder, latchCount); + throw new DistributedTestException(formattedMessage); + } + } + catch (final InterruptedException e) + { + Thread.currentThread().interrupt(); + } + } + + public void registerClient(final RegisterClientCommand registrationCommand) + { + final String clientName = registrationCommand.getClientName(); + + _jmsDelegate.registerClient(registrationCommand); + _clientRegistry.registerClient(clientName); + } + + void processStopClientResponse(final Response response) + { + // TODO clientRegistry should expose a deregisterClient + _stopClientsResponseLatch.countDown(); + if (response.hasError()) + { + LOGGER.error("Client " + response.getRegisteredClientName() + " reported exception in response to command : " + + response.getErrorMessage()); + } + } + + public void stopAllRegisteredClients() + { + Collection registeredClients = _clientRegistry.getClients(); + + LOGGER.info("Stopping all clients"); + _stopClientsResponseLatch = new CountDownLatch(registeredClients.size()); + Command command = new StopClientCommand(); + for (final String clientName : registeredClients) + { + _jmsDelegate.sendCommandToClient(clientName, command); + } + + awaitLatch(_stopClientsResponseLatch, _commandResponseTimeout, "Timed out waiting for stop command responses. Expecting %d more responses."); + + LOGGER.info("Stopped all clients"); + } + + + public ResultsForAllTests runAllTests() + { + LOGGER.info("Running all tests"); + + ResultsForAllTests resultsForAllTests = new ResultsForAllTests(); + + for (TestInstance testInstance : _config.getTests()) + { + + ParticipatingClients participatingClients = new ParticipatingClients(_clientRegistry, testInstance.getClientNames()); + + LOGGER.info("Running test " + testInstance + ". Participating clients: " + participatingClients.getRegisteredNames()); + TestRunner runner = _testRunnerFactory.createTestRunner(participatingClients, + testInstance, + _jmsDelegate, + _commandResponseTimeout, + _testResultTimeout); + + TestResult testResult = runner.run(); + LOGGER.info("Finished test " + testInstance); + + resultsForAllTests.add(testResult); + } + + return resultsForAllTests; + } + + private final class StopClientResponseListener implements CommandListener + { + @Override + public boolean supports(Command command) + { + return command.getType() == CommandType.RESPONSE && ((Response)command).getInReplyToCommandType() == CommandType.STOP_CLIENT; + } + + @Override + public void processCommand(Command command) + { + processStopClientResponse((Response)command); + } + } + + private final class RegisterClientCommandListener implements + CommandListener + { + @Override + public boolean supports(Command command) + { + return command.getType() == CommandType.REGISTER_CLIENT; + } + + @Override + public void processCommand(Command command) + { + registerClient((RegisterClientCommand)command); + } + } + + public void setTestResultTimeout(final long testResultTimeout) + { + _testResultTimeout = testResultTimeout; + + } + + void setClientRegistry(ClientRegistry clientRegistry) + { + _clientRegistry = clientRegistry; + + } + + void setTestRunnerFactory(TestRunnerFactory factory) + { + if (factory == null) + { + throw new IllegalArgumentException("TestRunnerFactory cannot be null!"); + } + _testRunnerFactory = factory; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ParticipatingClients.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ParticipatingClients.java new file mode 100644 index 0000000000..077d628697 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ParticipatingClients.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import java.util.Collection; +import java.util.List; +import java.util.TreeSet; + +import org.apache.commons.collections.BidiMap; +import org.apache.commons.collections.bidimap.DualHashBidiMap; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class ParticipatingClients +{ + private final BidiMap _configuredToRegisteredNameMap; + + public ParticipatingClients(ClientRegistry clientRegistry, List configuredClientNamesForTest) + { + _configuredToRegisteredNameMap = mapConfiguredToRegisteredClientNames(configuredClientNamesForTest, clientRegistry); + } + + public String getRegisteredNameFromConfiguredName(String clientConfiguredName) + { + String registeredClientName = (String) _configuredToRegisteredNameMap.get(clientConfiguredName); + if (registeredClientName == null) + { + throw new IllegalArgumentException("Unrecognised client configured name " + clientConfiguredName + + " Mapping is " + _configuredToRegisteredNameMap); + } + return registeredClientName; + } + + public String getConfiguredNameFromRegisteredName(String registeredClientName) + { + String clientConfiguredName = (String) _configuredToRegisteredNameMap.getKey(registeredClientName); + if (clientConfiguredName == null) + { + throw new IllegalArgumentException("Unrecognised client registered name " + registeredClientName + + " Mapping is " + _configuredToRegisteredNameMap); + } + + return clientConfiguredName; + } + + private BidiMap mapConfiguredToRegisteredClientNames(List configuredClientNamesForTest, ClientRegistry clientRegistry) + { + BidiMap configuredToRegisteredNameMap = new DualHashBidiMap(); + + TreeSet registeredClients = new TreeSet(clientRegistry.getClients()); + for (String configuredClientName : configuredClientNamesForTest) + { + String allocatedClientName = registeredClients.pollFirst(); + if (allocatedClientName == null) + { + throw new IllegalArgumentException("Too few clients in registry " + clientRegistry + " configured clients " + configuredClientNamesForTest); + } + configuredToRegisteredNameMap.put(configuredClientName, allocatedClientName); + } + + return configuredToRegisteredNameMap; + } + + @SuppressWarnings("unchecked") + public Collection getRegisteredNames() + { + return _configuredToRegisteredNameMap.values(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("configuredToRegisteredNameMap", _configuredToRegisteredNameMap).toString(); + } + + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java new file mode 100644 index 0000000000..6c5ff3450c --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +public class ResultsForAllTests +{ + private List _results = new ArrayList(); + private boolean _hasErrors; + + public List getTestResults() + { + return _results; + } + + public void add(ITestResult testResult) + { + _results.add(testResult); + if(testResult.hasErrors()) + { + _hasErrors = true; + } + } + + public boolean hasErrors() + { + return _hasErrors; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestResult.java new file mode 100644 index 0000000000..756c641532 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestResult.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +public class TestResult implements ITestResult +{ + private final SortedSet _participantResults = Collections.synchronizedSortedSet( + new TreeSet(ParticipantResult.PARTICIPANT_NAME_COMPARATOR)); + + private boolean _hasErrors; + private String _name; + + public TestResult(String name) + { + _name = name; + } + + @Override + public List getParticipantResults() + { + List list = new ArrayList(_participantResults); + return Collections.unmodifiableList(list); + } + + public void addParticipantResult(ParticipantResult participantResult) + { + _participantResults.add(participantResult); + if(participantResult.hasError()) + { + _hasErrors = true; + } + } + + @Override + public boolean hasErrors() + { + return _hasErrors; + } + + @Override + public String getName() + { + return _name; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java new file mode 100644 index 0000000000..30595269b3 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java @@ -0,0 +1,342 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.config.QueueConfig; +import org.apache.qpid.disttest.controller.config.TestInstance; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StartTestCommand; +import org.apache.qpid.disttest.message.TearDownTestCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestRunner +{ + private static final Logger LOGGER = LoggerFactory.getLogger(TestRunner.class); + + private static final long PARTICIPANT_RESULTS_LOG_INTERVAL = 60000; + public static final long WAIT_FOREVER = -1; + + private final long _commandResponseTimeout; + + private final Set _setOfResponsesToExpect = Collections.synchronizedSet(new HashSet()); + + private final ParticipatingClients _participatingClients; + + private final TestInstance _testInstance; + private ControllerJmsDelegate _jmsDelegate; + + private volatile CountDownLatch _commandResponseLatch = null; + private final CountDownLatch _testResultsLatch; + private final TestResult _testResult; + + /** Length of time to await test results or {@value #WAIT_FOREVER} */ + private final long _testResultTimeout; + + private Thread _removeQueuesShutdownHook = new Thread() + { + @Override + public void run() + { + LOGGER.info("Shutdown intercepted: deleting test queues"); + try + { + deleteQueues(); + } + catch (Throwable t) + { + LOGGER.error("Failed to delete test queues during shutdown", t); + } + } + }; + + public TestRunner(ParticipatingClients participatingClients, TestInstance testInstance, ControllerJmsDelegate jmsDelegate, long commandResponseTimeout, long testResultTimeout) + { + _participatingClients = participatingClients; + _testInstance = testInstance; + _jmsDelegate = jmsDelegate; + _commandResponseTimeout = commandResponseTimeout; + _testResultsLatch = new CountDownLatch(testInstance.getTotalNumberOfParticipants()); + _testResultTimeout = testResultTimeout; + _testResult = new TestResult(testInstance.getName()); + } + + public TestResult run() + { + final ParticipantResultListener participantResultListener = new ParticipantResultListener(); + TestCommandResponseListener testCommandResponseListener = new TestCommandResponseListener(); + + try + { + _jmsDelegate.addCommandListener(testCommandResponseListener); + _jmsDelegate.addCommandListener(participantResultListener); + + runParts(); + + return _testResult; + } + finally + { + _jmsDelegate.removeCommandListener(participantResultListener); + _jmsDelegate.removeCommandListener(testCommandResponseListener); + } + } + + private void runParts() + { + boolean queuesCreated = false; + + try + { + createQueues(); + queuesCreated = true; + Runtime.getRuntime().addShutdownHook(_removeQueuesShutdownHook); + + sendTestSetupCommands(); + awaitCommandResponses(); + sendCommandToParticipatingClients(new StartTestCommand()); + awaitCommandResponses(); + + awaitTestResults(); + + sendCommandToParticipatingClients(new TearDownTestCommand()); + awaitCommandResponses(); + } + finally + { + + if (queuesCreated) + { + deleteQueues(); + } + + Runtime.getRuntime().removeShutdownHook(_removeQueuesShutdownHook); + + } + } + + void createQueues() + { + List queues = _testInstance.getQueues(); + if (!queues.isEmpty()) + { + _jmsDelegate.createQueues(queues); + } + } + + void sendTestSetupCommands() + { + List commandsForAllClients = _testInstance.createCommands(); + final int numberOfCommandsToSend = commandsForAllClients.size(); + _commandResponseLatch = new CountDownLatch(numberOfCommandsToSend); + + LOGGER.debug("About to send {} command(s)", numberOfCommandsToSend); + + for (CommandForClient commandForClient : commandsForAllClients) + { + String configuredClientName = commandForClient.getClientName(); + String registeredClientName = _participatingClients.getRegisteredNameFromConfiguredName(configuredClientName); + + Command command = commandForClient.getCommand(); + + LOGGER.debug("Sending command : {} ", command); + + sendCommandInternal(registeredClientName, command); + } + } + + void awaitCommandResponses() + { + awaitLatch(_commandResponseLatch, _commandResponseTimeout, "Timed out waiting for command responses. Expecting %d more responses."); + } + + + void processCommandResponse(final Response response) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Received response for command " + response); + } + + _commandResponseLatch.countDown(); + checkForResponseError(response); + } + + + void awaitTestResults() + { + long timeout = _testResultTimeout; + DistributedTestException lastException = null; + + boolean waitForever = _testResultTimeout == WAIT_FOREVER; + final long interval = waitForever ? PARTICIPANT_RESULTS_LOG_INTERVAL : Math.min(PARTICIPANT_RESULTS_LOG_INTERVAL, _testResultTimeout); + + while(_testResultsLatch.getCount() > 0 && (waitForever || timeout > 0)) + { + try + { + awaitLatch(_testResultsLatch, interval, "Waiting for participant results... Expecting %d more responses."); + } + catch (DistributedTestException e) + { + lastException = e; + LOGGER.info(e.getMessage()); + } + + if (!waitForever) + { + timeout =- interval; + } + } + + if (_testResultsLatch.getCount() > 0) + { + throw lastException; + } + } + + void deleteQueues() + { + List queues = _testInstance.getQueues(); + if (!queues.isEmpty()) + { + _jmsDelegate.deleteQueues(queues); + } + } + + void sendCommandToParticipatingClients(final Command command) + { + Collection participatingRegisteredClients = _participatingClients.getRegisteredNames(); + final int numberOfClients = participatingRegisteredClients.size(); + _commandResponseLatch = new CountDownLatch(numberOfClients); + + LOGGER.debug("About to send command {} to {} clients", command, numberOfClients); + + for (final String clientName : participatingRegisteredClients) + { + LOGGER.debug("Sending command : {} ", command); + sendCommandInternal(clientName, command); + } + } + + public void processParticipantResult(ParticipantResult result) + { + setOriginalTestDetailsOn(result); + + _testResult.addParticipantResult(result); + LOGGER.info("Received result " + result); + + _testResultsLatch.countDown(); + checkForResponseError(result); + } + + private void setOriginalTestDetailsOn(ParticipantResult result) + { + // Client knows neither the configured client name nor test name + String registeredClientName = result.getRegisteredClientName(); + String configuredClient = _participatingClients.getConfiguredNameFromRegisteredName(registeredClientName); + + result.setConfiguredClientName(configuredClient); + result.setTestName(_testInstance.getName()); + result.setIterationNumber(_testInstance.getIterationNumber()); + } + + private void sendCommandInternal(String registeredClientName, Command command) + { + _setOfResponsesToExpect.add(command.getType()); + _jmsDelegate.sendCommandToClient(registeredClientName, command); + } + + private void awaitLatch(CountDownLatch latch, long timeout, String messageWithOneDecimalPlaceholder) + { + try + { + final boolean countedDownOK = latch.await(timeout, TimeUnit.MILLISECONDS); + if (!countedDownOK) + { + final long latchCount = latch.getCount(); + String formattedMessage = String.format(messageWithOneDecimalPlaceholder, latchCount); + throw new DistributedTestException(formattedMessage); + } + } + catch (final InterruptedException e) + { + Thread.currentThread().interrupt(); + } + } + + private void checkForResponseError(final Response response) + { + if (response.hasError()) + { + LOGGER.error("Client " + response.getRegisteredClientName() + " reported error " + response); + } + } + + final class ParticipantResultListener implements CommandListener + { + @Override + public boolean supports(Command command) + { + return command instanceof ParticipantResult; + } + + @Override + public void processCommand(Command command) + { + processParticipantResult((ParticipantResult) command); + + } + } + + final class TestCommandResponseListener implements CommandListener + { + @Override + public void processCommand(Command command) + { + processCommandResponse((Response)command); + } + + @Override + public boolean supports(Command command) + { + CommandType type = command.getType(); + if (type == CommandType.RESPONSE) + { + Response response = (Response)command; + return _setOfResponsesToExpect.contains(response.getInReplyToCommandType()); + } + return false; + } + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunnerFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunnerFactory.java new file mode 100644 index 0000000000..bf0e5afb9c --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunnerFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller; + +import org.apache.qpid.disttest.controller.config.TestInstance; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; + +public class TestRunnerFactory +{ + public TestRunner createTestRunner(ParticipatingClients participatingClients, TestInstance testInstance, ControllerJmsDelegate jmsDelegate, long commandResponseTimeout, long testResultTimeout) + { + return new TestRunner(participatingClients, testInstance, jmsDelegate, commandResponseTimeout, testResultTimeout); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ClientConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ClientConfig.java new file mode 100644 index 0000000000..4353a85cd3 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ClientConfig.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.qpid.disttest.controller.CommandForClient; +import org.apache.qpid.disttest.message.Command; + +public class ClientConfig +{ + /* + * TODO add this field when repeating groups of clients need to be used. Talk to Phil and Keith! + * private int _instances; + */ + + private List _connections; + private List _messageProviders; + private String _name; + + public ClientConfig() + { + _name = null; + _connections = Collections.emptyList(); + _messageProviders = Collections.emptyList(); + } + + public ClientConfig(String name, ConnectionConfig... connections) + { + this(name, Arrays.asList(connections), null); + } + + public ClientConfig(String name, List connections, List messageProviders) + { + _name = name; + _connections = connections; + if (messageProviders == null) + { + _messageProviders = Collections.emptyList(); + } + else + { + _messageProviders = messageProviders; + } + } + + public String getName() + { + return _name; + } + + public List getConnections() + { + return Collections.unmodifiableList(_connections); + } + + public List createCommands() + { + List commandsForClient = new ArrayList(); + + for (MessageProviderConfig messageProvider : _messageProviders) + { + Command command = messageProvider.createCommand(); + commandsForClient.add(new CommandForClient(_name, command)); + } + for (ConnectionConfig connection : _connections) + { + List commands = connection.createCommands(); + for (Command command : commands) + { + commandsForClient.add(new CommandForClient(_name, command)); + } + } + return commandsForClient; + } + + public int getTotalNumberOfParticipants() + { + int numOfParticipants = 0; + for (ConnectionConfig connection : _connections) + { + numOfParticipants = numOfParticipants + connection.getTotalNumberOfParticipants(); + } + return numOfParticipants; + } + + public List getMessageProviders() + { + return Collections.unmodifiableList(_messageProviders); + } + + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/Config.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/Config.java new file mode 100644 index 0000000000..fe56137276 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/Config.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class Config +{ + private List _tests; + + public Config() + { + super(); + _tests = Collections.emptyList(); + } + + public Config(TestConfig... tests) + { + _tests = Arrays.asList(tests); + } + + public List getTests() + { + List testInstances = new ArrayList(); + for (TestConfig testConfig : _tests) + { + int iterationNumber = 0; + + List iterationValues = testConfig.getIterationValues(); + if(iterationValues.isEmpty()) + { + testInstances.add(new TestInstance(testConfig)); + } + else + { + for (IterationValue iterationValue : iterationValues) + { + testInstances.add(new TestInstance(testConfig, iterationNumber, iterationValue)); + iterationNumber++; + } + } + } + + return Collections.unmodifiableList(testInstances); + } + + List getTestConfigs() + { + return Collections.unmodifiableList(_tests); + } + + public int getTotalNumberOfClients() + { + int numberOfClients = 0; + for (TestConfig testConfig : _tests) + { + numberOfClients = Math.max(testConfig.getTotalNumberOfClients(), numberOfClients); + } + return numberOfClients; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java new file mode 100644 index 0000000000..6288b42eac --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.Reader; + +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.json.PropertyValueAdapter; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class ConfigReader +{ + + public Config getConfigFromFile(String fileName) throws FileNotFoundException + { + FileReader reader = new FileReader(fileName); + + Config config = readConfig(reader); + return config; + } + + public Config readConfig(Reader reader) + { + Gson gson = new GsonBuilder() + .registerTypeAdapter(PropertyValue.class, new PropertyValueAdapter()) + .create(); + Config config = gson.fromJson(reader, Config.class); + return config; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConnectionConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConnectionConfig.java new file mode 100644 index 0000000000..e2cc31e21e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConnectionConfig.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateConnectionCommand; + +public class ConnectionConfig +{ + private String _name; + private List _sessions; + private String _factory; + + // For Gson + public ConnectionConfig() + { + super(); + _sessions = Collections.emptyList(); + } + + public ConnectionConfig(String name, String factory, SessionConfig... sessions) + { + super(); + _name = name; + _factory = factory; + _sessions = Arrays.asList(sessions); + + } + + public List getSessions() + { + return Collections.unmodifiableList(_sessions); + } + + public String getName() + { + return _name; + } + + public List createCommands() + { + List commands = new ArrayList(); + commands.add(createCommand()); + for (SessionConfig sessionConfig : _sessions) + { + commands.addAll(sessionConfig.createCommands(_name)); + } + return commands; + } + + private CreateConnectionCommand createCommand() + { + CreateConnectionCommand command = new CreateConnectionCommand(); + command.setConnectionName(_name); + command.setConnectionFactoryName(_factory); + return command; + } + + public int getTotalNumberOfParticipants() + { + int numOfParticipants = 0; + + for (SessionConfig sessionConfig : _sessions) + { + numOfParticipants = numOfParticipants + sessionConfig.getTotalNumberOfParticipants(); + } + return numOfParticipants; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java new file mode 100644 index 0000000000..ed47e02667 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java @@ -0,0 +1,65 @@ +package org.apache.qpid.disttest.controller.config; + +import org.apache.qpid.disttest.message.CreateConsumerCommand; + +public class ConsumerConfig extends ParticipantConfig +{ + private boolean _isTopic; + private boolean _isDurableSubscription; + private boolean _isBrowsingSubscription; + private String _selector; + private boolean _noLocal; + private boolean _synchronous; + + // For Gson + public ConsumerConfig() + { + _isTopic = false; + _isDurableSubscription = false; + _isBrowsingSubscription = false; + _selector = null; + _noLocal = false; + _synchronous = true; + } + + public ConsumerConfig( + String consumerName, + String destinationName, + long numberOfMessages, + int batchSize, + long maximumDuration, + boolean isTopic, + boolean isDurableSubscription, + boolean isBrowsingSubscription, + String selector, + boolean noLocal, + boolean synchronous) + { + super(consumerName, destinationName, numberOfMessages, batchSize, maximumDuration); + + _isTopic = isTopic; + _isDurableSubscription = isDurableSubscription; + _isBrowsingSubscription = isBrowsingSubscription; + _selector = selector; + _noLocal = noLocal; + _synchronous = synchronous; + } + + public CreateConsumerCommand createCommand(String sessionName) + { + CreateConsumerCommand createConsumerCommand = new CreateConsumerCommand(); + + setParticipantProperties(createConsumerCommand); + + createConsumerCommand.setSessionName(sessionName); + createConsumerCommand.setTopic(_isTopic); + createConsumerCommand.setDurableSubscription(_isDurableSubscription); + createConsumerCommand.setBrowsingSubscription(_isBrowsingSubscription); + createConsumerCommand.setSelector(_selector); + createConsumerCommand.setNoLocal(_noLocal); + createConsumerCommand.setSynchronous(_synchronous); + + return createConsumerCommand; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/IterationValue.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/IterationValue.java new file mode 100644 index 0000000000..ef953a5d07 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/IterationValue.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.beanutils.BeanUtilsBean; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.message.Command; + +public class IterationValue +{ + private final Map _iterationPropertyValuesWithUnderscores; + + public IterationValue(Map iterationMap) + { + _iterationPropertyValuesWithUnderscores = iterationMap; + } + + public IterationValue() + { + _iterationPropertyValuesWithUnderscores = Collections.emptyMap(); + } + + public Map getIterationPropertyValuesWithUnderscores() + { + return _iterationPropertyValuesWithUnderscores; + } + + public void applyToCommand(Command command) + { + try + { + Map withoutUnderscoresToMatchCommandPropertyNames = getIterationPropertyValuesWithoutUnderscores(); + BeanUtilsBean.getInstance().copyProperties(command, withoutUnderscoresToMatchCommandPropertyNames); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Couldn't copy properties from iteration " + this + " to " + command, e); + } + catch (InvocationTargetException e) + { + throw new RuntimeException("Couldn't copy properties from iteration " + this + " to " + command, e); + } + } + + private Map getIterationPropertyValuesWithoutUnderscores() + { + Map iterationPropertyValues = new HashMap(); + for (String propertyNameWithUnderscore : _iterationPropertyValuesWithUnderscores.keySet()) + { + String propertyName = propertyNameWithUnderscore.replaceFirst("_", ""); + String propertyValue = _iterationPropertyValuesWithUnderscores.get(propertyNameWithUnderscore); + + iterationPropertyValues.put(propertyName, propertyValue); + } + return iterationPropertyValues; + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("iterationMap", _iterationPropertyValuesWithUnderscores).toString(); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/MessageProviderConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/MessageProviderConfig.java new file mode 100644 index 0000000000..318ec7f045 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/MessageProviderConfig.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.Map; + +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; + +public class MessageProviderConfig +{ + private String _name; + private Map _messageProperties; + + public MessageProviderConfig() + { + super(); + } + + public MessageProviderConfig(String name, Map messageProperties) + { + super(); + _name = name; + _messageProperties = messageProperties; + } + + public String getName() + { + return _name; + } + + public Map getMessageProperties() + { + return _messageProperties; + } + + public CreateMessageProviderCommand createCommand() + { + CreateMessageProviderCommand command = new CreateMessageProviderCommand(); + command.setProviderName(_name); + command.setMessageProperties(_messageProperties); + return command; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java new file mode 100644 index 0000000000..31037a3038 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import org.apache.qpid.disttest.message.CreateParticpantCommand; + +public abstract class ParticipantConfig +{ + private String _destinationName; + private long _numberOfMessages; + private String _name; + private int _batchSize; + private long _maximumDuration; + + // For GSON + public ParticipantConfig() + { + _name = null; + _destinationName = null; + _numberOfMessages = 0; + _batchSize = 0; + _maximumDuration = 0; + } + + public ParticipantConfig( + String name, + String destinationName, + long numberOfMessages, + int batchSize, + long maximumDuration) + { + _name = name; + _destinationName = destinationName; + _numberOfMessages = numberOfMessages; + _batchSize = batchSize; + _maximumDuration = maximumDuration; + } + + protected void setParticipantProperties(CreateParticpantCommand createParticipantCommand) + { + createParticipantCommand.setParticipantName(_name); + createParticipantCommand.setDestinationName(_destinationName); + createParticipantCommand.setNumberOfMessages(_numberOfMessages); + createParticipantCommand.setBatchSize(_batchSize); + createParticipantCommand.setMaximumDuration(_maximumDuration); + } + +} \ No newline at end of file diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java new file mode 100644 index 0000000000..7806528a8c --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import javax.jms.Message; + +import org.apache.qpid.disttest.message.CreateProducerCommand; + +public class ProducerConfig extends ParticipantConfig +{ + private int _deliveryMode; + private int _messageSize; + private int _priority; + private long _timeToLive; + private long _interval; + private long _startDelay; + private String _messageProviderName; + + // For Gson + public ProducerConfig() + { + _deliveryMode = Message.DEFAULT_DELIVERY_MODE; + _messageSize = 0; + _priority = Message.DEFAULT_PRIORITY; + _timeToLive = Message.DEFAULT_TIME_TO_LIVE; + _interval = 0; + _startDelay = 0; + _messageProviderName = null; + } + + public ProducerConfig( + String producerName, + String destinationName, + long numberOfMessages, + int batchSize, + long maximumDuration, + int deliveryMode, + int messageSize, + int priority, + long timeToLive, + long interval, + long startDelay, + String messageProviderName) + { + super(producerName, destinationName, numberOfMessages, batchSize, maximumDuration); + + _deliveryMode = deliveryMode; + _messageSize = messageSize; + _priority = priority; + _timeToLive = timeToLive; + _interval = interval; + _startDelay = startDelay; + _messageProviderName = messageProviderName; + } + + public CreateProducerCommand createCommand(String sessionName) + { + CreateProducerCommand command = new CreateProducerCommand(); + + setParticipantProperties(command); + + command.setSessionName(sessionName); + command.setDeliveryMode(_deliveryMode); + command.setMessageSize(_messageSize); + command.setPriority(_priority); + command.setTimeToLive(_timeToLive); + command.setInterval(_interval); + command.setStartDelay(_startDelay); + command.setMessageProviderName(_messageProviderName); + + return command; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java new file mode 100644 index 0000000000..cffc2b7c50 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.Collections; +import java.util.Map; + +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class QueueConfig +{ + private String _name; + private boolean _durable; + private Map _attributes; + + public QueueConfig() + { + super(); + _attributes = Collections.emptyMap(); + } + + public QueueConfig(String name, boolean durable, Map attributes) + { + super(); + this._name = name; + this._durable = durable; + this._attributes = attributes; + } + + public String getName() + { + return _name; + } + + // TODO x-qpid-capacity and x-qpid-flow-resume-capacity need to be typed as numeric but we currrently + // pass these as a string. + public Map getAttributes() + { + return _attributes; + } + + public boolean isDurable() + { + return _durable; + } + + @Override + public String toString() + { + return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/SessionConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/SessionConfig.java new file mode 100644 index 0000000000..12372e5391 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/SessionConfig.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.jms.Session; + +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateSessionCommand; + +public class SessionConfig +{ + private static final List EMPTY_PRODUCER_LIST = Collections.emptyList(); + private static final List EMPTY_CONSUMER_LIST = Collections.emptyList(); + + private int _acknowledgeMode; + private String _sessionName; + private List _producers; + private List _consumers; + + // For Gson + public SessionConfig() + { + this(null, Session.SESSION_TRANSACTED, EMPTY_CONSUMER_LIST, EMPTY_PRODUCER_LIST); + } + + public SessionConfig(String sessionName, int acknowledgeMode, ProducerConfig...producers) + { + this(sessionName, acknowledgeMode, EMPTY_CONSUMER_LIST, Arrays.asList(producers)); + } + + public SessionConfig(String sessionName, int acknowledgeMode, ConsumerConfig... consumers) + { + this(sessionName, acknowledgeMode, Arrays.asList(consumers), EMPTY_PRODUCER_LIST); + } + + public SessionConfig(String sessionName, int acknowledgeMode, List consumers, List producers) + { + _sessionName = sessionName; + _acknowledgeMode = acknowledgeMode; + _consumers = consumers; + _producers = producers; + } + + public int getAcknowledgeMode() + { + return _acknowledgeMode; + } + + public String getSessionName() + { + return _sessionName; + } + + public List getProducers() + { + return Collections.unmodifiableList(_producers); + } + + public List getConsumers() + { + return Collections.unmodifiableList(_consumers); + } + + public List createCommands(String connectionName) + { + List commands = new ArrayList(); + commands.add(createCommand(connectionName)); + for (ProducerConfig producer : _producers) + { + commands.add(producer.createCommand(_sessionName)); + } + for (ConsumerConfig consumer : _consumers) + { + commands.add(consumer.createCommand(_sessionName)); + } + return commands; + } + + private CreateSessionCommand createCommand(String connectionName) + { + CreateSessionCommand command = new CreateSessionCommand(); + command.setAcknowledgeMode(_acknowledgeMode); + command.setConnectionName(connectionName); + command.setSessionName(_sessionName); + return command; + } + + public int getTotalNumberOfParticipants() + { + return _producers.size() + _consumers.size(); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestConfig.java new file mode 100644 index 0000000000..2bb5f1b289 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestConfig.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.disttest.controller.CommandForClient; + +public class TestConfig +{ + private final String _name; + + private final List _clients; + + private final List _queues; + + private final List> _iterations; + + public TestConfig() + { + _clients = Collections.emptyList(); + _queues = Collections.emptyList(); + _name = null; + _iterations = Collections.emptyList(); + } + + public TestConfig(String name, ClientConfig[] clients, QueueConfig[] queues) + { + _clients = Arrays.asList(clients); + _queues = Arrays.asList(queues); + _name = name; + _iterations = Collections.emptyList(); + } + + public List getClientNames() + { + List clientNames = new ArrayList(); + for (ClientConfig clientConfig : _clients) + { + clientNames.add(clientConfig.getName()); + } + return clientNames; + } + + public int getTotalNumberOfClients() + { + return _clients.size(); + } + + public int getTotalNumberOfParticipants() + { + int numOfParticipants = 0; + for (ClientConfig client : _clients) + { + numOfParticipants = numOfParticipants + client.getTotalNumberOfParticipants(); + } + return numOfParticipants; + } + + public List createCommands() + { + List commandsForClients = new ArrayList(); + for (ClientConfig client : _clients) + { + commandsForClients.addAll(client.createCommands()); + } + + return Collections.unmodifiableList(commandsForClients); + } + + public List getQueues() + { + return Collections.unmodifiableList(_queues); + } + + public String getName() + { + return _name; + } + + public List getIterationValues() + { + List iterationValues = new ArrayList(); + for (Map iterationMap : _iterations) + { + iterationValues.add(new IterationValue(iterationMap)); + } + + return iterationValues; + } + + public List getClients() + { + return Collections.unmodifiableList(_clients); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestInstance.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestInstance.java new file mode 100644 index 0000000000..9f555ef4da --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/TestInstance.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.controller.CommandForClient; +import org.apache.qpid.disttest.message.Command; + +public class TestInstance +{ + private static final IterationValue EMPTY_ITERATION_VALUES = new IterationValue(); + + private TestConfig _testConfig; + private IterationValue _iterationValue; + private int _iterationNumber; + + public TestInstance(TestConfig testConfig, int iterationNumber, IterationValue iterationValue) + { + _testConfig = testConfig; + _iterationNumber = iterationNumber; + _iterationValue = iterationValue; + } + + public TestInstance(TestConfig testConfig) + { + this(testConfig, 0, EMPTY_ITERATION_VALUES); + } + + public List createCommands() + { + List commands = _testConfig.createCommands(); + List newCommands = new ArrayList(commands.size()); + + for (CommandForClient commandForClient : commands) + { + String clientName = commandForClient.getClientName(); + Command command = commandForClient.getCommand(); + + _iterationValue.applyToCommand(command); + + newCommands.add(new CommandForClient(clientName, command)); + } + + return newCommands; + + } + + public String getName() + { + return _testConfig.getName(); + } + + public int getIterationNumber() + { + return _iterationNumber; + } + + public int getTotalNumberOfParticipants() + { + return _testConfig.getTotalNumberOfParticipants(); + } + + public List getQueues() + { + return _testConfig.getQueues(); + } + + public List getClientNames() + { + return _testConfig.getClientNames(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("testName", getName()) + .append("iterationNumber", _iterationNumber) + .toString(); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java new file mode 100644 index 0000000000..d68fc86a0e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java @@ -0,0 +1,592 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.jms; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.DistributedTestConstants; +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.client.MessageProvider; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClientJmsDelegate +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ClientJmsDelegate.class); + + private final Context _context; + private final Destination _controllerQueue; + private final Connection _controllerConnection; + private final Session _controllerSession; + private final MessageProducer _controlQueueProducer; + + private final String _clientName; + private Queue _instructionQueue; + + private Map _testConnections; + private Map _testSessions; + private Map _testProducers; + private Map _testConsumers; + private Map _testMessageProviders; + + private final MessageProvider _defaultMessageProvider; + + public ClientJmsDelegate(final Context context) + { + try + { + _context = context; + final ConnectionFactory connectionFactory = (ConnectionFactory) _context.lookup("connectionfactory"); + _controllerConnection = connectionFactory.createConnection(); + _controllerConnection.start(); + _controllerQueue = (Destination) context.lookup(DistributedTestConstants.CONTROLLER_QUEUE_JNDI_NAME); + _controllerSession = _controllerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _controlQueueProducer = _controllerSession.createProducer(_controllerQueue); + _clientName = UUID.randomUUID().toString(); + _testConnections = new HashMap(); + _testSessions = new HashMap(); + _testProducers = new HashMap(); + _testConsumers = new HashMap(); + _testMessageProviders = new HashMap(); + _defaultMessageProvider = new MessageProvider(null); + } + catch (final NamingException ne) + { + throw new DistributedTestException("Unable to create client jms delegate", ne); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to create client jms delegate", jmse); + } + } + + public void setInstructionListener(final Client client) + { + try + { + _instructionQueue = _controllerSession.createTemporaryQueue(); + final MessageConsumer instructionConsumer = _controllerSession.createConsumer(_instructionQueue); + instructionConsumer.setMessageListener(new MessageListener() + { + @Override + public void onMessage(final Message message) + { + client.processInstruction(JmsMessageAdaptor.messageToCommand(message)); + } + }); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to setup instruction listener", jmse); + } + } + + public void sendRegistrationMessage() + { + Command command; + try + { + command = new RegisterClientCommand(_clientName, _instructionQueue.getQueueName()); + } + catch (final JMSException e) + { + throw new DistributedTestException(e); + } + sendCommand(command); + } + + public void sendResponseMessage(final Response responseMessage) + { + sendCommand(responseMessage); + } + + private void sendCommand(final Command command) + { + try + { + final Message message = JmsMessageAdaptor.commandToMessage(_controllerSession, command); + _controlQueueProducer.send(message); + LOGGER.debug("Sent message for " + command.getType() + ". message id: " + message.getJMSMessageID()); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to send command: " + command, jmse); + } + } + + public void createConnection(final CreateConnectionCommand command) + { + try + { + final ConnectionFactory connectionFactory = (ConnectionFactory) _context.lookup(command + .getConnectionFactoryName()); + final Connection newConnection = connectionFactory.createConnection(); + addConnection(command.getConnectionName(), newConnection); + } + catch (final NamingException ne) + { + throw new DistributedTestException("Unable to lookup factoryName: " + command.getConnectionFactoryName(), + ne); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to create connection: " + command.getConnectionName() + + " (using factory name: " + command.getConnectionFactoryName() + ")", jmse); + } + } + + public void createSession(final CreateSessionCommand command) + { + try + { + final Connection connection = _testConnections.get(command.getConnectionName()); + if (connection == null) + { + throw new DistributedTestException("No test connection found called: " + command.getConnectionName(), + command); + } + final boolean transacted = command.getAcknowledgeMode() == Session.SESSION_TRANSACTED; + + final Session newSession = connection.createSession(transacted, command.getAcknowledgeMode()); + LOGGER.info("Created session " + command.getSessionName() + " with transacted = " + newSession.getTransacted() + " and acknowledgeMode = " + newSession.getAcknowledgeMode()); + + addSession(command.getSessionName(), newSession); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to create new session: " + command, jmse); + } + } + + public void createProducer(final CreateProducerCommand command) + { + try + { + final Session session = _testSessions.get(command.getSessionName()); + if (session == null) + { + throw new DistributedTestException("No test session found called: " + command.getSessionName(), command); + } + final Destination destination = session.createQueue(command.getDestinationName()); + final MessageProducer jmsProducer = session.createProducer(destination); + if (command.getPriority() != -1) + { + jmsProducer.setPriority(command.getPriority()); + } + if (command.getTimeToLive() > 0) + { + jmsProducer.setTimeToLive(command.getTimeToLive()); + } + + if (command.getDeliveryMode() == DeliveryMode.NON_PERSISTENT + || command.getDeliveryMode() == DeliveryMode.PERSISTENT) + { + jmsProducer.setDeliveryMode(command.getDeliveryMode()); + } + + addProducer(command.getParticipantName(), jmsProducer); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to create new producer: " + command, jmse); + } + + } + + public void createConsumer(final CreateConsumerCommand command) + { + try + { + final Session session = _testSessions.get(command.getSessionName()); + if (session == null) + { + throw new DistributedTestException("No test session found called: " + command.getSessionName(), command); + } + final Destination destination = command.isTopic() ? session.createTopic(command.getDestinationName()) + : session.createQueue(command.getDestinationName()); + final MessageConsumer jmsConsumer = session.createConsumer(destination, command.getSelector()); + + _testConsumers.put(command.getParticipantName(), jmsConsumer); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to create new consumer: " + command, jmse); + } + } + + /** + * destroy the client. Don't call from the Dispatcher thread. + */ + public void destroy() + { + try + { + // Stopping the connection allows in-flight onMessage calls to + // finish. + _controllerConnection.stop(); + + if (_controllerSession != null) + { + _controllerSession.close(); + } + if (_controllerConnection != null) + { + _controllerConnection.close(); + } + + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to destroy cleanly", jmse); + } + } + + public Destination getControllerQueue() + { + return _controllerQueue; + } + + public String getClientName() + { + return _clientName; + } + + public int getNoOfTestConnections() + { + return _testConnections.size(); + } + + public int getNoOfTestSessions() + { + return _testSessions.size(); + } + + public int getNoOfTestProducers() + { + return _testProducers.size(); + } + + public int getNoOfTestConsumers() + { + return _testConsumers.size(); + } + + public void startConnections() + { + // start connections for consumers + // it would be better if we could track consumer connections and start + // only those + if (!_testConsumers.isEmpty()) + { + for (final Map.Entry entry : _testConnections.entrySet()) + { + final Connection connection = entry.getValue(); + try + { + connection.start(); + } + catch (final JMSException e) + { + throw new DistributedTestException("Failed to start connection '" + entry.getKey() + "' :" + + e.getLocalizedMessage()); + } + } + } + } + + public void commitOrAcknowledgeMessage(final Message message, final String sessionName) + { + try + { + final Session session = _testSessions.get(sessionName); + if (session.getTransacted()) + { + session.commit(); + } + else if (message != null && session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) + { + message.acknowledge(); + } + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to commit or acknowledge message on session: " + + sessionName, jmse); + } + } + + public int getAcknowledgeMode(final String sessionName) + { + try + { + final Session session = _testSessions.get(sessionName); + return session.getAcknowledgeMode(); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to determine acknowledgement mode for session: " + + sessionName, jmse); + } + } + + public Message sendNextMessage(final CreateProducerCommand command) + { + Message sentMessage = null; + MessageProvider messageProvider = _testMessageProviders.get(command.getMessageProviderName()); + if (messageProvider == null) + { + messageProvider = _defaultMessageProvider; + } + + final Session session = _testSessions.get(command.getSessionName()); + final MessageProducer producer = _testProducers.get(command.getParticipantName()); + try + { + sentMessage = messageProvider.nextMessage(session, command); + int deliveryMode = producer.getDeliveryMode(); + int priority = producer.getPriority(); + long ttl = producer.getTimeToLive(); + if (messageProvider.isPropertySet(MessageProvider.PRIORITY)) + { + priority = sentMessage.getJMSPriority(); + } + if (messageProvider.isPropertySet(MessageProvider.DELIVERY_MODE)) + { + deliveryMode = sentMessage.getJMSDeliveryMode(); + } + if (messageProvider.isPropertySet(MessageProvider.TTL)) + { + ttl = sentMessage.getLongProperty(MessageProvider.TTL); + } + producer.send(sentMessage, deliveryMode, priority, ttl); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to create and send message with producer: " + + command.getParticipantName() + " on session: " + command.getSessionName(), jmse); + } + return sentMessage; + } + + protected void addSession(final String sessionName, final Session newSession) + { + _testSessions.put(sessionName, newSession); + } + + protected void addConnection(final String connectionName, final Connection newConnection) + { + _testConnections.put(connectionName, newConnection); + } + + protected void addProducer(final String producerName, final MessageProducer jmsProducer) + { + _testProducers.put(producerName, jmsProducer); + } + + public Message consumeMessage(String consumerName, long receiveInterval) + { + Message consumedMessage = null; + MessageConsumer consumer = _testConsumers.get(consumerName); + try + { + consumedMessage = consumer.receive(receiveInterval); + } + catch (JMSException e) + { + throw new DistributedTestException("Unable to consume message with consumer: " + consumerName, e); + } + return consumedMessage; + } + + public void registerListener(String consumerName, MessageListener messageListener) + { + MessageConsumer consumer = _testConsumers.get(consumerName); + try + { + consumer.setMessageListener(messageListener); + } + catch (JMSException e) + { + throw new DistributedTestException("Unable to register message listener with consumer: " + consumerName, e); + } + } + + public void rollbackOrRecover(String sessionName) + { + try + { + final Session session = _testSessions.get(sessionName); + if (session.getTransacted()) + { + session.rollback(); + } + else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) + { + session.recover(); + } + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to rollback or recover on session: " + + sessionName, jmse); + } + } + + public void releaseMessage(String sessionName) + { + try + { + final Session session = _testSessions.get(sessionName); + if (session.getTransacted()) + { + session.rollback(); + } + else + { + session.recover(); + } + } + catch (final JMSException jmse) + { + LOGGER.warn("Unable to rollback or recover on session: " + sessionName, jmse); + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("clientName", _clientName).toString(); + } + + public void closeTestConnections() + { + StringBuilder jmsErrorMessages = new StringBuilder(); + int failedCloseCounter = 0; + for (final Map.Entry entry : _testConnections.entrySet()) + { + final Connection connection = entry.getValue(); + try + { + connection.close(); + } + catch (final JMSException e) + { + LOGGER.error("Failed to close connection '" + entry.getKey() + "' :" + e.getLocalizedMessage(), e); + failedCloseCounter++; + if (jmsErrorMessages.length() > 0) + { + jmsErrorMessages.append('\n'); + } + jmsErrorMessages.append(e.getMessage()); + } + } + _testConnections.clear(); + _testSessions.clear(); + _testProducers.clear(); + _testConsumers.clear(); + if (failedCloseCounter > 0) + { + throw new DistributedTestException("Close failed for " + failedCloseCounter + " connection(s) with the following errors: " + jmsErrorMessages.toString()); + } + } + + public void closeTestConsumer(String consumerName) + { + MessageConsumer consumer = _testConsumers.get(consumerName); + if (consumer != null) + { + try + { + consumer.close(); + LOGGER.info("Closed test consumer " + consumerName); + } + catch (JMSException e) + { + throw new DistributedTestException("Failed to close consumer: " + consumerName, e); + } + } + } + + public void closeTestProducer(String producerName) + { + MessageProducer producer = _testProducers.get(producerName); + if (producer != null) + { + try + { + producer.close(); + } + catch (JMSException e) + { + throw new DistributedTestException("Failed to close producer: " + producerName, e); + } + } + } + + public int calculatePayloadSizeFrom(Message message) + { + try + { + if (message != null && message instanceof TextMessage) + { + return ((TextMessage) message).getText().getBytes().length; + } + // TODO support other message types + return 0; + } + catch (JMSException e) + { + throw new DistributedTestException("Unable to determine the payload size for message " + message, e); + } + } + + public void createMessageProvider(CreateMessageProviderCommand command) + { + _testMessageProviders.put(command.getProviderName(), new MessageProvider(command.getMessageProperties())); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java new file mode 100644 index 0000000000..69da409be5 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.jms; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.CommandListener; +import org.apache.qpid.disttest.controller.config.QueueConfig; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ControllerJmsDelegate +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ControllerJmsDelegate.class); + + private final Map _clientNameToQueueMap = new ConcurrentHashMap(); + private final Connection _connection; + private final Destination _controllerQueue; + private final Session _session; + private final QueueCreator _queueCreator; + + private List _commandListeners = new CopyOnWriteArrayList(); + + public ControllerJmsDelegate(final Context context) throws NamingException, JMSException + { + final ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("connectionfactory"); + _connection = connectionFactory.createConnection(); + _connection.start(); + _controllerQueue = (Destination) context.lookup("controllerqueue"); + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _queueCreator = new QpidQueueCreator(); + } + + public void start() + { + try + { + final MessageConsumer consumer = _session.createConsumer(_controllerQueue); + consumer.setMessageListener(new MessageListener() + { + @Override + public void onMessage(final Message message) + { + try + { + String jmsMessageID = message.getJMSMessageID(); + LOGGER.debug("Received message " + jmsMessageID); + + final Command command = JmsMessageAdaptor.messageToCommand(message); + LOGGER.debug("Converted message " + jmsMessageID + " into command: " + command); + + processCommandWithFirstSupportingListener(command); + LOGGER.debug("Finished processing command for message " + jmsMessageID); + } + catch (Throwable t) + { + LOGGER.error("Can't handle JMS message", t); + } + } + }); + } + catch (final JMSException e) + { + throw new DistributedTestException(e); + } + } + + /** ensures connections are closed, otherwise the JVM may be prevented from terminating */ + public void closeConnections() + { + try + { + _session.close(); + } + catch (JMSException e) + { + LOGGER.error("Unable to close session", e); + } + + try + { + _connection.stop(); + } + catch (JMSException e) + { + LOGGER.error("Unable to stop connection", e); + } + + try + { + _connection.close(); + } + catch (JMSException e) + { + throw new DistributedTestException("Unable to close connection", e); + } + } + + public void registerClient(final RegisterClientCommand command) + { + final String clientName = command.getClientName(); + final Destination clientIntructionQueue = createDestinationFromString(command.getClientQueueName()); + _clientNameToQueueMap.put(clientName, clientIntructionQueue); + } + + public void sendCommandToClient(final String clientName, final Command command) + { + final Destination clientQueue = _clientNameToQueueMap.get(clientName); + if (clientQueue == null) + { + throw new DistributedTestException("Client name " + clientName + " not known. I know about: " + + _clientNameToQueueMap.keySet()); + } + + try + { + final MessageProducer producer = _session.createProducer(clientQueue); + final Message message = JmsMessageAdaptor.commandToMessage(_session, command); + + producer.send(message); + } + catch (final JMSException e) + { + throw new DistributedTestException(e); + } + } + + private void processCommandWithFirstSupportingListener(Command command) + { + for (CommandListener listener : _commandListeners) + { + if (listener.supports(command)) + { + listener.processCommand(command); + return; + } + } + + throw new IllegalStateException("There is no registered listener to process command " + command); + } + + private Destination createDestinationFromString(final String clientQueueName) + { + Destination clientIntructionQueue; + try + { + clientIntructionQueue = _session.createQueue(clientQueueName); + } + catch (JMSException e) + { + throw new DistributedTestException("Unable to create Destination from " + clientQueueName); + } + return clientIntructionQueue; + } + + public void createQueues(List queues) + { + _queueCreator.createQueues(_session, queues); + } + + public void deleteQueues(List queues) + { + _queueCreator.deleteQueues(_session, queues); + } + + public void addCommandListener(CommandListener commandListener) + { + _commandListeners.add(commandListener); + } + + public void removeCommandListener(CommandListener commandListener) + { + _commandListeners.remove(commandListener); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/JmsMessageAdaptor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/JmsMessageAdaptor.java new file mode 100644 index 0000000000..c9dba21a74 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/JmsMessageAdaptor.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.jms; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Session; + +import org.apache.qpid.disttest.DistributedTestConstants; +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.json.JsonHandler; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.CreateResponderCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StartTestCommand; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.apache.qpid.disttest.message.TearDownTestCommand; + +public class JmsMessageAdaptor +{ + public static Message commandToMessage(final Session session, final Command command) + { + Message jmsMessage = null; + try + { + jmsMessage = session.createMessage(); + jmsMessage.setStringProperty(DistributedTestConstants.MSG_COMMAND_PROPERTY, command.getType().name()); + final JsonHandler jsonHandler = new JsonHandler(); + jmsMessage.setStringProperty(DistributedTestConstants.MSG_JSON_PROPERTY, jsonHandler.marshall(command)); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to convert command " + command + " to JMS Message", jmse); + } + + return jmsMessage; + } + + public static Command messageToCommand(final Message jmsMessage) + { + Command command = null; + try + { + final CommandType commandType = CommandType.valueOf(jmsMessage + .getStringProperty(DistributedTestConstants.MSG_COMMAND_PROPERTY)); + final JsonHandler jsonHandler = new JsonHandler(); + command = jsonHandler.unmarshall(jmsMessage.getStringProperty(DistributedTestConstants.MSG_JSON_PROPERTY), + getCommandClassFromType(commandType)); + } + catch (final JMSException jmse) + { + throw new DistributedTestException("Unable to convert JMS message " + jmsMessage + " to command object", + jmse); + } + return command; + } + + static Class getCommandClassFromType(final CommandType type) + { + switch (type) + { + case CREATE_CONNECTION: + return CreateConnectionCommand.class; + case CREATE_SESSION: + return CreateSessionCommand.class; + case CREATE_PRODUCER: + return CreateProducerCommand.class; + case CREATE_CONSUMER: + return CreateConsumerCommand.class; + case CREATE_RESPONDER: + return CreateResponderCommand.class; + case NO_OP: + return NoOpCommand.class; + case REGISTER_CLIENT: + return RegisterClientCommand.class; + case STOP_CLIENT: + return StopClientCommand.class; + case RESPONSE: + return Response.class; + case START_TEST: + return StartTestCommand.class; + case TEAR_DOWN_TEST: + return TearDownTestCommand.class; + case PARTICIPANT_RESULT: + return ParticipantResult.class; + case CONSUMER_PARTICIPANT_RESULT: + return ConsumerParticipantResult.class; + case PRODUCER_PARTICIPANT_RESULT: + return ProducerParticipantResult.class; + case CREATE_MESSAGE_PROVIDER: + return CreateMessageProviderCommand.class; + default: + throw new DistributedTestException("No class defined for type: " + type); + } + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java new file mode 100644 index 0000000000..912ce54495 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.jms; + +import java.util.List; + +import javax.jms.Session; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.config.QueueConfig; +import org.apache.qpid.framing.FieldTable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QpidQueueCreator implements QueueCreator +{ + private static final Logger LOGGER = LoggerFactory.getLogger(QpidQueueCreator.class); + + private static final FieldTable EMPTY_QUEUE_BIND_ARGUMENTS = new FieldTable(); + + @Override + public void createQueues(Session session, List configs) + { + AMQSession amqSession = (AMQSession)session; + for (QueueConfig queueConfig : configs) + { + createQueue(amqSession, queueConfig); + } + } + + @Override + public void deleteQueues(Session session, List configs) + { + AMQSession amqSession = (AMQSession)session; + for (QueueConfig queueConfig : configs) + { + deleteQueue(amqSession, queueConfig); + } + } + + private void createQueue(AMQSession session, QueueConfig queueConfig) + { + try + { + AMQDestination destination = (AMQDestination) session.createQueue(queueConfig.getName()); + boolean autoDelete = false; + boolean exclusive = false; + session.createQueue(destination.getAMQQueueName(), autoDelete, + queueConfig.isDurable(), exclusive, queueConfig.getAttributes()); + session.bindQueue(destination.getAMQQueueName(), destination.getRoutingKey(), + EMPTY_QUEUE_BIND_ARGUMENTS, destination.getExchangeName(), + destination, autoDelete); + + LOGGER.info("Created queue " + queueConfig); + } + catch (Exception e) + { + throw new DistributedTestException("Failed to create queue:" + queueConfig, e); + } + } + + private void deleteQueue(AMQSession session, QueueConfig queueConfig) + { + try + { + // The Qpid AMQSession API currently makes the #deleteQueue method protected and the + // raw protocol method public. This should be changed then we should switch the below to + // use #deleteQueue. + AMQDestination destination = (AMQDestination) session.createQueue(queueConfig.getName()); + session.sendQueueDelete(destination.getAMQQueueName()); + LOGGER.info("Deleted queue " + queueConfig.getName()); + } + catch (Exception e) + { + throw new DistributedTestException("Failed to delete queue:" + queueConfig.getName(), e); + } + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java new file mode 100644 index 0000000000..0947dd53cb --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.jms; + +import java.util.List; + +import javax.jms.Session; + +import org.apache.qpid.disttest.controller.config.QueueConfig; + +public interface QueueCreator +{ + public void createQueues(final Session session, final List configs); + public void deleteQueues(final Session session, final List configs); +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/json/JsonHandler.java b/java/perftests/src/main/java/org/apache/qpid/disttest/json/JsonHandler.java new file mode 100644 index 0000000000..8e50cd4f11 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/json/JsonHandler.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.json; + +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.message.Command; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class JsonHandler +{ + private final Gson _gson = new GsonBuilder() + .registerTypeAdapter(PropertyValue.class, new PropertyValueAdapter()) + .create(); + + public T unmarshall(final String jsonParams, final Class clazz) + { + return _gson.fromJson(jsonParams, clazz); + } + + public String marshall(final T command) + { + return _gson.toJson(command); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/json/PropertyValueAdapter.java b/java/perftests/src/main/java/org/apache/qpid/disttest/json/PropertyValueAdapter.java new file mode 100644 index 0000000000..94f712e652 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/json/PropertyValueAdapter.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.json; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.disttest.client.property.GeneratedPropertyValue; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.client.property.PropertyValueFactory; +import org.apache.qpid.disttest.client.property.SimplePropertyValue; + +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public class PropertyValueAdapter implements JsonDeserializer, JsonSerializer +{ + private static final String DEF_FIELD = "@def"; + private PropertyValueFactory _factory = new PropertyValueFactory(); + + @Override + public PropertyValue deserialize(JsonElement json, Type type, JsonDeserializationContext context) + throws JsonParseException + { + if (json.isJsonNull()) + { + return null; + } + else if (json.isJsonPrimitive()) + { + Object result = null; + JsonPrimitive primitive = json.getAsJsonPrimitive(); + if (primitive.isString()) + { + result = primitive.getAsString(); + } + else if (primitive.isNumber()) + { + String asString = primitive.getAsString(); + if (asString.indexOf('.') != -1 || asString.indexOf('e') != -1) + { + result = primitive.getAsDouble(); + } + else + { + result = primitive.getAsLong(); + } + } + else if (primitive.isBoolean()) + { + result = primitive.getAsBoolean(); + } + else + { + throw new JsonParseException("Unsupported primitive value " + primitive); + } + return new SimplePropertyValue(result); + } + else if (json.isJsonArray()) + { + JsonArray array = json.getAsJsonArray(); + List result = new ArrayList(array.size()); + for (JsonElement element : array) + { + result.add(context.deserialize(element, Object.class)); + } + return new SimplePropertyValue(result); + } + else if (json.isJsonObject()) + { + JsonObject object = json.getAsJsonObject(); + JsonElement defElement = object.getAsJsonPrimitive(DEF_FIELD); + Class classInstance = null; + if (defElement != null) + { + try + { + classInstance = _factory.getPropertyValueClass(defElement.getAsString()); + } + catch (ClassNotFoundException e) + { + // ignore + } + } + if (classInstance == null) + { + Map result = new HashMap(); + for (Map.Entry entry : object.entrySet()) + { + Object value = context.deserialize(entry.getValue(), Object.class); + result.put(entry.getKey(), value); + } + return new SimplePropertyValue(result); + } + else + { + return context.deserialize(json, classInstance); + } + } + else + { + throw new JsonParseException("Unsupported JSON type " + json); + } + } + + @Override + public JsonElement serialize(PropertyValue src, Type typeOfSrc, JsonSerializationContext context) + { + if (src instanceof GeneratedPropertyValue) + { + JsonObject object = (JsonObject) context.serialize(src, Object.class); + object.addProperty(DEF_FIELD, ((GeneratedPropertyValue) src).getDefinition()); + return object; + } + else + { + return context.serialize(src.getValue(), Object.class); + } + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/Command.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/Command.java new file mode 100644 index 0000000000..86b4d0e439 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/Command.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + + +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.Visitor; +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.controller.Controller; + +/** + * A command sent between the {@link Controller} and a {@link Client} + */ +public abstract class Command +{ + private final CommandType type; + + public Command(final CommandType type) + { + this.type = type; + } + + public CommandType getType() + { + return type; + } + + public void accept(Visitor visitor) + { + visitor.visit(this); + } + + @Override + public String toString() + { + return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CommandType.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CommandType.java new file mode 100644 index 0000000000..b04cbdaba1 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CommandType.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public enum CommandType +{ + CREATE_CONNECTION, + CREATE_CONSUMER, + CREATE_PRODUCER, + CREATE_RESPONDER, + CREATE_SESSION, + NO_OP, + REGISTER_CLIENT, + RESPONSE, + START_TEST, + STOP_CLIENT, + TEAR_DOWN_TEST, + PARTICIPANT_RESULT, + CONSUMER_PARTICIPANT_RESULT, + PRODUCER_PARTICIPANT_RESULT, + CREATE_MESSAGE_PROVIDER +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java new file mode 100644 index 0000000000..f92e3ea538 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSIING_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; + +public class ConsumerParticipantResult extends ParticipantResult +{ + private boolean _topic; + private boolean _durableSubscription; + private boolean _browsingSubscription; + private boolean _selector; + private boolean _noLocal; + private boolean _synchronousConsumer; + + public ConsumerParticipantResult() + { + super(CommandType.CONSUMER_PARTICIPANT_RESULT); + } + + public ConsumerParticipantResult(String participantName) + { + this(); + setParticipantName(participantName); + } + + @OutputAttribute(attribute=IS_DURABLE_SUBSCRIPTION) + public boolean isDurableSubscription() + { + return _durableSubscription; + } + + public void setDurableSubscription(boolean durable) + { + _durableSubscription = durable; + } + + + @OutputAttribute(attribute=IS_BROWSIING_SUBSCRIPTION) + public boolean isBrowsingSubscription() + { + return _browsingSubscription; + } + + public void setBrowsingSubscription(boolean browsingSubscription) + { + _browsingSubscription = browsingSubscription; + } + + + @OutputAttribute(attribute=IS_SELECTOR) + public boolean isSelector() + { + return _selector; + } + + public void setSelector(boolean selector) + { + _selector = selector; + } + + + @OutputAttribute(attribute=IS_NO_LOCAL) + public boolean isNoLocal() + { + return _noLocal; + + } + + public void setNoLocal(boolean noLocal) + { + _noLocal = noLocal; + } + + @OutputAttribute(attribute=IS_SYNCHRONOUS_CONSUMER) + public boolean isSynchronousConsumer() + { + return _synchronousConsumer; + } + + public void setSynchronousConsumer(boolean synchronousConsumer) + { + _synchronousConsumer = synchronousConsumer; + } + + + public void setTopic(boolean isTopic) + { + _topic = isTopic; + } + + @OutputAttribute(attribute=IS_TOPIC) + public boolean isTopic() + { + return _topic; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConnectionCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConnectionCommand.java new file mode 100644 index 0000000000..c5a96e9a94 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConnectionCommand.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class CreateConnectionCommand extends Command +{ + private String _connectionName; + private String _connectionFactoryName; + + public CreateConnectionCommand() + { + super(CommandType.CREATE_CONNECTION); + } + + public CreateConnectionCommand(String connectionName, String connectionFactoryName) + { + super(CommandType.CREATE_CONNECTION); + _connectionName = connectionName; + _connectionFactoryName = connectionFactoryName; + } + + public void setConnectionName(final String connectionName) + { + this._connectionName = connectionName; + } + + public String getConnectionName() + { + return _connectionName; + } + + public void setConnectionFactoryName(final String connectionFactoryName) + { + this._connectionFactoryName = connectionFactoryName; + } + + public String getConnectionFactoryName() + { + return _connectionFactoryName; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java new file mode 100644 index 0000000000..678e428f94 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class CreateConsumerCommand extends CreateParticpantCommand +{ + private boolean _isTopic; + private boolean _isDurableSubscription; + private boolean _isBrowsingSubscription; + private String _selector; + private boolean _noLocal; + private boolean _synchronous; + private long _receiveTimeout = 5000; + + + public CreateConsumerCommand() + { + super(CommandType.CREATE_CONSUMER); + } + + public boolean isDurableSubscription() + { + return _isDurableSubscription; + } + + public void setDurableSubscription(final boolean isDurableSubscription) + { + this._isDurableSubscription = isDurableSubscription; + } + + public boolean isBrowsingSubscription() + { + return _isBrowsingSubscription; + } + + public void setBrowsingSubscription(final boolean isBrowsingSubscription) + { + _isBrowsingSubscription = isBrowsingSubscription; + } + + public String getSelector() + { + return _selector; + } + + public void setSelector(final String selector) + { + this._selector = selector; + } + + public boolean isNoLocal() + { + return _noLocal; + } + + public void setNoLocal(final boolean noLocal) + { + this._noLocal = noLocal; + } + + public boolean isTopic() + { + return _isTopic; + } + + public void setTopic(boolean isTopic) + { + this._isTopic = isTopic; + } + + public boolean isSynchronous() + { + return _synchronous; + } + + public void setSynchronous(boolean synchronous) + { + _synchronous = synchronous; + } + + public void setReceiveTimeout(long receiveTimeout) + { + _receiveTimeout = receiveTimeout; + + } + + public long getReceiveTimeout() + { + return _receiveTimeout; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateMessageProviderCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateMessageProviderCommand.java new file mode 100644 index 0000000000..3f30fdd96a --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateMessageProviderCommand.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import java.util.Map; + +import org.apache.qpid.disttest.client.property.PropertyValue; + +public class CreateMessageProviderCommand extends Command +{ + private String _providerName; + private Map _messageProperties; + + public CreateMessageProviderCommand() + { + super(CommandType.CREATE_MESSAGE_PROVIDER); + } + + public String getProviderName() + { + return _providerName; + } + + public void setProviderName(String providerName) + { + this._providerName = providerName; + } + + public Map getMessageProperties() + { + return _messageProperties; + } + + public void setMessageProperties(Map messageProperties) + { + this._messageProperties = messageProperties; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java new file mode 100644 index 0000000000..b1caa6ef75 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +import org.apache.commons.lang.builder.ToStringBuilder; + +public abstract class CreateParticpantCommand extends Command +{ + private String _participantName; + private String _sessionName; + private String _destinationName; + private long _numberOfMessages; + private int _batchSize; + private long _maximumDuration; + + public CreateParticpantCommand(CommandType type) + { + super(type); + } + + public String getParticipantName() + { + return _participantName; + } + + public void setParticipantName(final String participantName) + { + _participantName = participantName; + } + + public String getSessionName() + { + return _sessionName; + } + + public void setSessionName(final String sessionName) + { + _sessionName = sessionName; + } + + public String getDestinationName() + { + return _destinationName; + } + + public void setDestinationName(final String destinationName) + { + _destinationName = destinationName; + } + + public long getNumberOfMessages() + { + return _numberOfMessages; + } + + public void setNumberOfMessages(final long numberOfMessages) + { + _numberOfMessages = numberOfMessages; + } + + public int getBatchSize() + { + return _batchSize; + } + + public void setBatchSize(int batchSize) + { + _batchSize = batchSize; + } + + public long getMaximumDuration() + { + return _maximumDuration; + } + + public void setMaximumDuration(long maximumDuration) + { + _maximumDuration = maximumDuration; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateProducerCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateProducerCommand.java new file mode 100644 index 0000000000..69dfe1ff5a --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateProducerCommand.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class CreateProducerCommand extends CreateParticpantCommand +{ + private int _deliveryMode; + private int _messageSize; + private int _priority; + private long _timeToLive; + private long _interval; + private long _startDelay; + private String _messageProviderName; + + public CreateProducerCommand() + { + super(CommandType.CREATE_PRODUCER); + } + + public int getMessageSize() + { + return _messageSize; + } + + public void setMessageSize(final int messageSize) + { + this._messageSize = messageSize; + } + + public int getPriority() + { + return _priority; + } + + public void setPriority(final int priority) + { + this._priority = priority; + } + + public int getDeliveryMode() + { + return _deliveryMode; + } + + public void setDeliveryMode(final int deliveryMode) + { + this._deliveryMode = deliveryMode; + } + + public long getTimeToLive() + { + return _timeToLive; + } + + public void setTimeToLive(final long timeToLive) + { + this._timeToLive = timeToLive; + } + + public long getInterval() + { + return _interval; + } + + public void setInterval(long interval) + { + this._interval = interval; + } + + public long getStartDelay() + { + return _startDelay; + } + + public void setStartDelay(long startDelay) + { + this._startDelay = startDelay; + } + + public String getMessageProviderName() + { + return _messageProviderName; + } + + public void setMessageProviderName(String messageProviderName) + { + this._messageProviderName = messageProviderName; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateResponderCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateResponderCommand.java new file mode 100644 index 0000000000..85a2b5e548 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateResponderCommand.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class CreateResponderCommand extends Command +{ + public CreateResponderCommand() + { + super(CommandType.CREATE_RESPONDER); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateSessionCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateSessionCommand.java new file mode 100644 index 0000000000..f6f59c26af --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateSessionCommand.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class CreateSessionCommand extends Command +{ + private String sessionName; + private String connectionName; + private int acknowledgeMode; + + public CreateSessionCommand() + { + super(CommandType.CREATE_SESSION); + } + + public String getSessionName() + { + return sessionName; + } + + public void setSessionName(final String sessionName) + { + this.sessionName = sessionName; + } + + public String getConnectionName() + { + return connectionName; + } + + public void setConnectionName(final String connectionName) + { + this.connectionName = connectionName; + } + + public int getAcknowledgeMode() + { + return acknowledgeMode; + } + + public void setAcknowledgeMode(final int acknowledgeMode) + { + this.acknowledgeMode = acknowledgeMode; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/NoOpCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/NoOpCommand.java new file mode 100644 index 0000000000..1cdaf00163 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/NoOpCommand.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + + +public class NoOpCommand extends Command +{ + public NoOpCommand() + { + super(CommandType.NO_OP); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/OutputAttribute.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/OutputAttribute.java new file mode 100644 index 0000000000..b912eaa1cb --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/OutputAttribute.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Marks an attribute of {@link ParticipantResult} that should be written to the test output file. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface OutputAttribute +{ + ParticipantAttribute attribute(); +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java new file mode 100644 index 0000000000..ccc7c0d9fb --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import org.apache.qpid.disttest.client.Participant; + +/** + * Meta-date representing the attributes of {@link Participant} that we write to the test output file. + * + * Order of declaration is currently important - it determines they order they appear in the output. + * + * @see OutputAttribute + */ +public enum ParticipantAttribute +{ + TEST_NAME("testName"), + ITERATION_NUMBER("iterationNumber"), + CONFIGURED_CLIENT_NAME("clientName"), + PARTICIPANT_NAME("participantName"), + NUMBER_OF_MESSAGES_PROCESSED("numberOfMessages"), + PAYLOAD_SIZE("payloadSizeB"), + PRIORITY("priority"), + TIME_TO_LIVE("timeToLiveMs"), + ACKNOWLEDGE_MODE("acknowledgeMode"), + DELIVERY_MODE("deliveryMode"), + BATCH_SIZE("batchSize"), + MAXIMUM_DURATION("maximumDurationMs"), + PRODUCER_START_DELAY("producerStartDelayMs"), + PRODUCER_INTERVAL("producerIntervalMs"), + IS_TOPIC("isTopic"), + IS_DURABLE_SUBSCRIPTION("isDurableSubscription"), + IS_BROWSIING_SUBSCRIPTION("isBrowsingSubscription"), + IS_SELECTOR("isSelector"), + IS_NO_LOCAL("isNoLocal"), + IS_SYNCHRONOUS_CONSUMER("isSynchronousConsumer"), + TOTAL_NUMBER_OF_CONSUMERS("totalNumberOfConsumers"), + TOTAL_NUMBER_OF_PRODUCERS("totalNumberOfProducers"), + TOTAL_PAYLOAD_PROCESSED("totalPayloadProcessedB"), + THROUGHPUT("throughputKbPerS"), + TIME_TAKEN("timeTakenMs"), + ERROR_MESSAGE("errorMessage"); + + private String _displayName; + + ParticipantAttribute(String displayName) + { + _displayName = displayName; + } + + public String getDisplayName() + { + return _displayName; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttributeExtractor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttributeExtractor.java new file mode 100644 index 0000000000..95a19ceefc --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttributeExtractor.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.beanutils.PropertyUtils; + + +public class ParticipantAttributeExtractor +{ + public static Map getAttributes(Object targetObject) + { + Map attributes = new HashMap(); + + + PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(targetObject); + for (PropertyDescriptor propertyDescriptor : descriptors) + { + final Method readMethod = getPropertyReadMethod(targetObject, propertyDescriptor); + + for (Annotation annotation : readMethod.getDeclaredAnnotations()) + { + if (annotation instanceof OutputAttribute) + { + OutputAttribute outputAttribute = (OutputAttribute) annotation; + + Object value = getPropertyValue(targetObject, propertyDescriptor.getName()); + attributes.put(outputAttribute.attribute(), value); + } + } + } + + return attributes; + } + + public static Method getPropertyReadMethod(Object targetObject, PropertyDescriptor propertyDescriptor) + { + final Method readMethod = propertyDescriptor.getReadMethod(); + + if (readMethod == null) + { + throw new RuntimeException("No read method for property " + propertyDescriptor.getName() + " on " + targetObject); + } + return readMethod; + } + + public static Object getPropertyValue(Object targetObject, String propertyName) + { + try + { + return PropertyUtils.getProperty(targetObject, propertyName); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Couldn't get value of property " + propertyName + " from " + targetObject, e); + } + catch (InvocationTargetException e) + { + throw new RuntimeException("Couldn't get value of property " + propertyName + " from " + targetObject, e); + } + catch (NoSuchMethodException e) + { + throw new RuntimeException("Couldn't get value of property " + propertyName + " from " + targetObject, e); + } + + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java new file mode 100644 index 0000000000..a6d3d91bae --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java @@ -0,0 +1,272 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; + +import java.util.Comparator; +import java.util.Date; +import java.util.Map; + +public class ParticipantResult extends Response +{ + private String _testName; + private String _participantName; + private int _iterationNumber; + + private long _startInMillis; + private long _endInMillis; + private int _batchSize; + private long _maximumDuration; + + private String _configuredClientName; + + private long _numberOfMessagesProcessed; + private long _totalPayloadProcessed; + private int _payloadSize; + private double _throughput; + + private int _totalNumberOfConsumers; + private int _totalNumberOfProducers; + + // As Session.SESSION_TRANSACTED is 0, we use value -1 so we can distinguish the case where an aggregated result + // summarizes results from participants using different session acknowledge modes. + private int _acknowledgeMode = -1; + + public static final Comparator PARTICIPANT_NAME_COMPARATOR = new Comparator() + { + @Override + public int compare(ParticipantResult participantResult1, ParticipantResult participantResult2) + { + return participantResult1.getParticipantName().compareTo(participantResult2.getParticipantName()); + } + }; + + public ParticipantResult() + { + this(CommandType.PARTICIPANT_RESULT); + } + + public ParticipantResult(CommandType commandType) + { + super(commandType); + } + + public ParticipantResult(String participantName) + { + this(); + setParticipantName(participantName); + } + + @OutputAttribute(attribute=TEST_NAME) + public String getTestName() + { + return _testName; + } + + public void setTestName(String testName) + { + _testName = testName; + } + + @OutputAttribute(attribute=ITERATION_NUMBER) + public int getIterationNumber() + { + return _iterationNumber; + } + + public void setIterationNumber(int iterationNumber) + { + _iterationNumber = iterationNumber; + } + + public void setStartDate(Date start) + { + _startInMillis = start.getTime(); + } + + public void setEndDate(Date end) + { + _endInMillis = end.getTime(); + } + + public Date getStartDate() + { + return new Date(_startInMillis); + } + + public Date getEndDate() + { + return new Date(_endInMillis); + } + + + public long getStartInMillis() + { + return _startInMillis; + } + + public long getEndInMillis() + { + return _endInMillis; + } + + + @OutputAttribute(attribute=PARTICIPANT_NAME) + public String getParticipantName() + { + return _participantName; + } + + + public void setParticipantName(String participantName) + { + _participantName = participantName; + } + + @OutputAttribute(attribute=ParticipantAttribute.TIME_TAKEN) + public long getTimeTaken() + { + return _endInMillis - _startInMillis; + } + + @OutputAttribute(attribute=CONFIGURED_CLIENT_NAME) + public String getConfiguredClientName() + { + return _configuredClientName; + } + + public void setConfiguredClientName(String configuredClientName) + { + _configuredClientName = configuredClientName; + } + + @OutputAttribute(attribute=NUMBER_OF_MESSAGES_PROCESSED) + public long getNumberOfMessagesProcessed() + { + return _numberOfMessagesProcessed; + } + + public void setNumberOfMessagesProcessed(long numberOfMessagesProcessed) + { + _numberOfMessagesProcessed = numberOfMessagesProcessed; + } + + @OutputAttribute(attribute=ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED) + public long getTotalPayloadProcessed() + { + return _totalPayloadProcessed; + } + + @OutputAttribute(attribute = PAYLOAD_SIZE) + public int getPayloadSize() + { + return _payloadSize; + } + + public void setPayloadSize(int payloadSize) + { + _payloadSize = payloadSize; + } + + public void setTotalPayloadProcessed(long totalPayloadProcessed) + { + _totalPayloadProcessed = totalPayloadProcessed; + } + + public Map getAttributes() + { + return ParticipantAttributeExtractor.getAttributes(this); + } + + public void setBatchSize(int batchSize) + { + _batchSize = batchSize; + } + + @OutputAttribute(attribute=BATCH_SIZE) + public int getBatchSize() + { + return _batchSize; + } + + public void setMaximumDuration(long maximumDuration) + { + _maximumDuration = maximumDuration; + } + + @OutputAttribute(attribute=MAXIMUM_DURATION) + public long getMaximumDuration() + { + return _maximumDuration; + } + + @OutputAttribute(attribute=THROUGHPUT) + public double getThroughput() + { + return _throughput; + } + + public void setThroughput(double throughput) + { + _throughput = throughput; + } + + public void setTotalNumberOfConsumers(int totalNumberOfConsumers) + { + _totalNumberOfConsumers = totalNumberOfConsumers; + } + + @OutputAttribute(attribute=ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS) + public int getTotalNumberOfConsumers() + { + return _totalNumberOfConsumers; + } + + public void setTotalNumberOfProducers(int totalNumberOfProducers) + { + _totalNumberOfProducers = totalNumberOfProducers; + } + + @OutputAttribute(attribute=ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS) + public int getTotalNumberOfProducers() + { + return _totalNumberOfProducers; + } + + @OutputAttribute(attribute=ParticipantAttribute.ACKNOWLEDGE_MODE) + public int getAcknowledgeMode() + { + return _acknowledgeMode; + } + + public void setAcknowledgeMode(int acknowledgeMode) + { + _acknowledgeMode = acknowledgeMode; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java new file mode 100644 index 0000000000..766c90eec8 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; + +public class ProducerParticipantResult extends ParticipantResult +{ + private int _priority; + private long _timeToLive; + private long _startDelay; + private long _interval; + private int _deliveryMode; + public ProducerParticipantResult() + { + super(CommandType.PRODUCER_PARTICIPANT_RESULT); + } + + public ProducerParticipantResult(String participantName) + { + this(); + setParticipantName(participantName); + } + + @OutputAttribute(attribute=PRIORITY) + public int getPriority() + { + return _priority; + } + + public void setPriority(int priority) + { + _priority = priority; + } + + @OutputAttribute(attribute=TIME_TO_LIVE) + public long getTimeToLive() + { + return _timeToLive; + } + + public void setTimeToLive(long timeToLive) + { + _timeToLive = timeToLive; + } + + @OutputAttribute(attribute=PRODUCER_START_DELAY) + public long getStartDelay() + { + return _startDelay; + } + + public void setStartDelay(long startDelay) + { + _startDelay = startDelay; + } + + @OutputAttribute(attribute=PRODUCER_INTERVAL) + public long getInterval() + { + return _interval; + } + + public void setInterval(long producerInterval) + { + _interval = producerInterval; + } + + @OutputAttribute(attribute=DELIVERY_MODE) + public int getDeliveryMode() + { + return _deliveryMode; + } + + public void setDeliveryMode(int deliveryMode) + { + this._deliveryMode = deliveryMode; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/RegisterClientCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/RegisterClientCommand.java new file mode 100644 index 0000000000..af880a37d9 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/RegisterClientCommand.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class RegisterClientCommand extends Command +{ + private final String _clientName; + private final String _clientQueueName; + + public RegisterClientCommand(final String clientName, final String clientQueueName) + { + super(CommandType.REGISTER_CLIENT); + _clientName = clientName; + _clientQueueName = clientQueueName; + } + + public String getClientName() + { + return _clientName; + } + + public String getClientQueueName() + { + return _clientQueueName; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/Response.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/Response.java new file mode 100644 index 0000000000..aac056efcb --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/Response.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + + +public class Response extends Command +{ + protected String _registeredClientName; + protected String _errorMessage; + private CommandType _inReplyToCommandType; + + public Response(final String registeredclientName, final CommandType inReplyToCommandType, final String errorMessage) + { + super(CommandType.RESPONSE); + _registeredClientName = registeredclientName; + _errorMessage = errorMessage; + _inReplyToCommandType = inReplyToCommandType; + } + + public Response(String clientName, CommandType inReplyToCommandType) + { + this(clientName, inReplyToCommandType, null); + } + + /** + * Provided so that subclasses can call super(commandType) + */ + protected Response(CommandType commandType) + { + super(commandType); + } + + public String getRegisteredClientName() + { + return _registeredClientName; + } + + public void setRegisteredClientName(String registeredClientName) + { + _registeredClientName = registeredClientName; + } + + @OutputAttribute(attribute=ParticipantAttribute.ERROR_MESSAGE) + public String getErrorMessage() + { + return _errorMessage; + } + + public void setErrorMessage(String errorMessage) + { + _errorMessage = errorMessage; + } + + public boolean hasError() + { + return _errorMessage != null; + } + + public CommandType getInReplyToCommandType() + { + return _inReplyToCommandType; + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/StartTestCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/StartTestCommand.java new file mode 100644 index 0000000000..4a53697ecd --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/StartTestCommand.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +public class StartTestCommand extends Command +{ + + public StartTestCommand() + { + super(CommandType.START_TEST); + } + +} \ No newline at end of file diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/StopClientCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/StopClientCommand.java new file mode 100644 index 0000000000..08758aaa69 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/StopClientCommand.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +public class StopClientCommand extends Command +{ + public StopClientCommand() + { + super(CommandType.STOP_CLIENT); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/TearDownTestCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/TearDownTestCommand.java new file mode 100644 index 0000000000..6b1367d4f9 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/TearDownTestCommand.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +public class TearDownTestCommand extends Command +{ + + public TearDownTestCommand() + { + super(CommandType.TEAR_DOWN_TEST); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/AggregatedTestResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/AggregatedTestResult.java new file mode 100644 index 0000000000..5e6da2e65b --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/AggregatedTestResult.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.aggregation; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.qpid.disttest.message.ParticipantResult; + +public class AggregatedTestResult implements ITestResult +{ + private ParticipantResult _allParticipantResult; + private ParticipantResult _allConsumerParticipantResult; + private ParticipantResult _allProducerParticipantResult; + private final ITestResult _originalTestResult; + + public AggregatedTestResult(ITestResult originalTestResult) + { + _originalTestResult = originalTestResult; + } + + /** + * Returns the result where {@link ParticipantResult#getNumberOfMessagesProcessed()} + * is the total number of messages consumed during the test, and {@link ParticipantResult#getTimeTaken()} + * is the time between the start of the first producer and the end of the last consumer to finish. + */ + public ParticipantResult getAllParticipantResult() + { + return _allParticipantResult; + } + + public void setAllParticipantResult(ParticipantResult allParticipantResult) + { + _allParticipantResult = allParticipantResult; + } + + public ParticipantResult getAllConsumerParticipantResult() + { + return _allConsumerParticipantResult; + } + public void setAllConsumerParticipantResult(ParticipantResult allConsumerParticipantResult) + { + _allConsumerParticipantResult = allConsumerParticipantResult; + } + public ParticipantResult getAllProducerParticipantResult() + { + return _allProducerParticipantResult; + } + public void setAllProducerParticipantResult(ParticipantResult allProducerParticipantResult) + { + _allProducerParticipantResult = allProducerParticipantResult; + } + + // TODO should weaken to Collection + @Override + public List getParticipantResults() + { + List allParticipantResults = new ArrayList(_originalTestResult.getParticipantResults()); + + allParticipantResults.add(_allConsumerParticipantResult); + allParticipantResults.add(_allProducerParticipantResult); + allParticipantResults.add(_allParticipantResult); + + return allParticipantResults; + } + + @Override + public boolean hasErrors() + { + return _originalTestResult.hasErrors(); + } + + @Override + public String getName() + { + return _originalTestResult.getName(); + } + + + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/Aggregator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/Aggregator.java new file mode 100644 index 0000000000..cde30d36e5 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/Aggregator.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.aggregation; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; + +public class Aggregator +{ + + private TestResultAggregator _testResultAggregator = new TestResultAggregator(); + + public ResultsForAllTests aggregateResults(ResultsForAllTests rawResultsForAllTests) + { + + ResultsForAllTests aggregatedResultsForAllTests = new ResultsForAllTests(); + + + for (ITestResult testResult : rawResultsForAllTests.getTestResults()) + { + AggregatedTestResult aggregateTestResult = _testResultAggregator.aggregateTestResult(testResult); + aggregatedResultsForAllTests.add(aggregateTestResult); + } + + + return aggregatedResultsForAllTests; + } + + void setTestResultAggregator(TestResultAggregator testResultAggregator) + { + _testResultAggregator = testResultAggregator; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java new file mode 100644 index 0000000000..3f9cdff69d --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.aggregation; + +import java.util.List; + +import org.apache.qpid.disttest.message.ParticipantResult; + +// TODO rename me!! +public interface ITestResult +{ + + // TODO should weaken to Collection + List getParticipantResults(); + + boolean hasErrors(); + + String getName(); + +} \ No newline at end of file diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java new file mode 100644 index 0000000000..207d0131eb --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.results.aggregation; + +import java.util.Date; +import java.util.NavigableSet; +import java.util.TreeSet; + +import org.apache.qpid.disttest.message.ParticipantResult; + +public class ParticipantResultAggregator +{ + private final String _aggregatedResultName; + private final Class _targetClass; + + private long _minStartDate = Long.MAX_VALUE; + private long _maxEndDate = 0; + private long _numberOfMessagesProcessed = 0; + private long _totalPayloadProcessed = 0; + + private int _totalNumberOfConsumers = 0; + private int _totalNumberOfProducers = 0; + + private NavigableSet _encounteredPayloadSizes = new TreeSet(); + private NavigableSet _encounteredIterationNumbers = new TreeSet(); + private NavigableSet _encounteredBatchSizes = new TreeSet(); + private NavigableSet _encounteredAcknowledgeMode = new TreeSet(); + private NavigableSet _encountedTestNames = new TreeSet(); + + public ParticipantResultAggregator(Class targetClass, String aggregateResultName) + { + _aggregatedResultName = aggregateResultName; + _targetClass = targetClass; + } + + public void aggregate(ParticipantResult result) + { + if (isAggregatable(result)) + { + rollupConstantAttributes(result); + computeVariableAttributes(result); + } + } + + public ParticipantResult getAggregatedResult() + { + ParticipantResult aggregatedResult = new ParticipantResult(_aggregatedResultName); + + setRolledUpConstantAttributes(aggregatedResult); + setComputedVariableAttributes(aggregatedResult); + + return aggregatedResult; + } + + private boolean isAggregatable(ParticipantResult result) + { + return _targetClass.isAssignableFrom(result.getClass()); + } + + private void computeVariableAttributes(ParticipantResult result) + { + _numberOfMessagesProcessed += result.getNumberOfMessagesProcessed(); + _totalPayloadProcessed += result.getTotalPayloadProcessed(); + _totalNumberOfConsumers += result.getTotalNumberOfConsumers(); + _totalNumberOfProducers += result.getTotalNumberOfProducers(); + _minStartDate = Math.min(_minStartDate, result.getStartInMillis()); + _maxEndDate = Math.max(_maxEndDate, result.getEndInMillis()); + } + + private void rollupConstantAttributes(ParticipantResult result) + { + if (result.getTestName() != null) + { + _encountedTestNames.add(result.getTestName()); + } + _encounteredPayloadSizes.add(result.getPayloadSize()); + _encounteredIterationNumbers.add(result.getIterationNumber()); + _encounteredBatchSizes.add(result.getBatchSize()); + _encounteredAcknowledgeMode.add(result.getAcknowledgeMode()); + } + + private void setComputedVariableAttributes(ParticipantResult aggregatedResult) + { + aggregatedResult.setNumberOfMessagesProcessed(_numberOfMessagesProcessed); + aggregatedResult.setTotalPayloadProcessed(_totalPayloadProcessed); + aggregatedResult.setTotalNumberOfConsumers(_totalNumberOfConsumers); + aggregatedResult.setTotalNumberOfProducers(_totalNumberOfProducers); + aggregatedResult.setStartDate(new Date(_minStartDate)); + aggregatedResult.setEndDate(new Date(_maxEndDate)); + aggregatedResult.setThroughput(calculateThroughputInKiloBytesPerSecond()); + } + + private void setRolledUpConstantAttributes(ParticipantResult aggregatedResult) + { + if (_encounteredIterationNumbers.size() == 1) + { + aggregatedResult.setIterationNumber( _encounteredIterationNumbers.first()); + } + if (_encounteredPayloadSizes.size() == 1) + { + aggregatedResult.setPayloadSize(_encounteredPayloadSizes.first()); + } + if (_encountedTestNames.size() == 1) + { + aggregatedResult.setTestName(_encountedTestNames.first()); + } + if (_encounteredBatchSizes.size() == 1) + { + aggregatedResult.setBatchSize(_encounteredBatchSizes.first()); + } + if (_encounteredAcknowledgeMode.size() == 1) + { + aggregatedResult.setAcknowledgeMode(_encounteredAcknowledgeMode.first()); + } + } + + private double calculateThroughputInKiloBytesPerSecond() + { + double durationInMillis = _maxEndDate - _minStartDate; + double durationInSeconds = durationInMillis / 1000; + double totalPayloadProcessedInKiloBytes = ((double)_totalPayloadProcessed) / 1024; + + return totalPayloadProcessedInKiloBytes/durationInSeconds; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java new file mode 100644 index 0000000000..5934e0e997 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.aggregation; + +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; + +public class TestResultAggregator +{ + static final String AGGREGATED_ERROR_MESSAGE = "One or more participants reported errors."; + public static final String ALL_PARTICIPANTS_NAME = "All"; + public static final String ALL_PRODUCER_PARTICIPANTS_NAME = "All Producers"; + public static final String ALL_CONSUMER_PARTICIPANTS_NAME = "All Consumers"; + + public AggregatedTestResult aggregateTestResult(ITestResult originalTestResult) + { + ParticipantResultAggregator consumerResultAggregator = new ParticipantResultAggregator(ConsumerParticipantResult.class, + ALL_CONSUMER_PARTICIPANTS_NAME); + ParticipantResultAggregator producerResultAggregator = new ParticipantResultAggregator(ProducerParticipantResult.class, + ALL_PRODUCER_PARTICIPANTS_NAME); + ParticipantResultAggregator aggregatedResultsAggregator = new ParticipantResultAggregator(ParticipantResult.class, + ALL_PARTICIPANTS_NAME); + + boolean hasError = aggregateOriginalResults(originalTestResult, + consumerResultAggregator, + producerResultAggregator); + + ParticipantResult aggregatedProducerResult = producerResultAggregator.getAggregatedResult(); + ParticipantResult aggregaredConsumerResult = consumerResultAggregator.getAggregatedResult(); + + ParticipantResult aggregatedAllResult = aggregateAggregatedResults( + aggregatedResultsAggregator, aggregatedProducerResult, + aggregaredConsumerResult); + + applyNonAggregateablesToAll(aggregatedAllResult, + aggregatedProducerResult, aggregaredConsumerResult); + + AggregatedTestResult newTestResult = new AggregatedTestResult(originalTestResult); + newTestResult.setAllProducerParticipantResult(aggregatedProducerResult); + newTestResult.setAllConsumerParticipantResult(aggregaredConsumerResult); + newTestResult.setAllParticipantResult(aggregatedAllResult); + + if (hasError) + { + aggregatedAllResult.setErrorMessage(TestResultAggregator.AGGREGATED_ERROR_MESSAGE); + } + + return newTestResult; + } + + private ParticipantResult aggregateAggregatedResults( + ParticipantResultAggregator aggregatedResultsAggregator, + ParticipantResult aggregatedProducerResult, + ParticipantResult aggregaredConsumerResult) + { + aggregatedResultsAggregator.aggregate(aggregatedProducerResult); + aggregatedResultsAggregator.aggregate(aggregaredConsumerResult); + ParticipantResult aggregatedAllResult = aggregatedResultsAggregator.getAggregatedResult(); + return aggregatedAllResult; + } + + private boolean aggregateOriginalResults(ITestResult originalTestResult, + ParticipantResultAggregator consumerParticipantResultAggregator, + ParticipantResultAggregator producerParticipantResultAggregator) + { + boolean hasError = false; + for (ParticipantResult result : originalTestResult.getParticipantResults()) + { + consumerParticipantResultAggregator.aggregate(result); + producerParticipantResultAggregator.aggregate(result); + + if (result.hasError()) + { + hasError = true; + } + } + return hasError; + } + + private void applyNonAggregateablesToAll(ParticipantResult aggregatedAllResult, ParticipantResult aggregatedProducerResult, ParticipantResult aggregatedConsumerResult) + { + aggregatedAllResult.setStartDate(aggregatedProducerResult.getStartDate()); + aggregatedAllResult.setEndDate(aggregatedConsumerResult.getEndDate()); + + aggregatedAllResult.setNumberOfMessagesProcessed(aggregatedConsumerResult.getNumberOfMessagesProcessed()); + aggregatedAllResult.setTotalPayloadProcessed(aggregatedConsumerResult.getTotalPayloadProcessed()); + aggregatedAllResult.setThroughput(aggregatedConsumerResult.getThroughput()); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java new file mode 100644 index 0000000000..52e53ca624 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.formatting; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.message.ParticipantAttribute; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +/** + * produces CSV output using the ordered enums in {@link ParticipantAttribute} + */ +public class CSVFormater +{ + public String format(ResultsForAllTests results) + { + StringBuilder builder = new StringBuilder(); + + builder.append(header()); + + List testResults = results.getTestResults(); + + for (ITestResult testResult : testResults) + { + + List participantResults = new ArrayList(testResult.getParticipantResults()); + Collections.sort(participantResults, new CSVOrderParticipantResultComparator()); + + for (ParticipantResult participantResult : participantResults) + { + Map attributes = participantResult.getAttributes(); + builder.append(row(attributes)); + } + } + + return builder.toString(); + } + + /** + * return a row, including a newline character at the end + */ + private String row(Map attributeValueMap) + { + List attributeValues = new ArrayList(); + for (ParticipantAttribute attribute : ParticipantAttribute.values()) + { + attributeValues.add(attributeValueMap.get(attribute)); + } + + String row = StringUtils.join(attributeValues.toArray(), ","); + return row + "\n"; + } + + /** return the header row, including a newline at the end */ + private String header() + { + List displayNames = new ArrayList(); + for (ParticipantAttribute attribute : ParticipantAttribute.values()) + { + displayNames.add(attribute.getDisplayName()); + } + + String header = StringUtils.join(displayNames.toArray(), ","); + return header + "\n"; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparator.java new file mode 100644 index 0000000000..0e1fbbc3c6 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparator.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.formatting; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.builder.CompareToBuilder; +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; + +public class CSVOrderParticipantResultComparator implements Comparator +{ + // TODO yuk + private static final Map, Integer> TYPE_CODES = new HashMap, Integer>(); + static { + TYPE_CODES.put(ProducerParticipantResult.class, 0); + TYPE_CODES.put(ConsumerParticipantResult.class, 1); + TYPE_CODES.put(ParticipantResult.class, 2); + } + + @Override + public int compare(ParticipantResult left, ParticipantResult right) + { + return new CompareToBuilder() + .append(getTypeCode(left), getTypeCode(right)) + .append(left.getParticipantName(), right.getParticipantName()) + .toComparison(); + } + + + private int getTypeCode(ParticipantResult participantResult) + { + return TYPE_CODES.get(participantResult.getClass()); + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/oldtopic/Config.java b/java/perftests/src/main/java/org/apache/qpid/oldtopic/Config.java deleted file mode 100644 index 5b6169ed2d..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/oldtopic/Config.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.oldtopic; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.config.ConnectorConfig; -import org.apache.qpid.config.ConnectionFactoryInitialiser; -import org.apache.qpid.config.Connector; -import org.apache.qpid.config.AbstractConfig; - -import javax.jms.Connection; -import javax.jms.ConnectionFactory; - -class Config extends AbstractConfig implements ConnectorConfig -{ - - private String host = "localhost"; - private int port = 5672; - private String factory = null; - - private int payload = 256; - private int messages = 1000; - private int clients = 1; - private int batch = 1; - private long delay = 1; - private int warmup; - private int ackMode= AMQSession.NO_ACKNOWLEDGE; - private String clientId; - private String subscriptionId; - private boolean persistent; - - public Config() - { - } - - int getAckMode() - { - return ackMode; - } - - void setPayload(int payload) - { - this.payload = payload; - } - - int getPayload() - { - return payload; - } - - void setClients(int clients) - { - this.clients = clients; - } - - int getClients() - { - return clients; - } - - void setMessages(int messages) - { - this.messages = messages; - } - - int getMessages() - { - return messages; - } - - public String getHost() - { - return host; - } - - public void setHost(String host) - { - this.host = host; - } - - public int getPort() - { - return port; - } - - public String getFactory() - { - return factory; - } - - public void setPort(int port) - { - this.port = port; - } - - int getBatch() - { - return batch; - } - - void setBatch(int batch) - { - this.batch = batch; - } - - int getWarmup() - { - return warmup; - } - - void setWarmup(int warmup) - { - this.warmup = warmup; - } - - public long getDelay() - { - return delay; - } - - public void setDelay(long delay) - { - this.delay = delay; - } - - String getClientId() - { - return clientId; - } - - String getSubscriptionId() - { - return subscriptionId; - } - - boolean usePersistentMessages() - { - return persistent; - } - - public void setOption(String key, String value) - { - if("-host".equalsIgnoreCase(key)) - { - setHost(value); - } - else if("-port".equalsIgnoreCase(key)) - { - try - { - setPort(Integer.parseInt(value)); - } - catch(NumberFormatException e) - { - throw new RuntimeException("Bad port number: " + value); - } - } - else if("-payload".equalsIgnoreCase(key)) - { - setPayload(parseInt("Bad payload size", value)); - } - else if("-messages".equalsIgnoreCase(key)) - { - setMessages(parseInt("Bad message count", value)); - } - else if("-clients".equalsIgnoreCase(key)) - { - setClients(parseInt("Bad client count", value)); - } - else if("-batch".equalsIgnoreCase(key)) - { - setBatch(parseInt("Bad batch count", value)); - } - else if("-delay".equalsIgnoreCase(key)) - { - setDelay(parseLong("Bad batch delay", value)); - } - else if("-warmup".equalsIgnoreCase(key)) - { - setWarmup(parseInt("Bad warmup count", value)); - } - else if("-ack".equalsIgnoreCase(key)) - { - ackMode = parseInt("Bad ack mode", value); - } - else if("-factory".equalsIgnoreCase(key)) - { - factory = value; - } - else if("-clientId".equalsIgnoreCase(key)) - { - clientId = value; - } - else if("-subscriptionId".equalsIgnoreCase(key)) - { - subscriptionId = value; - } - else if("-persistent".equalsIgnoreCase(key)) - { - persistent = "true".equalsIgnoreCase(value); - } - else - { - System.out.println("Ignoring unrecognised option: " + key); - } - } - - static String getAckModeDescription(int ackMode) - { - switch(ackMode) - { - case AMQSession.NO_ACKNOWLEDGE: return "NO_ACKNOWLEDGE"; - case AMQSession.AUTO_ACKNOWLEDGE: return "AUTO_ACKNOWLEDGE"; - case AMQSession.CLIENT_ACKNOWLEDGE: return "CLIENT_ACKNOWLEDGE"; - case AMQSession.DUPS_OK_ACKNOWLEDGE: return "DUPS_OK_ACKNOWELDGE"; - case AMQSession.PRE_ACKNOWLEDGE: return "PRE_ACKNOWLEDGE"; - } - return "AckMode=" + ackMode; - } - - public Connection createConnection() throws Exception - { - return new Connector().createConnection(this); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/oldtopic/Listener.java b/java/perftests/src/main/java/org/apache/qpid/oldtopic/Listener.java deleted file mode 100644 index 4732782d4c..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/oldtopic/Listener.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.oldtopic; -import org.apache.log4j.*; -import javax.jms.Connection; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Session; - -public class Listener implements MessageListener -{ - private final Connection _connection; - private final MessageProducer _controller; - private final javax.jms.Session _session; - private final MessageFactory _factory; - private boolean init; - private int count; - private long start; - - Listener(Connection connection, int ackMode) throws Exception - { - this(connection, ackMode, null); - } - - Listener(Connection connection, int ackMode, String name) throws Exception - { - _connection = connection; - _session = connection.createSession(false, ackMode); - _factory = new MessageFactory(_session); - - //register for events - if(name == null) - { - _factory.createTopicConsumer().setMessageListener(this); - } - else - { - _factory.createDurableTopicConsumer(name).setMessageListener(this); - } - - _connection.start(); - - _controller = _factory.createControlPublisher(); - System.out.println("Waiting for messages " + - Config.getAckModeDescription(ackMode) - + (name == null ? "" : " (subscribed with name " + name + " and client id " + connection.getClientID() + ")") - + "..."); - - } - - private void shutdown() - { - try - { - _session.close(); - _connection.stop(); - _connection.close(); - } - catch(Exception e) - { - e.printStackTrace(System.out); - } - } - - private void report() - { - try - { - String msg = getReport(); - _controller.send(_factory.createReportResponseMessage(msg)); - System.out.println("Sent report: " + msg); - } - catch(Exception e) - { - e.printStackTrace(System.out); - } - } - - private String getReport() - { - long time = (System.currentTimeMillis() - start); - return "Received " + count + " in " + time + "ms"; - } - - public void onMessage(Message message) - { - if(!init) - { - start = System.currentTimeMillis(); - count = 0; - init = true; - } - - if(_factory.isShutdown(message)) - { - shutdown(); - } - else if(_factory.isReport(message)) - { - //send a report: - report(); - init = false; - } - else if (++count % 100 == 0) - { - System.out.println("Received " + count + " messages."); - } - } - - public static void main(String[] argv) throws Exception - { - Config config = new Config(); - config.setOptions(argv); - - Connection con = config.createConnection(); - if(config.getClientId() != null) - { - con.setClientID(config.getClientId()); - } - new Listener(con, config.getAckMode(), config.getSubscriptionId()); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/oldtopic/MessageFactory.java b/java/perftests/src/main/java/org/apache/qpid/oldtopic/MessageFactory.java deleted file mode 100644 index b2fbeb7e35..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/oldtopic/MessageFactory.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.oldtopic; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.AMQTopic; - -import javax.jms.*; - -/** - */ -class MessageFactory -{ - private static final char[] DATA = "abcdefghijklmnopqrstuvwxyz".toCharArray(); - - private final Session _session; - private final Topic _topic; - private final Topic _control; - private final byte[] _payload; - - - MessageFactory(Session session) throws JMSException - { - this(session, 256); - } - - MessageFactory(Session session, int size) throws JMSException - { - _session = session; -/* if(session instanceof AMQSession) - { - _topic = new AMQTopic("topictest.messages"); - _control = new AMQTopic("topictest.control"); - } - else*/ - { - _topic = session.createTopic("topictest.messages"); - _control = session.createTopic("topictest.control"); - } - _payload = new byte[size]; - - for(int i = 0; i < size; i++) - { - _payload[i] = (byte) DATA[i % DATA.length]; - } - } - - Topic getTopic() - { - return _topic; - } - - Message createEventMessage() throws JMSException - { - BytesMessage msg = _session.createBytesMessage(); - msg.writeBytes(_payload); - return msg; - } - - Message createShutdownMessage() throws JMSException - { - return _session.createTextMessage("SHUTDOWN"); - } - - Message createReportRequestMessage() throws JMSException - { - return _session.createTextMessage("REPORT"); - } - - Message createReportResponseMessage(String msg) throws JMSException - { - return _session.createTextMessage(msg); - } - - boolean isShutdown(Message m) - { - return checkText(m, "SHUTDOWN"); - } - - boolean isReport(Message m) - { - return checkText(m, "REPORT"); - } - - Object getReport(Message m) - { - try - { - return ((TextMessage) m).getText(); - } - catch (JMSException e) - { - e.printStackTrace(System.out); - return e.toString(); - } - } - - MessageConsumer createTopicConsumer() throws Exception - { - return _session.createConsumer(_topic); - } - - MessageConsumer createDurableTopicConsumer(String name) throws Exception - { - return _session.createDurableSubscriber(_topic, name); - } - - MessageConsumer createControlConsumer() throws Exception - { - return _session.createConsumer(_control); - } - - MessageProducer createTopicPublisher() throws Exception - { - return _session.createProducer(_topic); - } - - MessageProducer createControlPublisher() throws Exception - { - return _session.createProducer(_control); - } - - private static boolean checkText(Message m, String s) - { - try - { - return m instanceof TextMessage && ((TextMessage) m).getText().equals(s); - } - catch (JMSException e) - { - e.printStackTrace(System.out); - return false; - } - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/oldtopic/Publisher.java b/java/perftests/src/main/java/org/apache/qpid/oldtopic/Publisher.java deleted file mode 100644 index 841fcc63ad..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/oldtopic/Publisher.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.oldtopic; - -import javax.jms.*; - -public class Publisher implements MessageListener -{ - private final Object _lock = new Object(); - private final Connection _connection; - private final Session _session; - private final MessageFactory _factory; - private final MessageProducer _publisher; - private int _count; - - Publisher(Connection connection, int size, int ackMode, boolean persistent) throws Exception - { - _connection = connection; - _session = _connection.createSession(false, ackMode); - _factory = new MessageFactory(_session, size); - _publisher = _factory.createTopicPublisher(); - _publisher.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); - System.out.println("Publishing " + (persistent ? "persistent" : "non-persistent") + " messages of " + size + " bytes, " + Config.getAckModeDescription(ackMode) + "."); - } - - private void test(Config config) throws Exception - { - test(config.getBatch(), config.getDelay(), config.getMessages(), config.getClients(), config.getWarmup()); - } - - private void test(int batches, long delay, int msgCount, int consumerCount, int warmup) throws Exception - { - _factory.createControlConsumer().setMessageListener(this); - _connection.start(); - - if(warmup > 0) - { - System.out.println("Runing warmup (" + warmup + " msgs)"); - long time = batch(warmup, consumerCount); - System.out.println("Warmup completed in " + time + "ms"); - } - - long[] times = new long[batches]; - for(int i = 0; i < batches; i++) - { - if(i > 0) - { - Thread.sleep(delay*1000); - } - times[i] = batch(msgCount, consumerCount); - System.out.println("Batch " + (i+1) + " of " + batches + " completed in " + times[i] + " ms."); - } - - long min = min(times); - long max = max(times); - System.out.println("min: " + min + ", max: " + max + " avg: " + avg(times, min, max)); - - //request shutdown - _publisher.send(_factory.createShutdownMessage()); - - _connection.stop(); - _connection.close(); - } - - private long batch(int msgCount, int consumerCount) throws Exception - { - _count = consumerCount; - long start = System.currentTimeMillis(); - publish(msgCount); - waitForCompletion(consumerCount); - return System.currentTimeMillis() - start; - } - - private void publish(int count) throws Exception - { - - //send events - for (int i = 0; i < count; i++) - { - _publisher.send(_factory.createEventMessage()); - if ((i + 1) % 100 == 0) - { - System.out.println("Sent " + (i + 1) + " messages"); - } - } - - //request report - _publisher.send(_factory.createReportRequestMessage()); - } - - private void waitForCompletion(int consumers) throws Exception - { - System.out.println("Waiting for completion..."); - synchronized (_lock) - { - while (_count > 0) - { - _lock.wait(); - } - } - } - - - public void onMessage(Message message) - { - System.out.println("Received report " + _factory.getReport(message) + " " + --_count + " remaining"); - if (_count == 0) - { - synchronized (_lock) - { - _lock.notify(); - } - } - } - - static long min(long[] times) - { - long min = times.length > 0 ? times[0] : 0; - for(int i = 0; i < times.length; i++) - { - min = Math.min(min, times[i]); - } - return min; - } - - static long max(long[] times) - { - long max = times.length > 0 ? times[0] : 0; - for(int i = 0; i < times.length; i++) - { - max = Math.max(max, times[i]); - } - return max; - } - - static long avg(long[] times, long min, long max) - { - long sum = 0; - for(int i = 0; i < times.length; i++) - { - sum += times[i]; - } - sum -= min; - sum -= max; - - return (sum / (times.length - 2)); - } - - public static void main(String[] argv) throws Exception - { - Config config = new Config(); - config.setOptions(argv); - - Connection con = config.createConnection(); - int size = config.getPayload(); - int ackMode = config.getAckMode(); - boolean persistent = config.usePersistentMessages(); - new Publisher(con, size, ackMode, persistent).test(config); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingAsyncTestPerf.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingAsyncTestPerf.java deleted file mode 100644 index b55dac45c7..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/ping/PingAsyncTestPerf.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.ping; - -import junit.framework.Test; -import junit.framework.TestSuite; - -import org.apache.log4j.Logger; - -import org.apache.qpid.requestreply.PingPongProducer; - -import org.apache.qpid.junit.extensions.TimingController; -import org.apache.qpid.junit.extensions.TimingControllerAware; - -import javax.jms.JMSException; -import javax.jms.Message; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -/** - * PingAsyncTestPerf is a performance test that outputs multiple timings from its test method, using the timing controller - * interface supplied by the test runner from a seperate listener thread. It differs from the {@link PingTestPerf} test - * that it extends because it can output timings as replies are received, rather than waiting until all expected replies - * are received. This is less 'blocky' than the tests in {@link PingTestPerf}, and provides a truer simulation of sending - * and recieving clients working asynchronously. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Send many ping messages and output timings asynchronously on batches received. - *
- */ -public class PingAsyncTestPerf extends PingTestPerf implements TimingControllerAware -{ - private static Logger _logger = Logger.getLogger(PingAsyncTestPerf.class); - - /** Holds the name of the property to get the test results logging batch size. */ - public static final String TEST_RESULTS_BATCH_SIZE_PROPNAME = "batchSize"; - - /** Holds the default test results logging batch size. */ - public static final int TEST_RESULTS_BATCH_SIZE_DEFAULT = 1000; - - /** Used to hold the timing controller passed from the test runner. */ - private TimingController _timingController; - - /** Used to generate unique correlation ids for each test run. */ - private AtomicLong corellationIdGenerator = new AtomicLong(); - - /** Holds test specifics by correlation id. This consists of the expected number of messages and the timing controler. */ - private Map perCorrelationIds = - Collections.synchronizedMap(new HashMap()); - - /** Holds the batched results listener, that does logging on batch boundaries. */ - private BatchedResultsListener batchedResultsListener = null; - - /** - * Creates a new asynchronous ping performance test with the specified name. - * - * @param name The test name. - */ - public PingAsyncTestPerf(String name) - { - super(name); - - // Sets up the test parameters with defaults. - testParameters.setPropertyIfNull(TEST_RESULTS_BATCH_SIZE_PROPNAME, - Integer.toString(TEST_RESULTS_BATCH_SIZE_DEFAULT)); - } - - /** - * Compile all the tests into a test suite. - * @return The test suite to run. Should only contain testAsyncPingOk method. - */ - public static Test suite() - { - // Build a new test suite - TestSuite suite = new TestSuite("Ping Performance Tests"); - - // Run performance tests in read committed mode. - suite.addTest(new PingAsyncTestPerf("testAsyncPingOk")); - - return suite; - } - - /** - * Accepts a timing controller from the test runner. - * - * @param timingController The timing controller to register mutliple timings with. - */ - public void setTimingController(TimingController timingController) - { - _timingController = timingController; - } - - /** - * Gets the timing controller passed in by the test runner. - * - * @return The timing controller passed in by the test runner. - */ - public TimingController getTimingController() - { - return _timingController; - } - - /** - * Sends the specified number of pings, asynchronously outputs timings on every batch boundary, and waits until - * all replies have been received or a time out occurs before exiting this method. - * - * @param numPings The number of pings to send. - * @throws Exception pass all errors out to the test harness - */ - public void testAsyncPingOk(int numPings) throws Exception - { - // _logger.debug("public void testAsyncPingOk(int numPings): called"); - - // get prefill count to update the expected count - int preFill = testParameters.getPropertyAsInteger(PingPongProducer.PREFILL_PROPNAME); - - // Ensure that at least one ping was requeusted. - if (numPings + preFill == 0) - { - _logger.error("Number of pings requested was zero."); - fail("Number of pings requested was zero."); - } - - // Get the per thread test setup to run the test through. - PerThreadSetup perThreadSetup = threadSetup.get(); - PingClient pingClient = perThreadSetup._pingClient; - - // Advance the correlation id of messages to send, to make it unique for this run. - perThreadSetup._correlationId = Long.toString(corellationIdGenerator.incrementAndGet()); - // String messageCorrelationId = perThreadSetup._correlationId; - // _logger.debug("messageCorrelationId = " + messageCorrelationId); - - - // Initialize the count and timing controller for the new correlation id. - // This perCorrelationId is only used for controlling the test. - // The PingClient itself uses its own perCorrelationId see in PingPongProducer - PerCorrelationId perCorrelationId = new PerCorrelationId(); - TimingController tc = getTimingController().getControllerForCurrentThread(); - perCorrelationId._tc = tc; - perCorrelationId._expectedCount = pingClient.getExpectedNumPings(numPings + preFill); - perCorrelationIds.put(perThreadSetup._correlationId, perCorrelationId); - - // Must be called before pingAndWaitForReply to setup the CorrelationID. - // This is required because pingClient.start() will start all client threads - // This means that the CorrelationID must be registered before hand. - pingClient.setupCorrelationID(perThreadSetup._correlationId, perCorrelationId._expectedCount); - - // Start the client connection if: - // 1) we are not in a SEND_ONLY test. - // 2) if we have not yet started client because messages are sitting on broker. - // This is either due to a preFill or a consume only test. - if (!testParameters.getPropertyAsBoolean(PingPongProducer.SEND_ONLY_PROPNAME) && - (preFill > 0 || testParameters.getPropertyAsBoolean(PingPongProducer.CONSUME_ONLY_PROPNAME))) - { - pingClient.start(); - } - - // Send the requested number of messages, and wait until they have all been received. - long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME)); - int numReplies = pingClient.pingAndWaitForReply(null, numPings , preFill, timeout, perThreadSetup._correlationId); - - // Check that all the replies were received and log a fail if they were not. - if (numReplies < perCorrelationId._expectedCount) - { - System.out.println("##### " + numReplies + "replies, expected " + perCorrelationId._expectedCount + " #####"); - perCorrelationId._tc.completeTest(false, numPings - perCorrelationId._expectedCount); - } - - // Remove the expected count and timing controller for the message correlation id, to ensure they are cleaned up. - perCorrelationIds.remove(perThreadSetup._correlationId); - } - - /** - * Performs test fixture creation on a per thread basis. This will only be called once for each test thread. - */ - public void threadSetUp() - { - _logger.debug("public void threadSetUp(): called"); - - try - { - // Call the set up method in the super class. This creates a PingClient pinger. - super.threadSetUp(); - - // Create the chained message listener, only if it has not already been created. This is set up with the - // batch size property, to tell it what batch size to output results on. A synchronized block is used to - // ensure that only one thread creates this. - synchronized (this) - { - if (batchedResultsListener == null) - { - int batchSize = Integer.parseInt(testParameters.getProperty(TEST_RESULTS_BATCH_SIZE_PROPNAME)); - batchedResultsListener = new BatchedResultsListener(batchSize); - } - } - - // Get the set up that the super class created. - PerThreadSetup perThreadSetup = threadSetup.get(); - - // Register the chained message listener on the pinger to do its asynchronous test timings from. - perThreadSetup._pingClient.setChainedMessageListener(batchedResultsListener); - } - catch (Exception e) - { - _logger.warn("There was an exception during per thread setup.", e); - } - } - - /** - * BatchedResultsListener is a {@link PingPongProducer.ChainedMessageListener} that can be attached to the - * pinger, in order to receive notifications about every message received and the number remaining to be - * received. Whenever the number remaining crosses a batch size boundary this results listener outputs - * a test timing for the actual number of messages received in the current batch. - */ - private class BatchedResultsListener implements PingPongProducer.ChainedMessageListener - { - /** The test results logging batch size. */ - int _batchSize; - - /** The latency recoreded for the batch */ - private long _batchLatency = 0; - - /** - * Creates a results listener on the specified batch size. - * - * @param batchSize The batch size to use. - */ - public BatchedResultsListener(int batchSize) - { - _batchSize = batchSize; - } - - /** - * This callback method is called from all of the pingers that this test creates. It uses the correlation id - * from the message to identify the timing controller for the test thread that was responsible for sending those - * messages. - * - * @param message The message. - * @param remainingCount The count of messages remaining to be received with a particular correlation id. - * - * @throws JMSException Any underlying JMSException is allowed to fall through. - */ - public void onMessage(Message message, int remainingCount, long latency) throws JMSException - { - // Record the latency for the whole batch - _batchLatency += latency; - // Check if a batch boundary has been crossed. - if ((remainingCount % _batchSize) == 0) - { - // Extract the correlation id from the message. - String correlationId = message.getJMSCorrelationID(); - - /*_logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount - + "): called on batch boundary for message id: " + correlationId + " with thread id: " - + Thread.currentThread().getId());*/ - - // Get the details for the correlation id and check that they are not null. They can become null - // if a test times out. - PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationId); - if (perCorrelationId != null) - { - // Get the timing controller and expected count for this correlation id. - TimingController tc = perCorrelationId._tc; - int expected = perCorrelationId._expectedCount; - - // Calculate how many messages were actually received in the last batch. This will be the batch size - // except where the number expected is not a multiple of the batch size and this is the first remaining - // count to cross a batch size boundary, in which case it will be the number expected modulo the batch - // size. - int receivedInBatch = ((expected - remainingCount) < _batchSize) ? (expected % _batchSize) : _batchSize; - - // Register a test result for the correlation id. - try - { - // Record the total latency for the batch. - // if batchSize=1 then this will just be the message latency - tc.completeTest(true, receivedInBatch, null, _batchSize == 1 ? latency : _batchLatency); - // Reset latency - _batchLatency = 0; - } - catch (InterruptedException e) - { - // Ignore this. It means the test runner wants to stop as soon as possible. - _logger.warn("Got InterruptedException.", e); - } - } - // Else ignore, test timed out. Should log a fail here? - } - } - } - - /** - * Holds state specific to each correlation id, needed to output test results. This consists of the count of - * the total expected number of messages, and the timing controller for the thread sending those message ids. - */ - private static class PerCorrelationId - { - public int _expectedCount; - public TimingController _tc; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java deleted file mode 100644 index dcfc67d4fc..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.ping; - -import org.apache.log4j.Logger; - -import org.apache.qpid.requestreply.PingPongProducer; - -import javax.jms.Destination; - -import java.util.List; -import java.util.Properties; - -/** - * PingClient is a {@link PingPongProducer} that does not need a {@link org.apache.qpid.requestreply.PingPongBouncer} - * to send replies to its pings. It simply listens to its own ping destinations, rather than seperate reply queues. - * It is an all in one ping client, that produces and consumes its own pings. - * - *

The constructor increments a count of the number of ping clients created. It is assumed that where many - * are created they will all be run in parallel and be active in sending and consuming pings at the same time. - * If the unique destinations flag is not set and a pub/sub ping cycle is being run, this means that they will all hear - * pings sent by each other. The expected number of pings received will therefore be multiplied up by the number of - * active ping clients. The {@link #getConsumersPerDestination()} method is used to supply this multiplier under these - * conditions. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Create a ping producer that listens to its own pings {@link PingPongProducer} - *
Count the number of ping producers and produce multiplier for scaling up messages expected over topic pings. - *
- */ -public class PingClient extends PingPongProducer -{ - /** Used for debugging. */ - private final Logger log = Logger.getLogger(PingClient.class); - - /** Used to count the number of ping clients created. */ - private static int _pingClientCount; - - /** - * Creates a ping producer with the specified parameters, of which there are many. See the class level comments - * for {@link PingPongProducer} for details. This constructor creates a connection to the broker and creates - * producer and consumer sessions on it, to send and recieve its pings and replies on. - * - * @param overrides Properties containing any desired overrides to the defaults. - * - * @throws Exception Any exceptions are allowed to fall through. - */ - public PingClient(Properties overrides) throws Exception - { - super(overrides); - - _pingClientCount++; - } - - /** - * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the - * effect of making this pinger listen to its own pings. - * - * @return The ping destinations. - */ - public List getReplyDestinations() - { - return _pingDestinations; - } - - /** - * Supplies the multiplier for the number of ping clients that will hear each ping when doing pub/sub pinging. - * - * @return The scaling up of the number of expected pub/sub pings. - */ - public int getConsumersPerDestination() - { - log.debug("public int getConsumersPerDestination(): called"); - - if (_isUnique) - { - log.debug(_noOfConsumers + " consumer per destination."); - - return _noOfConsumers; - } - else - { - log.debug((_pingClientCount * _noOfConsumers) + " consumers per destination."); - - return _pingClientCount * _noOfConsumers; - } - } - - public int getClientCount() - { - return _pingClientCount; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java deleted file mode 100644 index a15897c82b..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java +++ /dev/null @@ -1,452 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.ping; - -import org.apache.log4j.Logger; - -import org.apache.qpid.requestreply.PingPongProducer; -import org.apache.qpid.util.CommandLineParser; - -import org.apache.qpid.junit.extensions.util.MathUtils; -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -import javax.jms.*; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * PingDurableClient is a variation of the {@link PingPongProducer} ping tool. Instead of sending its pings and - * receiving replies to them at the same time, this tool sends pings until it is signalled by some 'event' to stop - * sending. It then waits for another signal before it re-opens a fresh connection and attempts to receive all of the - * pings that it has succesfully sent. It is intended to be an interactive test that lets a user experiment with - * failure conditions when using durable messaging. - * - *

The events that can stop it from sending are input from the user on the console, failure of its connection to - * the broker, completion of sending a specified number of messages, or expiry of a specified duration. In all cases - * it will do its best to clean up and close the connection before opening a fresh connection to receive the pings - * with. - * - *

The event to re-connect and attempt to recieve the pings is input from the user on the console. - * - *

This ping client inherits the configuration properties of its parent class ({@link PingPongProducer}) and - * additionally accepts the following parameters: - * - *

- *
Parameters
Parameter Default Comments - *
numMessages 100 The total number of messages to send. - *
numMessagesToAction -1 The number of messages to send before taking a custom 'action'. - *
duration 30S The length of time to ping for. (Format dDhHmMsS, for d days, h hours, - * m minutes and s seconds). - *
- * - *

This ping client also overrides some of the defaults of its parent class, to provide a reasonable set up - * when no parameters are specified. - * - *

- *
Parameters
Parameter Default Comments - *
uniqueDests false Prevents destination names being timestamped. - *
transacted true Only makes sense to test with transactions. - *
persistent true Only makes sense to test persistent. - *
durableDests true Should use durable queues with persistent messages. - *
commitBatchSize 10 - *
rate 20 Total default test time is 5 seconds. - *
- * - *

When a number of messages or duration is specified, this ping client will ping until the first of those limits - * is reached. Reaching the limit will be interpreted as the first signal to stop sending, and the ping client will - * wait for the second signal before receiving its pings. - * - *

This class provides a mechanism for extensions to add arbitrary actions, after a particular number of messages - * have been sent. When the number of messages equal the value set in the 'numMessagesToAction' property is method, - * the {@link #takeAction} method is called. By default this does nothing, but extensions of this class can provide - * custom behaviour with alternative implementations of this method (for example taking a backup). - * - *

- *
CRC Card
Responsibilities Collaborations - *
Send and receive pings. - *
Accept user input to signal stop sending. - *
Accept user input to signal start receiving. - *
Provide feedback on pings sent versus pings received. - *
Provide extension point for arbitrary action on a particular message count. - *
- */ -public class PingDurableClient extends PingPongProducer implements ExceptionListener -{ - private static final Logger log = Logger.getLogger(PingDurableClient.class); - - public static final String NUM_MESSAGES_PROPNAME = "numMessages"; - public static final String NUM_MESSAGES_DEFAULT = "100"; - public static final String DURATION_PROPNAME = "duration"; - public static final String DURATION_DEFAULT = "30S"; - public static final String NUM_MESSAGES_TO_ACTION_PROPNAME = "numMessagesToAction"; - public static final String NUM_MESSAGES_TO_ACTION_DEFAULT = "-1"; - - /** The maximum length of time to wait whilst receiving pings before assuming that no more are coming. */ - private static final long TIME_OUT = 3000; - - static - { - defaults.setProperty(NUM_MESSAGES_PROPNAME, NUM_MESSAGES_DEFAULT); - defaults.setProperty(DURATION_PROPNAME, DURATION_DEFAULT); - defaults.setProperty(UNIQUE_DESTS_PROPNAME, "false"); - defaults.setProperty(TRANSACTED_PROPNAME, "true"); - defaults.setProperty(PERSISTENT_MODE_PROPNAME, "true"); - defaults.setProperty(TX_BATCH_SIZE_PROPNAME, "10"); - defaults.setProperty(RATE_PROPNAME, "20"); - defaults.setProperty(DURABLE_DESTS_PROPNAME, "true"); - defaults.setProperty(NUM_MESSAGES_TO_ACTION_PROPNAME, NUM_MESSAGES_TO_ACTION_DEFAULT); - } - - /** Specifies the number of pings to send, if larger than 0. 0 means send until told to stop. */ - private int numMessages; - - /** Holds the number of messages to send before taking triggering the action. */ - private int numMessagesToAction; - - /** Sepcifies how long to ping for, if larger than 0. 0 means send until told to stop. */ - private long duration; - - /** Used to indciate that this application should terminate. Set by the shutdown hook. */ - private boolean terminate = false; - - /** - * @throws Exception Any exceptions are allowed to fall through. - */ - public PingDurableClient(Properties overrides) throws Exception - { - super(overrides); - log.debug("public PingDurableClient(Properties overrides = " + overrides + "): called"); - - // Extract the additional configuration parameters. - ParsedProperties properties = new ParsedProperties(defaults); - properties.putAll(overrides); - - numMessages = properties.getPropertyAsInteger(NUM_MESSAGES_PROPNAME); - String durationSpec = properties.getProperty(DURATION_PROPNAME); - numMessagesToAction = properties.getPropertyAsInteger(NUM_MESSAGES_TO_ACTION_PROPNAME); - - if (durationSpec != null) - { - duration = MathUtils.parseDuration(durationSpec) * 1000000; - } - } - - /** - * Starts the ping/wait/receive process. - * - * @param args The command line arguments. - */ - public static void main(String[] args) - { - try - { - // Create a ping producer overriding its defaults with all options passed on the command line. - Properties options = - CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties()); - PingDurableClient pingProducer = new PingDurableClient(options); - - // Create a shutdown hook to terminate the ping-pong producer. - Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook()); - - // Ensure that the ping pong producer is registered to listen for exceptions on the connection too. - // pingProducer.getConnection().setExceptionListener(pingProducer); - - // Run the test procedure. - int sent = pingProducer.send(); - pingProducer.closeConnection(); - pingProducer.waitForUser("Press return to begin receiving the pings."); - pingProducer.receive(sent); - - System.exit(0); - } - catch (Exception e) - { - System.err.println(e.getMessage()); - log.error("Top level handler caught execption.", e); - System.exit(1); - } - } - - /** - * Performs the main test procedure implemented by this ping client. See the class level comment for details. - */ - protected int send() throws Exception - { - log.debug("public void sendWaitReceive(): called"); - - log.debug("duration = " + duration); - log.debug("numMessages = " + numMessages); - - if (duration > 0) - { - System.out.println("Sending for up to " + (duration / 1000000000f) + " seconds."); - } - - if (_rate > 0) - { - System.out.println("Sending at " + _rate + " messages per second."); - } - - if (numMessages > 0) - { - System.out.println("Sending up to " + numMessages + " messages."); - } - - // Establish the connection and the message producer. - establishConnection(true, false); - _connection.start(); - - Message message = getTestMessage(getReplyDestinations().get(0), _messageSize, _persistent); - - // Send pings until a terminating condition is received. - boolean endCondition = false; - int messagesSent = 0; - int messagesCommitted = 0; - int messagesNotCommitted = 0; - long start = System.nanoTime(); - - // Clear console in. - clearConsole(); - - while (!endCondition) - { - boolean committed = false; - - try - { - committed = sendMessage(messagesSent, message) && _transacted; - - messagesSent++; - messagesNotCommitted++; - - // Keep count of the number of messsages currently committed and pending commit. - if (committed) - { - log.debug("Adding " + messagesNotCommitted + " messages to the committed count."); - messagesCommitted += messagesNotCommitted; - messagesNotCommitted = 0; - - System.out.println("Commited: " + messagesCommitted); - } - } - catch (JMSException e) - { - log.debug("Got JMSException whilst sending."); - _publish = false; - } - - // Perform the arbitrary action if the number of messages sent has reached the right number. - if (messagesSent == numMessagesToAction) - { - System.out.println("At action point, Messages sent = " + messagesSent + ", Messages Committed = " - + messagesCommitted + ", Messages not Committed = " + messagesNotCommitted); - takeAction(); - } - - // Determine if the end condition has been met, based on the number of messages, time passed, errors on - // the connection or user input. - long now = System.nanoTime(); - - if ((duration != 0) && ((now - start) > duration)) - { - System.out.println("Send halted because duration expired."); - endCondition = true; - } - else if ((numMessages != 0) && (messagesSent >= numMessages)) - { - System.out.println("Send halted because # messages completed."); - endCondition = true; - } - else if (System.in.available() > 0) - { - System.out.println("Send halted by user input."); - endCondition = true; - - clearConsole(); - } - else if (!_publish) - { - System.out.println("Send halted by error on the connection."); - endCondition = true; - } - } - - log.debug("messagesSent = " + messagesSent); - log.debug("messagesCommitted = " + messagesCommitted); - log.debug("messagesNotCommitted = " + messagesNotCommitted); - - System.out.println("Messages sent: " + messagesSent + ", Messages Committed = " + messagesCommitted - + ", Messages not Committed = " + messagesNotCommitted); - - return messagesSent; - } - - protected void closeConnection() - { - // Clean up the connection. - try - { - close(); - } - catch (JMSException e) - { - log.debug("There was an error whilst closing the connection: " + e, e); - System.out.println("There was an error whilst closing the connection."); - - // Ignore as did best could manage to clean up. - } - } - - protected void receive(int messagesSent) throws Exception - { - // Re-establish the connection and the message consumer. - _queueJVMSequenceID = new AtomicInteger(); - _queueSharedID = new AtomicInteger(); - - establishConnection(false, true); - _consumer[0].setMessageListener(null); - _consumerConnection[0].start(); - - // Try to receive all of the pings that were successfully sent. - int messagesReceived = 0; - boolean endCondition = false; - - while (!endCondition) - { - // Message received = _consumer.receiveNoWait(); - Message received = _consumer[0].receive(TIME_OUT); - log.debug("received = " + received); - - if (received != null) - { - messagesReceived++; - } - - // Determine if the end condition has been met, based on the number of messages and time passed since last - // receiving a message. - if (received == null) - { - System.out.println("Timed out."); - endCondition = true; - } - else if (messagesReceived >= messagesSent) - { - System.out.println("Got all messages."); - endCondition = true; - } - } - - // Ensure messages received are committed. - if (_consTransacted) - { - try - { - _consumerSession[0].commit(); - System.out.println("Committed for all messages received."); - } - catch (JMSException e) - { - log.debug("Error during commit: " + e, e); - System.out.println("Error during commit."); - try - { - _consumerSession[0].rollback(); - System.out.println("Rolled back on all messages received."); - } - catch (JMSException e2) - { - log.debug("Error during rollback: " + e, e); - System.out.println("Error on roll back of all messages received."); - } - - } - } - - log.debug("messagesReceived = " + messagesReceived); - - System.out.println("Messages received: " + messagesReceived); - - // Clean up the connection. - close(); - } - - /** - * Clears any pending input from the console. - */ - private void clearConsole() - { - try - { - BufferedReader bis = new BufferedReader(new InputStreamReader(System.in)); - - // System.in.skip(System.in.available()); - while (bis.ready()) - { - bis.readLine(); - } - } - catch (IOException e) - { } - } - - /** - * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the - * effect of making this pinger listen to its own pings. - * - * @return The ping destinations. - */ - public List getReplyDestinations() - { - return _pingDestinations; - } - - /** - * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered with - * the runtime system as a shutdown hook. This shutdown hook sets an additional terminate flag, compared with the - * shutdown hook in {@link PingPongProducer}, because the publish flag is used to indicate that sending or receiving - * message should stop, not that the application should termiante. - * - * @return A shutdown hook for the ping loop. - */ - public Thread getShutdownHook() - { - return new Thread(new Runnable() - { - public void run() - { - stop(); - terminate = true; - } - }); - } - - /** - * Performs an aribtrary action once the 'numMesagesToAction' count is reached on sending messages. This default - * implementation does nothing. - */ - public void takeAction() - { } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java deleted file mode 100644 index 5ba4004c56..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.ping; - -import junit.framework.Test; -import junit.framework.TestSuite; - -import org.apache.log4j.Logger; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.requestreply.PingPongProducer; - -import org.apache.qpid.junit.extensions.TimingController; -import org.apache.qpid.junit.extensions.TimingControllerAware; -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -import javax.jms.JMSException; -import javax.jms.Message; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -/** - * PingLatencyTestPerf is a performance test that outputs multiple timings from its test method, using the timing - * controller interface supplied by the test runner from a seperate listener thread. It outputs round trip timings for - * individual ping messages rather than for how long a complete batch of messages took to process. It also differs from - * the {@link PingTestPerf} test that it extends because it can output timings as replies are received, rather than - * waiting until all expected replies are received. - * - *

This test does not output timings for every single ping message, as when running at high volume, writing the test - * log for a vast number of messages would slow the testing down. Instead samples ping latency occasionally. The - * frequency of ping sampling is set using the {@link #TEST_RESULTS_BATCH_SIZE_PROPNAME} property, to override the - * default of every {@link #DEFAULT_TEST_RESULTS_BATCH_SIZE}. - * - *

The size parameter logged for each individual ping is set to the size of the batch of messages that the - * individual timed ping was taken from, rather than 1 for a single message. This is so that the total throughput - * (messages / time) can be calculated in order to examine the relationship between throughput and latency. - * - *

CRC Card
Responsibilities Collaborations
Send many ping - * messages and output timings for sampled individual pings.
- */ -public class PingLatencyTestPerf extends PingTestPerf implements TimingControllerAware -{ - private static Logger _logger = Logger.getLogger(PingLatencyTestPerf.class); - - /** Holds the name of the property to get the test results logging batch size. */ - public static final String TEST_RESULTS_BATCH_SIZE_PROPNAME = "batchSize"; - - /** Holds the default test results logging batch size. */ - public static final int DEFAULT_TEST_RESULTS_BATCH_SIZE = 1000; - - /** Used to hold the timing controller passed from the test runner. */ - private TimingController _timingController; - - /** Used to generate unique correlation ids for each test run. */ - private AtomicLong corellationIdGenerator = new AtomicLong(); - - /** - * Holds test specifics by correlation id. This consists of the expected number of messages and the timing - * controler. - */ - private Map perCorrelationIds = - Collections.synchronizedMap(new HashMap()); - - /** Holds the batched results listener, that does logging on batch boundaries. */ - private BatchedResultsListener batchedResultsListener = null; - - /** - * Creates a new asynchronous ping performance test with the specified name. - * - * @param name The test name. - */ - public PingLatencyTestPerf(String name) - { - super(name); - - // Sets up the test parameters with defaults. - ParsedProperties.setSysPropertyIfNull(TEST_RESULTS_BATCH_SIZE_PROPNAME, - Integer.toString(DEFAULT_TEST_RESULTS_BATCH_SIZE)); - } - - /** Compile all the tests into a test suite. */ - public static Test suite() - { - // Build a new test suite - TestSuite suite = new TestSuite("Ping Latency Tests"); - - // Run performance tests in read committed mode. - suite.addTest(new PingLatencyTestPerf("testPingLatency")); - - return suite; - } - - /** - * Accepts a timing controller from the test runner. - * - * @param timingController The timing controller to register mutliple timings with. - */ - public void setTimingController(TimingController timingController) - { - _timingController = timingController; - } - - /** - * Gets the timing controller passed in by the test runner. - * - * @return The timing controller passed in by the test runner. - */ - public TimingController getTimingController() - { - return _timingController; - } - - /** - * Sends the specified number of pings, asynchronously outputs timings on every batch boundary, and waits until all - * replies have been received or a time out occurs before exiting this method. - * - * @param numPings The number of pings to send. - */ - public void testPingLatency(int numPings) throws Exception - { - _logger.debug("public void testPingLatency(int numPings): called"); - - // Ensure that at least one ping was requeusted. - if (numPings == 0) - { - _logger.error("Number of pings requested was zero."); - } - - // Get the per thread test setup to run the test through. - PerThreadSetup perThreadSetup = threadSetup.get(); - PingClient pingClient = perThreadSetup._pingClient; - - // Advance the correlation id of messages to send, to make it unique for this run. - String messageCorrelationId = Long.toString(corellationIdGenerator.incrementAndGet()); - _logger.debug("messageCorrelationId = " + messageCorrelationId); - - // Initialize the count and timing controller for the new correlation id. - PerCorrelationId perCorrelationId = new PerCorrelationId(); - TimingController tc = getTimingController().getControllerForCurrentThread(); - perCorrelationId._tc = tc; - perCorrelationId._expectedCount = numPings; - perCorrelationIds.put(messageCorrelationId, perCorrelationId); - - // Attach the chained message listener to the ping producer to listen asynchronously for the replies to these - // messages. - pingClient.setChainedMessageListener(batchedResultsListener); - - // Generate a sample message of the specified size. - Message msg = - pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0), - testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME), - testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME)); - - // Send the requested number of messages, and wait until they have all been received. - long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME)); - int numReplies = pingClient.pingAndWaitForReply(msg, numPings, timeout, null); - - // Check that all the replies were received and log a fail if they were not. - if (numReplies < numPings) - { - tc.completeTest(false, 0); - } - - // Remove the chained message listener from the ping producer. - pingClient.removeChainedMessageListener(); - - // Remove the expected count and timing controller for the message correlation id, to ensure they are cleaned up. - perCorrelationIds.remove(messageCorrelationId); - } - - /** Performs test fixture creation on a per thread basis. This will only be called once for each test thread. */ - public void threadSetUp() - { - _logger.debug("public void threadSetUp(): called"); - - try - { - // Call the set up method in the super class. This creates a PingClient pinger. - super.threadSetUp(); - - // Create the chained message listener, only if it has not already been created. This is set up with the - // batch size property, to tell it what batch size to output results on. A synchronized block is used to - // ensure that only one thread creates this. - synchronized (this) - { - if (batchedResultsListener == null) - { - int batchSize = Integer.parseInt(testParameters.getProperty(TEST_RESULTS_BATCH_SIZE_PROPNAME)); - batchedResultsListener = new BatchedResultsListener(batchSize); - } - } - - // Get the set up that the super class created. - PerThreadSetup perThreadSetup = threadSetup.get(); - - // Register the chained message listener on the pinger to do its asynchronous test timings from. - perThreadSetup._pingClient.setChainedMessageListener(batchedResultsListener); - } - catch (Exception e) - { - _logger.warn("There was an exception during per thread setup.", e); - } - } - - /** - * BatchedResultsListener is a {@link org.apache.qpid.requestreply.PingPongProducer.ChainedMessageListener} that can - * be attached to the pinger, in order to receive notifications about every message received and the number - * remaining to be received. Whenever the number remaining crosses a batch size boundary this results listener - * outputs a test timing for the actual number of messages received in the current batch. - */ - private class BatchedResultsListener implements PingPongProducer.ChainedMessageListener - { - /** The test results logging batch size. */ - int _batchSize; - private boolean _strictAMQP; - - /** - * Creates a results listener on the specified batch size. - * - * @param batchSize The batch size to use. - */ - public BatchedResultsListener(int batchSize) - { - _batchSize = batchSize; - _strictAMQP = - Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, - AMQSession.STRICT_AMQP_DEFAULT)); - } - - /** - * This callback method is called from all of the pingers that this test creates. It uses the correlation id - * from the message to identify the timing controller for the test thread that was responsible for sending those - * messages. - * - * @param message The message. - * @param remainingCount The count of messages remaining to be received with a particular correlation id. - * - * @throws javax.jms.JMSException Any underlying JMSException is allowed to fall through. - */ - public void onMessage(Message message, int remainingCount, long latency) throws JMSException - { - _logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount + "): called"); - - // Check if a batch boundary has been crossed. - if ((remainingCount % _batchSize) == 0) - { - // Extract the correlation id from the message. - String correlationId = message.getJMSCorrelationID(); - - // Get the details for the correlation id and check that they are not null. They can become null - // if a test times out. - PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationId); - if (perCorrelationId != null) - { - // Get the timing controller and expected count for this correlation id. - TimingController tc = perCorrelationId._tc; - int expected = perCorrelationId._expectedCount; - - // Calculate how many messages were actually received in the last batch. This will be the batch size - // except where the number expected is not a multiple of the batch size and this is the first remaining - // count to cross a batch size boundary, in which case it will be the number expected modulo the batch - // size. - int receivedInBatch = ((expected - remainingCount) < _batchSize) ? (expected % _batchSize) : _batchSize; - - // Register a test result for the correlation id. - try - { - tc.completeTest(true, receivedInBatch, latency); - } - catch (InterruptedException e) - { - // Ignore this. It means the test runner wants to stop as soon as possible. - _logger.warn("Got InterruptedException.", e); - } - } - // Else ignore, test timed out. Should log a fail here? - } - } - } - - /** - * Holds state specific to each correlation id, needed to output test results. This consists of the count of the - * total expected number of messages, and the timing controller for the thread sending those message ids. - */ - private static class PerCorrelationId - { - public int _expectedCount; - public TimingController _tc; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java deleted file mode 100644 index 2fe852af77..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.ping; - -import java.util.Properties; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.ObjectMessage; - -import org.apache.log4j.Logger; - -import org.apache.qpid.client.message.TestMessageFactory; -import org.apache.qpid.util.CommandLineParser; - -/** - *

- *
CRC Card
Responsibilities Collaborations - *
- */ -public class PingSendOnlyClient extends PingDurableClient -{ - private static final Logger log = Logger.getLogger(PingSendOnlyClient.class); - - public PingSendOnlyClient(Properties overrides) throws Exception - { - super(overrides); - } - - /** - * Starts the ping/wait/receive process. - * - * @param args The command line arguments. - */ - public static void main(String[] args) - { - try - { - // Create a ping producer overriding its defaults with all options passed on the command line. - Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties()); - PingSendOnlyClient pingProducer = new PingSendOnlyClient(options); - - // Create a shutdown hook to terminate the ping-pong producer. - Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook()); - - // Ensure that the ping pong producer is registered to listen for exceptions on the connection too. - // pingProducer.getConnection().setExceptionListener(pingProducer); - - // Run the test procedure. - pingProducer.send(); - pingProducer.waitForUser("Press return to close connection and quit."); - pingProducer.closeConnection(); - - System.exit(0); - } - catch (Exception e) - { - System.err.println(e.getMessage()); - log.error("Top level handler caught execption.", e); - System.exit(1); - } - } - - public Message getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException - { - Message msg = TestMessageFactory.newTextMessage(_producerSession, messageSize); - - // Timestamp the message in nanoseconds. - msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime()); - - return msg; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java deleted file mode 100644 index cf16abc596..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.ping; - -import junit.framework.Assert; -import junit.framework.Test; -import junit.framework.TestSuite; - -import org.apache.log4j.Logger; - -import org.apache.qpid.requestreply.PingPongProducer; - -import org.apache.qpid.junit.extensions.AsymptoticTestCase; -import org.apache.qpid.junit.extensions.TestThreadAware; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.junit.extensions.util.TestContextProperties; - -import javax.jms.*; - -/** - * PingTestPerf is a ping test, that has been written with the intention of being scaled up to run many times - * simultaneously to simluate many clients/producers/connections. - * - *

A single run of the test using the default JUnit test runner will result in the sending and timing of a single - * full round trip ping. This test may be scaled up using a suitable JUnit test runner. - * - *

The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a - * temporary queue for replies. This setup is only established once for all the test repeats/threads that may be run, - * except if the connection is lost in which case an attempt to re-establish the setup is made. - * - *

The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that - * is the name of the temporary queue, fires off a message on the original queue and waits for a response on the - * temporary queue. - * - *

Configurable test properties: message size, transacted or not, persistent or not. Broker connection details. - * - *

- *
CRC Card
Responsibilities Collaborations - *
- */ -public class PingTestPerf extends AsymptoticTestCase implements TestThreadAware -{ - private static Logger _logger = Logger.getLogger(PingTestPerf.class); - - /** Thread local to hold the per-thread test setup fields. */ - ThreadLocal threadSetup = new ThreadLocal(); - - /** Holds a property reader to extract the test parameters from. */ - protected ParsedProperties testParameters = - TestContextProperties.getInstance(PingPongProducer.defaults /*System.getProperties()*/); - - public PingTestPerf(String name) - { - super(name); - - _logger.debug("testParameters = " + testParameters); - } - - /** - * Compile all the tests into a test suite. - * @return The test method testPingOk. - */ - public static Test suite() - { - // Build a new test suite - TestSuite suite = new TestSuite("Ping Performance Tests"); - - // Run performance tests in read committed mode. - suite.addTest(new PingTestPerf("testPingOk")); - - return suite; - } - - public void testPingOk(int numPings) throws Exception - { - if (numPings == 0) - { - Assert.fail("Number of pings requested was zero."); - } - - // Get the per thread test setup to run the test through. - PerThreadSetup perThreadSetup = threadSetup.get(); - - if (perThreadSetup == null) - { - Assert.fail("Could not get per thread test setup, it was null."); - } - - // Generate a sample message. This message is already time stamped and has its reply-to destination set. - Message msg = - perThreadSetup._pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0), - testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME), - testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME)); - - // start the test - long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME)); - int numReplies = perThreadSetup._pingClient.pingAndWaitForReply(msg, numPings, timeout, null); - - // Fail the test if the timeout was exceeded. - if (numReplies != perThreadSetup._pingClient.getExpectedNumPings(numPings)) - { - Assert.fail("The ping timed out after " + timeout + " ms. Messages Sent = " + numPings + ", MessagesReceived = " - + numReplies); - } - } - - /** Performs test fixture creation on a per thread basis. This will only be called once for each test thread. */ - public void threadSetUp() - { - _logger.debug("public void threadSetUp(): called"); - - try - { - PerThreadSetup perThreadSetup = new PerThreadSetup(); - - // This is synchronized because there is a race condition, which causes one connection to sleep if - // all threads try to create connection concurrently. - synchronized (this) - { - // Establish a client to ping a Destination and listen the reply back from same Destination - perThreadSetup._pingClient = new PingClient(testParameters); - perThreadSetup._pingClient.establishConnection(true, true); - } - - // Attach the per-thread set to the thread. - threadSetup.set(perThreadSetup); - } - catch (Exception e) - { - _logger.warn("There was an exception during per thread setup.", e); - } - } - - /** - * Called after all threads have completed their setup. - */ - public void postThreadSetUp() - { - _logger.debug("public void postThreadSetUp(): called"); - - PerThreadSetup perThreadSetup = threadSetup.get(); - // Prefill the broker unless we are in consume only mode. - int preFill = testParameters.getPropertyAsInteger(PingPongProducer.PREFILL_PROPNAME); - if (!testParameters.getPropertyAsBoolean(PingPongProducer.CONSUME_ONLY_PROPNAME) && preFill > 0) - { - try - { - // Manually set the correlation ID to 1. This is not ideal but it is the - // value that the main test loop will use. - perThreadSetup._pingClient.pingNoWaitForReply(null, preFill, String.valueOf(perThreadSetup._pingClient.getClientCount())); - - // Note with a large preFill and non-tx session the messages will be - // rapidly pushed in to the mina buffers. OOM's are a real risk here. - // Should perhaps consider using a TX session for the prefill. - - long delayBeforeConsume = testParameters.getPropertyAsLong(PingPongProducer.DELAY_BEFORE_CONSUME_PROPNAME); - - // Only delay if we are - // not doing send only - // and we have consumers - // and a delayBeforeConsume - if (!(testParameters.getPropertyAsBoolean(PingPongProducer.SEND_ONLY_PROPNAME)) - && (testParameters.getPropertyAsInteger(PingPongProducer.NUM_CONSUMERS_PROPNAME) > 0) - && delayBeforeConsume > 0) - { - - boolean verbose = testParameters.getPropertyAsBoolean(PingPongProducer.VERBOSE_PROPNAME); - // Only do logging if in verbose mode. - if (verbose) - { - if (delayBeforeConsume > 60000) - { - long minutes = delayBeforeConsume / 60000; - long seconds = (delayBeforeConsume - (minutes * 60000)) / 1000; - long ms = delayBeforeConsume - (minutes * 60000) - (seconds * 1000); - _logger.info("Delaying for " + minutes + "m " + seconds + "s " + ms + "ms before starting test."); - } - else - { - _logger.info("Delaying for " + delayBeforeConsume + "ms before starting test."); - } - } - - Thread.sleep(delayBeforeConsume); - - if (verbose) - { - _logger.info("Starting Test."); - } - } - - // We can't start the client's here as the test client has not yet been configured to receieve messages. - // only when the test method is executed will the correlationID map be set up and ready to consume - // the messages we have sent here. - } - catch (Exception e) - { - _logger.warn("There was an exception during per thread setup.", e); - } - } - else //Only start the consumer if we are not preFilling. - { - // Start the consumers, unless we have data on the broker - // already this is signified by being in consume_only, we will - // start the clients after setting up the correlation IDs. - // We should also not start the clients if we are in Send only - if (!testParameters.getPropertyAsBoolean(PingPongProducer.CONSUME_ONLY_PROPNAME) && - !(testParameters.getPropertyAsBoolean(PingPongProducer.SEND_ONLY_PROPNAME))) - { - // Start the client connection - try - { - perThreadSetup._pingClient.start(); - } - catch (JMSException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - - /** - * Performs test fixture clean - */ - public void threadTearDown() - { - _logger.debug("public void threadTearDown(): called"); - - try - { - // Get the per thread test fixture. - PerThreadSetup perThreadSetup = threadSetup.get(); - - // Close the pingers so that it cleans up its connection cleanly. - synchronized (this) - { - if ((perThreadSetup != null) && (perThreadSetup._pingClient != null)) - { - perThreadSetup._pingClient.close(); - } - } - } - catch (JMSException e) - { - _logger.warn("There was an exception during per thread tear down."); - } - finally - { - // Ensure the per thread fixture is reclaimed. - threadSetup.remove(); - } - } - - protected static class PerThreadSetup - { - /** - * Holds the test ping client. - */ - protected PingClient _pingClient; - protected String _correlationId; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java deleted file mode 100644 index 8e010ccf07..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.requestreply; - -import java.io.IOException; -import java.net.InetAddress; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.jms.*; - -import org.apache.log4j.Logger; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.jms.Session; -import org.apache.qpid.topic.Config; -import org.apache.qpid.exchange.ExchangeDefaults; - -/** - * PingPongBouncer is a message listener the bounces back messages to their reply to destination. This is used to return - * ping messages generated by {@link org.apache.qpid.requestreply.PingPongProducer} but could be used for other purposes - * too. - * - *

The correlation id from the received message is extracted, and placed into the reply as the correlation id. Messages - * are bounced back to their reply-to destination. The original sender of the message has the option to use either a unique - * temporary queue or the correlation id to correlate the original message to the reply. - * - *

There is a verbose mode flag which causes information about each ping to be output to the console - * (info level logging, so usually console). This can be helpfull to check the bounce backs are happening but should - * be disabled for real timing tests as writing to the console will slow things down. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Bounce back messages to their reply to destination. - *
Provide command line invocation to start the bounce back on a configurable broker url. - *
- * - * @todo Replace the command line parsing with a neater tool. - * - * @todo Make verbose accept a number of messages, only prints to console every X messages. - */ -public class PingPongBouncer implements MessageListener -{ - private static final Logger _logger = Logger.getLogger(PingPongBouncer.class); - - /** The default prefetch size for the message consumer. */ - private static final int PREFETCH = 1; - - /** The default no local flag for the message consumer. */ - private static final boolean NO_LOCAL = true; - - private static final String DEFAULT_DESTINATION_NAME = "ping"; - - /** The default exclusive flag for the message consumer. */ - private static final boolean EXCLUSIVE = false; - - /** A convenient formatter to use when time stamping output. */ - protected static final SimpleDateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS"); - - /** Used to indicate that the reply generator should log timing info to the console (logger info level). */ - private boolean _verbose = false; - - /** Determines whether this bounce back client bounces back messages persistently. */ - private boolean _persistent = false; - - private Destination _consumerDestination; - - /** Keeps track of the response destination of the previous message for the last reply to producer cache. */ - private Destination _lastResponseDest; - - /** The producer for sending replies with. */ - private MessageProducer _replyProducer; - - /** The consumer controlSession. */ - private Session _consumerSession; - - /** The producer controlSession. */ - private Session _producerSession; - - /** Holds the connection to the broker. */ - private AMQConnection _connection; - - /** Flag used to indicate if this is a point to point or pub/sub ping client. */ - private boolean _isPubSub = false; - - /** - * This flag is used to indicate that the user should be prompted to kill a broker, in order to test - * failover, immediately before committing a transaction. - */ - protected boolean _failBeforeCommit = false; - - /** - * This flag is used to indicate that the user should be prompted to a kill a broker, in order to test - * failover, immediate after committing a transaction. - */ - protected boolean _failAfterCommit = false; - - /** - * Creates a PingPongBouncer on the specified producer and consumer sessions. - * - * @param brokerDetails The addresses of the brokers to connect to. - * @param username The broker username. - * @param password The broker password. - * @param virtualpath The virtual host name within the broker. - * @param destinationName The name of the queue to receive pings on - * (or root of the queue name where many queues are generated). - * @param persistent A flag to indicate that persistent message should be used. - * @param transacted A flag to indicate that pings should be sent within transactions. - * @param selector A message selector to filter received pings with. - * @param verbose A flag to indicate that message timings should be sent to the console. - * - * @throws Exception All underlying exceptions allowed to fall through. This is only test code... - */ - public PingPongBouncer(String brokerDetails, String username, String password, String virtualpath, - String destinationName, boolean persistent, boolean transacted, String selector, boolean verbose, - boolean pubsub) throws Exception - { - // Create a client id to uniquely identify this client. - InetAddress address = InetAddress.getLocalHost(); - String clientId = address.getHostName() + System.currentTimeMillis(); - _verbose = verbose; - _persistent = persistent; - setPubSub(pubsub); - // Connect to the broker. - setConnection(new AMQConnection(brokerDetails, username, password, clientId, virtualpath)); - _logger.info("Connected with URL:" + getConnection().toURL()); - - // Set up the failover notifier. - getConnection().setConnectionListener(new FailoverNotifier()); - - // Create a controlSession to listen for messages on and one to send replies on, transactional depending on the - // command line option. - _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE); - _producerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE); - - // Create the queue to listen for message on. - createConsumerDestination(destinationName); - MessageConsumer consumer = - _consumerSession.createConsumer(_consumerDestination, PREFETCH, NO_LOCAL, EXCLUSIVE, selector); - - // Create a producer for the replies, without a default destination. - _replyProducer = _producerSession.createProducer(null); - _replyProducer.setDisableMessageTimestamp(true); - _replyProducer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); - - // Set this up to listen for messages on the queue. - consumer.setMessageListener(this); - } - - /** - * Starts a stand alone ping-pong client running in verbose mode. - * - * @param args - */ - public static void main(String[] args) throws Exception - { - System.out.println("Starting..."); - - // Display help on the command line. - if (args.length == 0) - { - _logger.info("Running test with default values..."); - //usage(); - //System.exit(0); - } - - // Extract all command line parameters. - Config config = new Config(); - config.setOptions(args); - String brokerDetails = config.getHost() + ":" + config.getPort(); - String virtualpath = "test"; - String destinationName = config.getDestination(); - if (destinationName == null) - { - destinationName = DEFAULT_DESTINATION_NAME; - } - - String selector = config.getSelector(); - boolean transacted = config.isTransacted(); - boolean persistent = config.usePersistentMessages(); - boolean pubsub = config.isPubSub(); - boolean verbose = true; - - //String selector = null; - - // Instantiate the ping pong client with the command line options and start it running. - PingPongBouncer pingBouncer = - new PingPongBouncer(brokerDetails, "guest", "guest", virtualpath, destinationName, persistent, transacted, - selector, verbose, pubsub); - pingBouncer.getConnection().start(); - - System.out.println("Waiting..."); - } - - private static void usage() - { - System.err.println("Usage: PingPongBouncer \n" + "-host : broker host\n" + "-port : broker port\n" - + "-destinationname : queue/topic name\n" + "-transacted : (true/false). Default is false\n" - + "-persistent : (true/false). Default is false\n" - + "-pubsub : (true/false). Default is false\n" + "-selector : selector string\n"); - } - - /** - * This is a callback method that is notified of all messages for which this has been registered as a message - * listener on a message consumer. It sends a reply (pong) to all messages it receieves on the reply to - * destination of the message. - * - * @param message The message that triggered this callback. - */ - public void onMessage(Message message) - { - try - { - String messageCorrelationId = message.getJMSCorrelationID(); - if (_verbose) - { - _logger.info(timestampFormatter.format(new Date()) + ": Got ping with correlation id, " - + messageCorrelationId); - } - - // Get the reply to destination from the message and check it is set. - Destination responseDest = message.getJMSReplyTo(); - - if (responseDest == null) - { - _logger.debug("Cannot send reply because reply-to destination is null."); - - return; - } - - // Spew out some timing information if verbose mode is on. - if (_verbose) - { - Long timestamp = message.getLongProperty("timestamp"); - - if (timestamp != null) - { - long diff = System.currentTimeMillis() - timestamp; - _logger.info("Time to bounce point: " + diff); - } - } - - // Correlate the reply to the original. - message.setJMSCorrelationID(messageCorrelationId); - - // Send the receieved message as the pong reply. - _replyProducer.send(responseDest, message); - - if (_verbose) - { - _logger.info(timestampFormatter.format(new Date()) + ": Sent reply with correlation id, " - + messageCorrelationId); - } - - // Commit the transaction if running in transactional mode. - commitTx(_producerSession); - } - catch (JMSException e) - { - _logger.debug("There was a JMSException: " + e.getMessage(), e); - } - } - - /** - * Gets the underlying connection that this ping client is running on. - * - * @return The underlying connection that this ping client is running on. - */ - public AMQConnection getConnection() - { - return _connection; - } - - /** - * Sets the connection that this ping client is using. - * - * @param connection The ping connection. - */ - public void setConnection(AMQConnection connection) - { - this._connection = connection; - } - - /** - * Sets or clears the pub/sub flag to indiciate whether this client is pinging a queue or a topic. - * - * @param pubsub true if this client is pinging a topic, false if it is pinging a queue. - */ - public void setPubSub(boolean pubsub) - { - _isPubSub = pubsub; - } - - /** - * Checks whether this client is a p2p or pub/sub ping client. - * - * @return true if this client is pinging a topic, false if it is pinging a queue. - */ - public boolean isPubSub() - { - return _isPubSub; - } - - /** - * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not - * a transactional controlSession, this method does nothing. - * - *

If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the - * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker - * after the commit is applied. - * - * @throws javax.jms.JMSException If the commit fails and then the rollback fails. - */ - protected void commitTx(Session session) throws JMSException - { - if (session.getTransacted()) - { - try - { - if (_failBeforeCommit) - { - _logger.debug("Failing Before Commit"); - doFailover(); - } - - session.commit(); - - if (_failAfterCommit) - { - _logger.debug("Failing After Commit"); - doFailover(); - } - - _logger.debug("Session Commited."); - } - catch (JMSException e) - { - _logger.trace("JMSException on commit:" + e.getMessage(), e); - - try - { - session.rollback(); - _logger.debug("Message rolled back."); - } - catch (JMSException jmse) - { - _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse); - - // Both commit and rollback failed. Throw the rollback exception. - throw jmse; - } - } - } - } - - /** - * Prompts the user to terminate the named broker, in order to test failover functionality. This method will block - * until the user supplied some input on the terminal. - * - * @param broker The name of the broker to terminate. - */ - protected void doFailover(String broker) - { - System.out.println("Kill Broker " + broker + " now."); - try - { - System.in.read(); - } - catch (IOException e) - { } - - System.out.println("Continuing."); - } - - /** - * Prompts the user to terminate the broker, in order to test failover functionality. This method will block - * until the user supplied some input on the terminal. - */ - protected void doFailover() - { - System.out.println("Kill Broker now."); - try - { - System.in.read(); - } - catch (IOException e) - { } - - System.out.println("Continuing."); - - } - - private void createConsumerDestination(String name) - { - if (isPubSub()) - { - _consumerDestination = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, name); - } - else - { - _consumerDestination = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, name); - } - } - - /** - * A connection listener that logs out any failover complete events. Could do more interesting things with this - * at some point... - */ - public static class FailoverNotifier implements ConnectionListener - { - public void bytesSent(long count) - { } - - public void bytesReceived(long count) - { } - - public boolean preFailover(boolean redirect) - { - return true; - } - - public boolean preResubscribe() - { - return true; - } - - public void failoverComplete() - { - _logger.info("App got failover complete callback."); - } - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java deleted file mode 100644 index 639b0c72ba..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java +++ /dev/null @@ -1,1818 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.requestreply; - -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import org.apache.qpid.test.framework.TestUtils; - -import org.apache.qpid.junit.extensions.BatchedThrottle; -import org.apache.qpid.junit.extensions.Throttle; -import org.apache.qpid.junit.extensions.util.CommandLineParser; -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -import javax.jms.*; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; - -import java.io.*; -import java.net.InetAddress; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * PingPongProducer is a client that sends test messages, and waits for replies to these messages. The replies may - * either be generated by another client (see {@link PingPongBouncer}, or an extension of it may be used that listens - * to its own messages and does not send replies (see {@link org.apache.qpid.ping.PingClient}). The intention of ping - * pong producer is that it is a swiss-army knife test client that makes almost every aspect of its behaviour - * configurable. - * - *

The pings are sent with a reply-to field set to a single temporary queue, which is the same for all pings. This - * means that this class has to do some work to correlate pings with pongs; it expectes the original message correlation - * id in the ping to be bounced back in the reply correlation id. - * - *

This ping tool accepts a vast number of configuration options, all of which are passed in to the constructor. It - * can ping topics or queues; ping multiple destinations; do persistent pings; send messages of any size; do pings within - * transactions; control the number of pings to send in each transaction; limit its sending rate; and perform failover - * testing. A complete list of accepted parameters, default values and comments on their usage is provided here: - * - *

- *
Parameters
Parameter Default Comments - *
messageSize 0 Message size in bytes. Not including any headers. - *
destinationName ping The root name to use to generate destination names to ping. - *
persistent false Determines whether peristent delivery is used. - *
transacted false Determines whether messages are sent/received in transactions. - *
broker tcp://localhost:5672 Determines the broker to connect to. - *
virtualHost test Determines the virtual host to send all ping over. - *
rate 0 The maximum rate (in hertz) to send messages at. 0 means no limit. - *
verbose false The verbose flag for debugging. Prints to console on every message. - *
pubsub false Whether to ping topics or queues. Uses p2p by default. - *
failAfterCommit false Whether to prompt user to kill broker after a commit batch. - *
failBeforeCommit false Whether to prompt user to kill broker before a commit batch. - *
failAfterSend false Whether to prompt user to kill broker after a send. - *
failBeforeSend false Whether to prompt user to kill broker before a send. - *
failOnce true Whether to prompt for failover only once. - *
username guest The username to access the broker with. - *
password guest The password to access the broker with. - *
selector null Not used. Defines a message selector to filter pings with. - *
destinationCount 1 The number of destinations to send pings to. - *
numConsumers 1 The number of consumers on each destination. - *
timeout 30000 In milliseconds. The timeout to stop waiting for replies. - *
commitBatchSize 1 The number of messages per transaction in transactional mode. - *
uniqueDests true Whether each receivers only listens to one ping destination or all. - *
durableDests false Whether or not durable destinations are used. - *
ackMode AUTO_ACK The message acknowledgement mode. Possible values are: - * 0 - SESSION_TRANSACTED - * 1 - AUTO_ACKNOWLEDGE - * 2 - CLIENT_ACKNOWLEDGE - * 3 - DUPS_OK_ACKNOWLEDGE - * 257 - NO_ACKNOWLEDGE - * 258 - PRE_ACKNOWLEDGE - *
consTransacted false Whether or not consumers use transactions. Defaults to the same value - * as the 'transacted' option if not seperately defined. - *
consAckMode AUTO_ACK The message acknowledgement mode for consumers. Defaults to the same - * value as 'ackMode' if not seperately defined. - *
maxPending 0 The maximum size in bytes, of messages sent but not yet received. - * Limits the volume of messages currently buffered on the client - * or broker. Can help scale test clients by limiting amount of buffered - * data to avoid out of memory errors. - *
- * - *

This implements the Runnable interface with a run method that implements an infinite ping loop. The ping loop - * does all its work through helper methods, so that code wishing to run a ping-pong cycle is not forced to do so by - * starting a new thread. The command line invocation does take advantage of this ping loop. A shutdown hook is also - * registered to terminate the ping-pong loop cleanly. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a ping and wait for all responses cycle. - *
Provide command line invocation to loop the ping cycle on a configurable broker url. - *
- * - * @todo Use read/write lock in the onmessage, not for reading writing but to make use of a shared and exlcusive lock pair. - * Obtain read lock on all messages, before decrementing the message count. At the end of the on message method add a - * block that obtains the write lock for the very last message, releases any waiting producer. Means that the last - * message waits until all other messages have been handled before releasing producers but allows messages to be - * processed concurrently, unlike the current synchronized block. - */ -public class PingPongProducer implements Runnable, ExceptionListener -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(PingPongProducer.class); - - /** Holds the name of the property to determine whether of not client id is overridden at connection time. */ - public static final String OVERRIDE_CLIENT_ID_PROPNAME = "overrideClientId"; - - /** Holds the default value of the override client id flag. */ - public static final String OVERRIDE_CLIENT_ID_DEAFULT = "false"; - - /** Holds the name of the property to define the JNDI factory name with. */ - public static final String FACTORY_NAME_PROPNAME = "factoryName"; - - /** Holds the default JNDI name of the connection factory. */ - public static final String FACTORY_NAME_DEAFULT = "local"; - - /** Holds the name of the property to set the JNDI initial context properties with. */ - public static final String FILE_PROPERTIES_PROPNAME = "properties"; - - /** Holds the default file name of the JNDI initial context properties. */ - public static final String FILE_PROPERTIES_DEAFULT = "perftests.properties"; - - /** Holds the name of the property to get the test message size from. */ - public static final String MESSAGE_SIZE_PROPNAME = "messageSize"; - - /** Used to set up a default message size. */ - public static final int MESSAGE_SIZE_DEAFULT = 0; - - /** Holds the name of the property to get the ping queue name from. */ - public static final String PING_QUEUE_NAME_PROPNAME = "destinationName"; - - /** Holds the name of the default destination to send pings on. */ - public static final String PING_QUEUE_NAME_DEFAULT = "ping"; - - /** Holds the name of the property to get the queue name postfix from. */ - public static final String QUEUE_NAME_POSTFIX_PROPNAME = "queueNamePostfix"; - - /** Holds the default queue name postfix value. */ - public static final String QUEUE_NAME_POSTFIX_DEFAULT = ""; - - /** Holds the name of the property to get the test delivery mode from. */ - public static final String PERSISTENT_MODE_PROPNAME = "persistent"; - - /** Holds the message delivery mode to use for the test. */ - public static final boolean PERSISTENT_MODE_DEFAULT = false; - - /** Holds the name of the property to get the test transactional mode from. */ - public static final String TRANSACTED_PROPNAME = "transacted"; - - /** Holds the transactional mode to use for the test. */ - public static final boolean TRANSACTED_DEFAULT = false; - - /** Holds the name of the property to get the test consumer transacted mode from. */ - public static final String CONSUMER_TRANSACTED_PROPNAME = "consTransacted"; - - /** Holds the consumer transactional mode default setting. */ - public static final boolean CONSUMER_TRANSACTED_DEFAULT = false; - - /** Holds the name of the property to get the test broker url from. */ - public static final String BROKER_PROPNAME = "broker"; - - /** Holds the default broker url for the test. */ - public static final String BROKER_DEFAULT = "tcp://localhost:5672"; - - /** Holds the name of the property to get the test broker virtual path. */ - public static final String VIRTUAL_HOST_PROPNAME = "virtualHost"; - - /** Holds the default virtual path for the test. */ - public static final String VIRTUAL_HOST_DEFAULT = ""; - - /** Holds the name of the property to get the message rate from. */ - public static final String RATE_PROPNAME = "rate"; - - /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */ - public static final int RATE_DEFAULT = 0; - - /** Holds the name of the property to get the verbose mode proeprty from. */ - public static final String VERBOSE_PROPNAME = "verbose"; - - /** Holds the default verbose mode. */ - public static final boolean VERBOSE_DEFAULT = false; - - /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */ - public static final String PUBSUB_PROPNAME = "pubsub"; - - /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */ - public static final boolean PUBSUB_DEFAULT = false; - - /** Holds the name of the property to get the fail after commit flag from. */ - public static final String FAIL_AFTER_COMMIT_PROPNAME = "failAfterCommit"; - - /** Holds the default failover after commit test flag. */ - public static final boolean FAIL_AFTER_COMMIT_DEFAULT = false; - - /** Holds the name of the proeprty to get the fail before commit flag from. */ - public static final String FAIL_BEFORE_COMMIT_PROPNAME = "failBeforeCommit"; - - /** Holds the default failover before commit test flag. */ - public static final boolean FAIL_BEFORE_COMMIT_DEFAULT = false; - - /** Holds the name of the proeprty to get the fail after send flag from. */ - public static final String FAIL_AFTER_SEND_PROPNAME = "failAfterSend"; - - /** Holds the default failover after send test flag. */ - public static final boolean FAIL_AFTER_SEND_DEFAULT = false; - - /** Holds the name of the property to get the fail before send flag from. */ - public static final String FAIL_BEFORE_SEND_PROPNAME = "failBeforeSend"; - - /** Holds the default failover before send test flag. */ - public static final boolean FAIL_BEFORE_SEND_DEFAULT = false; - - /** Holds the name of the property to get the fail once flag from. */ - public static final String FAIL_ONCE_PROPNAME = "failOnce"; - - /** The default failover once flag, true means only do one failover, false means failover on every commit cycle. */ - public static final boolean FAIL_ONCE_DEFAULT = true; - - /** Holds the name of the property to get the broker access username from. */ - public static final String USERNAME_PROPNAME = "username"; - - /** Holds the default broker log on username. */ - public static final String USERNAME_DEFAULT = "guest"; - - /** Holds the name of the property to get the broker access password from. */ - public static final String PASSWORD_PROPNAME = "password"; - - /** Holds the default broker log on password. */ - public static final String PASSWORD_DEFAULT = "guest"; - - /** Holds the name of the proeprty to get the. */ - public static final String SELECTOR_PROPNAME = "selector"; - - /** Holds the default message selector. */ - public static final String SELECTOR_DEFAULT = ""; - - /** Holds the name of the property to get the destination count from. */ - public static final String DESTINATION_COUNT_PROPNAME = "destinationCount"; - - /** Defines the default number of destinations to ping. */ - public static final int DESTINATION_COUNT_DEFAULT = 1; - - /** Holds the name of the property to get the number of consumers per destination from. */ - public static final String NUM_CONSUMERS_PROPNAME = "numConsumers"; - - /** Defines the default number consumers per destination. */ - public static final int NUM_CONSUMERS_DEFAULT = 1; - - /** Holds the name of the property to get the waiting timeout for response messages. */ - public static final String TIMEOUT_PROPNAME = "timeout"; - - /** Default time to wait before assuming that a ping has timed out. */ - public static final long TIMEOUT_DEFAULT = 30000; - - /** Holds the name of the property to get the commit batch size from. */ - public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize"; - - /** Defines the default number of pings to send in each transaction when running transactionally. */ - public static final int TX_BATCH_SIZE_DEFAULT = 1; - - /** Holds the name of the property to get the unique destinations flag from. */ - public static final String UNIQUE_DESTS_PROPNAME = "uniqueDests"; - - /** Defines the default value for the unique destinations property. */ - public static final boolean UNIQUE_DESTS_DEFAULT = true; - - /** Holds the name of the property to get the durable destinations flag from. */ - public static final String DURABLE_DESTS_PROPNAME = "durableDests"; - - /** Defines the default value of the durable destinations flag. */ - public static final boolean DURABLE_DESTS_DEFAULT = false; - - /** Holds the name of the proeprty to get the message acknowledgement mode from. */ - public static final String ACK_MODE_PROPNAME = "ackMode"; - - /** Defines the default message acknowledgement mode. */ - public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE; - - /** Holds the name of the property to get the consumers message acknowledgement mode from. */ - public static final String CONSUMER_ACK_MODE_PROPNAME = "consAckMode"; - - /** Defines the default consumers message acknowledgement mode. */ - public static final int CONSUMER_ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE; - - /** Holds the name of the property to get the maximum pending message size setting from. */ - public static final String MAX_PENDING_PROPNAME = "maxPending"; - - /** Defines the default value for the maximum pending message size setting. 0 means no limit. */ - public static final int MAX_PENDING_DEFAULT = 0; - - /** Defines the default prefetch size to use when consuming messages. */ - public static final int PREFETCH_DEFAULT = 100; - - /** Defines the default value of the no local flag to use when consuming messages. */ - public static final boolean NO_LOCAL_DEFAULT = false; - - /** Defines the default value of the exclusive flag to use when consuming messages. */ - public static final boolean EXCLUSIVE_DEFAULT = false; - - /** Holds the name of the property to store nanosecond timestamps in ping messages with. */ - public static final String MESSAGE_TIMESTAMP_PROPNAME = "timestamp"; - - /** Holds the name of the property to get the number of message to prefill the broker with before starting the main test. */ - public static final String PREFILL_PROPNAME = "preFill"; - - /** Defines the default value for the number of messages to prefill. 0,default, no messages. */ - public static final int PREFILL_DEFAULT = 0; - - /** Holds the name of the property to get the delay to wait in ms before starting the main test after having prefilled. */ - public static final String DELAY_BEFORE_CONSUME_PROPNAME = "delayBeforeConsume"; - - /** Defines the default value for delay in ms to wait before starting thet test run. 0,default, no delay. */ - public static final long DELAY_BEFORE_CONSUME = 0; - - /** Holds the name of the property to get when no messasges should be sent. */ - public static final String CONSUME_ONLY_PROPNAME = "consumeOnly"; - - /** Defines the default value of the consumeOnly flag to use when publishing messages is not desired. */ - public static final boolean CONSUME_ONLY_DEFAULT = false; - - /** Holds the name of the property to get when no messasges should be sent. */ - public static final String SEND_ONLY_PROPNAME = "sendOnly"; - - /** Defines the default value of the consumeOnly flag to use when publishing messages is not desired. */ - public static final boolean SEND_ONLY_DEFAULT = false; - - /** Holds the default configuration properties. */ - public static ParsedProperties defaults = new ParsedProperties(); - - static - { - defaults.setPropertyIfNull(OVERRIDE_CLIENT_ID_PROPNAME, OVERRIDE_CLIENT_ID_DEAFULT); - defaults.setPropertyIfNull(FILE_PROPERTIES_PROPNAME, FILE_PROPERTIES_DEAFULT); - defaults.setPropertyIfNull(FACTORY_NAME_PROPNAME, FACTORY_NAME_DEAFULT); - defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT); - defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT); - defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT); - defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT); - defaults.setPropertyIfNull(PING_QUEUE_NAME_PROPNAME, PING_QUEUE_NAME_DEFAULT); - defaults.setPropertyIfNull(QUEUE_NAME_POSTFIX_PROPNAME, QUEUE_NAME_POSTFIX_DEFAULT); - defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT); - defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT); - defaults.setPropertyIfNull(CONSUMER_TRANSACTED_PROPNAME, CONSUMER_TRANSACTED_DEFAULT); - defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT); - defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT); - defaults.setPropertyIfNull(CONSUMER_ACK_MODE_PROPNAME, CONSUMER_ACK_MODE_DEFAULT); - defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT); - defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT); - defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT); - defaults.setPropertyIfNull(UNIQUE_DESTS_PROPNAME, UNIQUE_DESTS_DEFAULT); - defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT); - defaults.setPropertyIfNull(FAIL_BEFORE_COMMIT_PROPNAME, FAIL_BEFORE_COMMIT_DEFAULT); - defaults.setPropertyIfNull(FAIL_AFTER_COMMIT_PROPNAME, FAIL_AFTER_COMMIT_DEFAULT); - defaults.setPropertyIfNull(FAIL_BEFORE_SEND_PROPNAME, FAIL_BEFORE_SEND_DEFAULT); - defaults.setPropertyIfNull(FAIL_AFTER_SEND_PROPNAME, FAIL_AFTER_SEND_DEFAULT); - defaults.setPropertyIfNull(FAIL_ONCE_PROPNAME, FAIL_ONCE_DEFAULT); - defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT); - defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT); - defaults.setPropertyIfNull(NUM_CONSUMERS_PROPNAME, NUM_CONSUMERS_DEFAULT); - defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT); - defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT); - defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT); - defaults.setPropertyIfNull(PREFILL_PROPNAME, PREFILL_DEFAULT); - defaults.setPropertyIfNull(DELAY_BEFORE_CONSUME_PROPNAME, DELAY_BEFORE_CONSUME); - defaults.setPropertyIfNull(CONSUME_ONLY_PROPNAME, CONSUME_ONLY_DEFAULT); - defaults.setPropertyIfNull(SEND_ONLY_PROPNAME, SEND_ONLY_DEFAULT); - } - - /** Allows setting of client ID on the connection, rather than through the connection URL. */ - protected boolean _overrideClientId; - - /** Holds the JNDI name of the JMS connection factory. */ - protected String _factoryName; - - /** Holds the name of the properties file to configure JNDI with. */ - protected String _fileProperties; - - /** Holds the broker url. */ - protected String _brokerDetails; - - /** Holds the username to access the broker with. */ - protected String _username; - - /** Holds the password to access the broker with. */ - protected String _password; - - /** Holds the virtual host on the broker to run the tests through. */ - protected String _virtualpath; - - /** Holds the root name from which to generate test destination names. */ - protected String _destinationName; - - /** Holds the default queue name postfix value. */ - protected String _queueNamePostfix; - - /** Holds the message selector to filter the pings with. */ - protected String _selector; - - /** Holds the producers transactional mode flag. */ - protected boolean _transacted; - - /** Holds the consumers transactional mode flag. */ - protected boolean _consTransacted; - - /** Determines whether this producer sends persistent messages. */ - protected boolean _persistent; - - /** Holds the acknowledgement mode used for the producers. */ - protected int _ackMode; - - /** Holds the acknowledgement mode setting for the consumers. */ - protected int _consAckMode; - - /** Determines what size of messages this producer sends. */ - protected int _messageSize; - - /** Used to indicate that the ping loop should print out whenever it pings. */ - protected boolean _verbose; - - /** Flag used to indicate if this is a point to point or pub/sub ping client. */ - protected boolean _isPubSub; - - /** Flag used to indicate if the destinations should be unique client. */ - protected boolean _isUnique; - - /** Flag used to indicate that durable destination should be used. */ - protected boolean _isDurable; - - /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a commit. */ - protected boolean _failBeforeCommit; - - /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a commit. */ - protected boolean _failAfterCommit; - - /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a send. */ - protected boolean _failBeforeSend; - - /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a send. */ - protected boolean _failAfterSend; - - /** Flag used to indicate that failover prompting should only be done on the first commit, not on every commit. */ - protected boolean _failOnce; - - /** Holds the number of sends that should be performed in every transaction when using transactions. */ - protected int _txBatchSize; - - /** Holds the number of destinations to ping. */ - protected int _noOfDestinations; - - /** Holds the number of consumers per destination. */ - protected int _noOfConsumers; - - private int[] _consumerBatchCounts; - - /** Holds the maximum send rate in herz. */ - protected int _rate; - - /** - * Holds the size of the maximum amount of pending data that the client should buffer, sending is suspended - * if this limit is breached. - */ - protected int _maxPendingSize; - - /** - * Holds the number of messages to send during the setup phase, before the clients start consuming. - */ - private Integer _preFill; - - /** - * Holds the time in ms to wait after preFilling before starting thet test. - */ - private Long _delayBeforeConsume; - - /** - * Holds a boolean value of wither this test should just consume, i.e. skips - * sending messages, but still expects to receive the specified number. - */ - private boolean _consumeOnly; - - /** - * Holds a boolean value of wither this test should just send, i.e. skips - * consuming messages, but still creates clients just doesn't start them. - */ - private boolean _sendOnly; - - - /** A source for providing sequential unique correlation ids. These will be unique within the same JVM. */ - private static AtomicLong _correlationIdGenerator = new AtomicLong(0L); - - /** A source for providing sequential unqiue ids for instances of this class to be identifed with. */ - private static AtomicInteger _instanceIdGenerator = new AtomicInteger(0); - - /** Holds this instances unique id. */ - private int instanceId; - - /** - * Holds a map from message ids to latches on which threads wait for replies. This map is shared accross multiple - * ping producers on the same JVM. - */ - private static Map perCorrelationIds = - Collections.synchronizedMap(new HashMap()); - - /** A convenient formatter to use when time stamping output. */ - protected static final DateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS"); - - /** Holds the connection for the message producer. */ - protected Connection _connection; - - /** Holds the consumer connections. */ - protected Connection[] _consumerConnection; - - /** Holds the controlSession on which ping replies are received. */ - protected Session[] _consumerSession; - - /** Holds the producer controlSession, needed to create ping messages. */ - protected Session _producerSession; - - /** Holds the destination where the response messages will arrive. */ - protected Destination _replyDestination; - - /** Holds the set of destinations that this ping producer pings. */ - protected List _pingDestinations; - - /** Used to restrict the sending rate to a specified limit. */ - protected Throttle _rateLimiter; - - /** Holds a message listener that this message listener chains all its messages to. */ - protected ChainedMessageListener _chainedMessageListener = null; - - /** - * This id generator is used to generate ids to append to the queue name to ensure that queues can be unique when - * creating multiple ping producers in the same JVM. - */ - protected static AtomicInteger _queueJVMSequenceID = new AtomicInteger(); - - /** - * This id generator is used to generates ids that are only unique within this pinger. Creating multiple pingers - * on the same JVM using this id generator will allow them to ping on the same queues. - */ - protected AtomicInteger _queueSharedID = new AtomicInteger(); - - /** Used to tell the ping loop when to terminate, it only runs while this is true. */ - protected boolean _publish = true; - - /** Holds the message producer to send the pings through. */ - protected MessageProducer _producer; - - /** Holds the message consumer to receive the ping replies through. */ - protected MessageConsumer[] _consumer; - - /** The prompt to display when asking the user to kill the broker for failover testing. */ - private static final String KILL_BROKER_PROMPT = "Kill broker now, then press Return."; - - /** Holds the name for this test client to be identified to the broker with. */ - private String _clientID; - - /** Keeps count of the total messages sent purely for debugging purposes. */ - private static AtomicInteger numSent = new AtomicInteger(); - - /** - * Holds a monitor which is used to synchronize sender and receivers threads, where the sender has elected - * to wait until the number of unreceived message is reduced before continuing to send. This monitor is a - * fair SynchronousQueue becuase that provides fair scheduling, to ensure that all producer threads get an - * equal chance to produce messages. - */ - static final SynchronousQueue _sendPauseMonitor = new SynchronousQueue(true); - - /** Keeps a count of the number of message currently sent but not received. */ - static AtomicInteger _unreceived = new AtomicInteger(0); - - /** - * Creates a ping producer with the specified parameters, of which there are many. See the class level comments - * for details. This constructor creates a connection to the broker and creates producer and consumer sessions on - * it, to send and recieve its pings and replies on. - * - * @param overrides Properties containing any desired overrides to the defaults. - * - * @throws Exception Any exceptions are allowed to fall through. - */ - public PingPongProducer(Properties overrides) throws Exception - { - // log.debug("public PingPongProducer(Properties overrides = " + overrides + "): called"); - instanceId = _instanceIdGenerator.getAndIncrement(); - - // Create a set of parsed properties from the defaults overriden by the passed in values. - ParsedProperties properties = new ParsedProperties(defaults); - properties.putAll(overrides); - - // Extract the configuration properties to set the pinger up with. - _overrideClientId = properties.getPropertyAsBoolean(OVERRIDE_CLIENT_ID_PROPNAME); - _factoryName = properties.getProperty(FACTORY_NAME_PROPNAME); - _fileProperties = properties.getProperty(FILE_PROPERTIES_PROPNAME); - _brokerDetails = properties.getProperty(BROKER_PROPNAME); - _username = properties.getProperty(USERNAME_PROPNAME); - _password = properties.getProperty(PASSWORD_PROPNAME); - _virtualpath = properties.getProperty(VIRTUAL_HOST_PROPNAME); - _destinationName = properties.getProperty(PING_QUEUE_NAME_PROPNAME); - _queueNamePostfix = properties.getProperty(QUEUE_NAME_POSTFIX_PROPNAME); - _selector = properties.getProperty(SELECTOR_PROPNAME); - _transacted = properties.getPropertyAsBoolean(TRANSACTED_PROPNAME); - _consTransacted = properties.getPropertyAsBoolean(CONSUMER_TRANSACTED_PROPNAME); - _persistent = properties.getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME); - _messageSize = properties.getPropertyAsInteger(MESSAGE_SIZE_PROPNAME); - _verbose = properties.getPropertyAsBoolean(VERBOSE_PROPNAME); - _failAfterCommit = properties.getPropertyAsBoolean(FAIL_AFTER_COMMIT_PROPNAME); - _failBeforeCommit = properties.getPropertyAsBoolean(FAIL_BEFORE_COMMIT_PROPNAME); - _failAfterSend = properties.getPropertyAsBoolean(FAIL_AFTER_SEND_PROPNAME); - _failBeforeSend = properties.getPropertyAsBoolean(FAIL_BEFORE_SEND_PROPNAME); - _failOnce = properties.getPropertyAsBoolean(FAIL_ONCE_PROPNAME); - _txBatchSize = properties.getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME); - _noOfDestinations = properties.getPropertyAsInteger(DESTINATION_COUNT_PROPNAME); - _noOfConsumers = properties.getPropertyAsInteger(NUM_CONSUMERS_PROPNAME); - _consumerBatchCounts = new int[_noOfConsumers]; - _rate = properties.getPropertyAsInteger(RATE_PROPNAME); - _isPubSub = properties.getPropertyAsBoolean(PUBSUB_PROPNAME); - _isUnique = properties.getPropertyAsBoolean(UNIQUE_DESTS_PROPNAME); - _isDurable = properties.getPropertyAsBoolean(DURABLE_DESTS_PROPNAME); - _ackMode = _transacted ? 0 : properties.getPropertyAsInteger(ACK_MODE_PROPNAME); - _consAckMode = _consTransacted ? 0 : properties.getPropertyAsInteger(CONSUMER_ACK_MODE_PROPNAME); - _maxPendingSize = properties.getPropertyAsInteger(MAX_PENDING_PROPNAME); - _preFill = properties.getPropertyAsInteger(PREFILL_PROPNAME); - _delayBeforeConsume = properties.getPropertyAsLong(DELAY_BEFORE_CONSUME_PROPNAME); - _consumeOnly = properties.getPropertyAsBoolean(CONSUME_ONLY_PROPNAME); - _sendOnly = properties.getPropertyAsBoolean(SEND_ONLY_PROPNAME); - - // Check that one or more destinations were specified. - if (_noOfDestinations < 1) - { - throw new IllegalArgumentException("There must be at least one destination."); - } - - // Set up a throttle to control the send rate, if a rate > 0 is specified. - if (_rate > 0) - { - _rateLimiter = new BatchedThrottle(); - _rateLimiter.setRate(_rate); - } - - // Create the connection and message producers/consumers. - // establishConnection(true, true); - } - - /** - * Establishes a connection to the broker and creates message consumers and producers based on the parameters - * that this ping client was created with. - * - * @param producer Flag to indicate whether or not the producer should be set up. - * @param consumer Flag to indicate whether or not the consumers should be set up. - * - * @throws Exception Any exceptions are allowed to fall through. - */ - public void establishConnection(boolean producer, boolean consumer) throws Exception - { - // log.debug("public void establishConnection(): called"); - - // Generate a unique identifying name for this client, based on it ip address and the current time. - InetAddress address = InetAddress.getLocalHost(); - // _clientID = address.getHostName() + System.currentTimeMillis(); - _clientID = "perftest_" + instanceId; - - // Create a connection to the broker. - createConnection(_clientID); - - // Create transactional or non-transactional sessions, based on the command line arguments. - _producerSession = _connection.createSession(_transacted, _ackMode); - - _consumerSession = new Session[_noOfConsumers]; - - for (int i = 0; i < _noOfConsumers; i++) - { - _consumerSession[i] = _consumerConnection[i].createSession(_consTransacted, _consAckMode); - } - - // Create the destinations to send pings to and receive replies from. - if (_noOfConsumers > 0) - { - _replyDestination = _consumerSession[0].createTemporaryQueue(); - } - createPingDestinations(_noOfDestinations, _selector, _destinationName, _isUnique, _isDurable); - - // Create the message producer only if instructed to. - if (producer) - { - createProducer(); - } - - // Create the message consumer only if instructed to. - if (consumer) - { - createReplyConsumers(getReplyDestinations(), _selector); - } - } - - /** - * Establishes a connection to the broker, based on the configuration parameters that this ping client was - * created with. - * - * @param clientID The clients identifier. - * - * @throws JMSException Underlying exceptions allowed to fall through. - * @throws NamingException Underlying exceptions allowed to fall through. - * @throws IOException Underlying exceptions allowed to fall through. - */ - protected void createConnection(String clientID) throws JMSException, NamingException, IOException - { - // _log.debug("protected void createConnection(String clientID = " + clientID + "): called"); - - // _log.debug("Creating a connection for the message producer."); - File propsFile = new File(_fileProperties); - InputStream is = new FileInputStream(propsFile); - Properties properties = new Properties(); - properties.load(is); - - Context context = new InitialContext(properties); - ConnectionFactory factory = (ConnectionFactory) context.lookup(_factoryName); - _connection = factory.createConnection(_username, _password); - - if (_overrideClientId) - { - _connection.setClientID(clientID); - } - - // _log.debug("Creating " + _noOfConsumers + " connections for the consumers."); - - _consumerConnection = new Connection[_noOfConsumers]; - - for (int i = 0; i < _noOfConsumers; i++) - { - _consumerConnection[i] = factory.createConnection(_username, _password); - // _consumerConnection[i].setClientID(clientID); - } - } - - /** - * Starts a ping-pong loop running from the command line. The bounce back client {@link PingPongBouncer} also needs - * to be started to bounce the pings back again. - * - * @param args The command line arguments. - */ - public static void main(String[] args) - { - try - { - Properties options = - CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties()); - - // Create a ping producer overriding its defaults with all options passed on the command line. - PingPongProducer pingProducer = new PingPongProducer(options); - pingProducer.establishConnection(true, true); - - // Start the ping producers dispatch thread running. - pingProducer._connection.start(); - - // Create a shutdown hook to terminate the ping-pong producer. - Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook()); - - // Ensure that the ping pong producer is registered to listen for exceptions on the connection too. - pingProducer._connection.setExceptionListener(pingProducer); - - // Create the ping loop thread and run it until it is terminated by the shutdown hook or exception. - Thread pingThread = new Thread(pingProducer); - pingThread.run(); - pingThread.join(); - } - catch (Exception e) - { - System.err.println(e.getMessage()); - log.error("Top level handler caught execption.", e); - System.exit(1); - } - } - - /** - * Convenience method for a short pause. - * - * @param sleepTime The time in milliseconds to pause for. - */ - public static void pause(long sleepTime) - { - if (sleepTime > 0) - { - try - { - Thread.sleep(sleepTime); - } - catch (InterruptedException ie) - { } - } - } - - /** - * Gets all the reply destinations (to listen for replies on). In this case this will just be the single reply to - * destination of this pinger. - * - * @return The single reply to destination of this pinger, wrapped in a list. - */ - public List getReplyDestinations() - { - // log.debug("public List getReplyDestinations(): called"); - - List replyDestinations = new ArrayList(); - replyDestinations.add(_replyDestination); - - // log.debug("replyDestinations = " + replyDestinations); - - return replyDestinations; - } - - /** - * Creates the producer to send the pings on. This is created without a default destination. Its persistent delivery - * flag is set accoring the ping producer creation options. - * - * @throws JMSException Any JMSExceptions are allowed to fall through. - */ - public void createProducer() throws JMSException - { - // log.debug("public void createProducer(): called"); - - _producer = (MessageProducer) _producerSession.createProducer(null); - _producer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); - - // log.debug("Created producer for " + (_persistent ? "persistent" : "non-persistent") + " messages."); - } - - /** - * Creates consumers for the specified number of destinations. The destinations themselves are also created by this - * method. - * - * @param noOfDestinations The number of destinations to create consumers for. - * @param selector The message selector to filter the consumers with. - * @param rootName The root of the name, or actual name if only one is being created. - * @param unique true to make the destinations unique to this pinger, false to share the - * numbering with all pingers on the same JVM. - * @param durable If the destinations are durable topics. - * - * @throws JMSException Any JMSExceptions are allowed to fall through. - */ - public void createPingDestinations(int noOfDestinations, String selector, String rootName, boolean unique, - boolean durable) throws JMSException - { - /*log.debug("public void createPingDestinations(int noOfDestinations = " + noOfDestinations + ", String selector = " - + selector + ", String rootName = " + rootName + ", boolean unique = " + unique + ", boolean durable = " - + durable + "): called");*/ - - _pingDestinations = new ArrayList(); - - // Create the desired number of ping destinations and consumers for them. - // log.debug("Creating " + noOfDestinations + " destinations to ping."); - - for (int i = 0; i < noOfDestinations; i++) - { - Destination destination; - String id; - - // Generate an id, unique within this pinger or to the whole JVM depending on the unique flag. - if (unique) - { - // log.debug("Creating unique destinations."); - id = "_" + _queueJVMSequenceID.incrementAndGet() + "_" + _connection.getClientID(); - } - else - { - // log.debug("Creating shared destinations."); - id = "_" + _queueSharedID.incrementAndGet(); - } - - // Check if this is a pub/sub pinger, in which case create topics. - if (_isPubSub) - { - destination = _producerSession.createTopic(rootName + id); - // log.debug("Created non-durable topic " + destination); - - if (durable) - { - _producerSession.createDurableSubscriber((Topic) destination, _connection.getClientID()); - } - } - // Otherwise this is a p2p pinger, in which case create queues. - else - { - destination = _producerSession.createQueue(rootName + id + _queueNamePostfix); - // log.debug("Created queue " + destination); - } - - // Keep the destination. - _pingDestinations.add(destination); - } - } - - /** - * Creates consumers for the specified destinations and registers this pinger to listen to their messages. - * - * @param destinations The destinations to listen to. - * @param selector A selector to filter the messages with. - * - * @throws javax.jms.JMSException Any JMSExceptions are allowed to fall through. - */ - public void createReplyConsumers(Collection destinations, String selector) throws JMSException - { - /*log.debug("public void createReplyConsumers(Collection destinations = " + destinations - + ", String selector = " + selector + "): called");*/ - - log.debug("There are " + destinations.size() + " destinations."); - log.debug("Creating " + _noOfConsumers + " consumers on each destination."); - log.debug("Total number of consumers is: " + (destinations.size() * _noOfConsumers)); - - for (Destination destination : destinations) - { - _consumer = new MessageConsumer[_noOfConsumers]; - - // If we don't have consumers then ensure we have created the - // destination. - if (_noOfConsumers == 0) - { - _producerSession.createConsumer(destination, selector, - NO_LOCAL_DEFAULT).close(); - } - - for (int i = 0; i < _noOfConsumers; i++) - { - // Create a consumer for the destination and set this pinger to listen to its messages. - _consumer[i] = _consumerSession[i].createConsumer(destination, selector, NO_LOCAL_DEFAULT); - - final int consumerNo = i; - - _consumer[i].setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - onMessageWithConsumerNo(message, consumerNo); - } - }); - - log.debug("Set consumer " + i + " to listen to replies sent to destination: " + destination); - } - } - } - - /** - * Stores the received message in the replies map, then resets the boolean latch that a thread waiting for a - * correlating reply may be waiting on. This is only done if the reply has a correlation id that is expected in the - * replies map. - * - * @param message The received message. - * @param consumerNo The consumer number within this test pinger instance. - */ - public void onMessageWithConsumerNo(Message message, int consumerNo) - { - // log.debug("public void onMessageWithConsumerNo(Message message, int consumerNo = " + consumerNo + "): called"); - try - { - long now = System.nanoTime(); - long timestamp = getTimestamp(message); - long pingTime = now - timestamp; - - // NDC.push("id" + instanceId + "/cons" + consumerNo); - - // Extract the messages correlation id. - String correlationID = message.getJMSCorrelationID(); - // log.debug("correlationID = " + correlationID); - - // int num = message.getIntProperty("MSG_NUM"); - // log.info("Message " + num + " received."); - - boolean isRedelivered = message.getJMSRedelivered(); - // log.debug("isRedelivered = " + isRedelivered); - - if (!isRedelivered) - { - // Countdown on the traffic light if there is one for the matching correlation id. - PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID); - - if (perCorrelationId != null) - { - CountDownLatch trafficLight = perCorrelationId.trafficLight; - - // Restart the timeout timer on every message. - perCorrelationId.timeOutStart = System.nanoTime(); - - // log.debug("Reply was expected, decrementing the latch for the id, " + correlationID); - - // Release waiting senders if there are some and using maxPending limit. - if ((_maxPendingSize > 0)) - { - // Decrement the count of sent but not yet received messages. - int unreceived = _unreceived.decrementAndGet(); - int unreceivedSize = - (unreceived * ((_messageSize == 0) ? 1 : _messageSize)) - / (_isPubSub ? getConsumersPerDestination() : 1); - - // log.debug("unreceived = " + unreceived); - // log.debug("unreceivedSize = " + unreceivedSize); - - // synchronized (_sendPauseMonitor) - // { - if (unreceivedSize < _maxPendingSize) - { - _sendPauseMonitor.poll(); - } - // } - } - - // Decrement the countdown latch. Before this point, it is possible that two threads might enter this - // method simultanesouly with the same correlation id. Decrementing the latch in a synchronized block - // ensures that each thread will get a unique value for the remaining messages. - long trueCount; - long remainingCount; - - synchronized (trafficLight) - { - trafficLight.countDown(); - - trueCount = trafficLight.getCount(); - remainingCount = trueCount - 1; - - if (++_consumerBatchCounts[consumerNo] == _txBatchSize) - { - _consumerBatchCounts[consumerNo] = 0; - if (_consAckMode == 2) - { - // log.debug("Doing client ack for consumer " + consumerNo + "."); - message.acknowledge(); - } - else - { - // log.debug("Trying commit for consumer " + consumerNo + "."); - commitTx(_consumerSession[consumerNo]); - // log.info("Tx committed on consumer " + consumerNo); - } - } - - // Forward the message and remaining count to any interested chained message listener. - if (_chainedMessageListener != null) - { - _chainedMessageListener.onMessage(message, (int) remainingCount, pingTime); - } - - // Check if this is the last message, in which case release any waiting producers. This is done - // after the transaction has been committed and any listeners notified. - if (trueCount == 1) - { - trafficLight.countDown(); - } - } - } - else - { - log.warn(consumerNo + " Got unexpected message with correlationId: " + correlationID); - log.warn(consumerNo + " Map contains:" + perCorrelationIds.entrySet()); - } - } - else - { - log.warn("Got redelivered message, ignoring."); - } - } - catch (Exception e) - { - log.warn("There was a Exception: " + e.getMessage(), e); - } - finally - { - // log.debug("public void onMessageWithConsumerNo(Message message, int consumerNo): ending"); - // NDC.clear(); - } - } - - public void setupCorrelationID(String correlationId, int expectedCount) - { - PerCorrelationId perCorrelationId = new PerCorrelationId(); - - // Create a count down latch to count the number of replies with. This is created before the messages are - // sent so that the replies cannot be received before the count down is created. - // One is added to this, so that the last reply becomes a special case. The special case is that the - // chained message listener must be called before this sender can be unblocked, but that decrementing the - // countdown needs to be done before the chained listener can be called. - perCorrelationId.trafficLight = new CountDownLatch(expectedCount + 1); - - perCorrelationIds.put(correlationId, perCorrelationId); - } - - - /** - * Sends the specified number of ping message and then waits for all correlating replies. If the wait times out - * before a reply arrives, then a null reply is returned from this method. This method allows the caller to specify - * the correlation id. - * - * Can be augmented through a pre-fill property (PingPongProducer.PREFILL_PROPNAME) that will populate the destination - * with a set number of messages so the total pings sent and therefore expected will be PREFILL + numPings. - * - * If pre-fill is specified then the consumers will start paused to allow the prefilling to occur. - * - * @param message The message to send. If this is null, one is generated. - * @param numPings The number of ping messages to send. - * @param timeout The timeout in milliseconds. - * @param messageCorrelationId The message correlation id. If this is null, one is generated. - * - * @return The number of replies received. This may be less than the number sent if the timeout terminated the wait - * for all prematurely. If we are running in noConsumer=0 so send only mode then it will return the no msgs sent. - * - * @throws JMSException All underlying JMSExceptions are allowed to fall through. - * @throws InterruptedException When interrupted by a timeout - */ - public int pingAndWaitForReply(Message message, int numPings, long timeout, String messageCorrelationId) - throws JMSException, InterruptedException - { - return pingAndWaitForReply(message, numPings, 0, timeout, messageCorrelationId); - } - - public int pingAndWaitForReply(Message message, int numPings, int preFill, long timeout, String messageCorrelationId) - throws JMSException, InterruptedException - { - /*log.debug("public int pingAndWaitForReply(Message message, int numPings = " + numPings + ", long timeout = " - + timeout + ", String messageCorrelationId = " + messageCorrelationId + "): called");*/ - - int totalPingsRequested = numPings + preFill; - - // Generate a unique correlation id to put on the messages before sending them, if one was not specified. - if (messageCorrelationId == null) - { - messageCorrelationId = Long.toString(_correlationIdGenerator.incrementAndGet()); - - setupCorrelationID(messageCorrelationId, getExpectedNumPings(totalPingsRequested)); - } - - try - { - // NDC.push("prod"); - - PerCorrelationId perCorrelationId = perCorrelationIds.get(messageCorrelationId); - - // Set up the current time as the start time for pinging on the correlation id. This is used to determine - // timeouts. - perCorrelationId.timeOutStart = System.nanoTime(); - - // Send the specifed number of messages for this test - pingNoWaitForReply(message, numPings, messageCorrelationId); - - boolean timedOut; - boolean allMessagesReceived; - int numReplies; - - // We don't have a consumer so don't try and wait for the messages. - // this does mean that if the producerSession is !TXed then we may - // get to exit before all msgs have been received. - // - // Return the number of requested messages, this will let the test - // report a pass. - if (_noOfConsumers == 0 || _sendOnly) - { - return getExpectedNumPings(totalPingsRequested); - } - - do - { - // Block the current thread until replies to all the messages are received, or it times out. - perCorrelationId.trafficLight.await(timeout, TimeUnit.MILLISECONDS); - - // Work out how many replies were receieved. - numReplies = getExpectedNumPings(totalPingsRequested) - (int) perCorrelationId.trafficLight.getCount(); - - allMessagesReceived = numReplies == getExpectedNumPings(totalPingsRequested); - - // log.debug("numReplies = " + numReplies); - // log.debug("allMessagesReceived = " + allMessagesReceived); - - // Recheck the timeout condition. - long now = System.nanoTime(); - long lastMessageReceievedAt = perCorrelationId.timeOutStart; - timedOut = (now - lastMessageReceievedAt) > (timeout * 1000000); - - // log.debug("now = " + now); - // log.debug("lastMessageReceievedAt = " + lastMessageReceievedAt); - } - while (!timedOut && !allMessagesReceived); - - if ((numReplies < getExpectedNumPings(totalPingsRequested)) && _verbose) - { - log.info("Timed out (" + timeout + " ms) before all replies received on id, " + messageCorrelationId); - } - else if (_verbose) - { - log.info("Got all replies on id, " + messageCorrelationId); - } - - // commitTx(_consumerSession); - - // log.debug("public int pingAndWaitForReply(Message message, int numPings, long timeout): ending"); - - return numReplies; - } - // Ensure that the message countdown latch is always removed from the reply map. The reply map is long lived, - // so will be a memory leak if this is not done. - finally - { - // NDC.pop(); - perCorrelationIds.remove(messageCorrelationId); - } - } - - /** - * Sends the specified number of ping messages and does not wait for correlating replies. - * - * @param message The message to send. - * @param numPings The number of pings to send. - * @param messageCorrelationId A correlation id to place on all messages sent. - * - * @throws JMSException All underlying JMSExceptions are allowed to fall through. - */ - public void pingNoWaitForReply(Message message, int numPings, String messageCorrelationId) throws JMSException - { - /*log.debug("public void pingNoWaitForReply(Message message, int numPings = " + numPings - + ", String messageCorrelationId = " + messageCorrelationId + "): called");*/ - - // If we are runnning a consumeOnly test then don't send any messages - if (_consumeOnly) - { - return; - } - - if (message == null) - { - message = getTestMessage(getReplyDestinations().get(0), _messageSize, _persistent); - } - - message.setJMSCorrelationID(messageCorrelationId); - - // Set up a committed flag to detect uncommitted messages at the end of the send loop. This may occurr if the - // transaction batch size is not a factor of the number of pings. In which case an extra commit at the end is - // needed. - boolean committed = false; - - // Send all of the ping messages. - for (int i = 0; i < numPings; i++) - { - // Re-timestamp the message. - // message.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime()); - - // Send the message, passing in the message count. - committed = sendMessage(i, message); - - // Spew out per message timings on every message sonly in verbose mode. - /*if (_verbose) - { - log.info(timestampFormatter.format(new Date()) + ": Pinged at with correlation id, " + messageCorrelationId); - }*/ - } - - // Call commit if the send loop finished before reaching a batch size boundary so there may still be uncommitted messages. - if (!committed) - { - commitTx(_producerSession); - } - } - - /** - * Sends the sepcified message, applies rate limiting and possibly commits the current transaction. The count of - * messages sent so far must be specified and is used to round robin the ping destinations (where there are more - * than one), and to determine if the transaction batch size has been reached and the sent messages should be - * committed. - * - * @param i The count of messages sent so far in a loop of multiple calls to this send method. - * @param message The message to send. - * - * @return true if the messages were committed, false otherwise. - * - * @throws JMSException All underlyiung JMSExceptions are allowed to fall through. - */ - protected boolean sendMessage(int i, Message message) throws JMSException - { - try - { - NDC.push("id" + instanceId + "/prod"); - - // log.debug("protected boolean sendMessage(int i = " + i + ", Message message): called"); - // log.debug("_txBatchSize = " + _txBatchSize); - - // Round robin the destinations as the messages are sent. - Destination destination = _pingDestinations.get(i % _pingDestinations.size()); - - // Prompt the user to kill the broker when doing failover testing. - _failBeforeSend = waitForUserToPromptOnFailure(_failBeforeSend); - - // Get the test setup for the correlation id. - String correlationID = message.getJMSCorrelationID(); - PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID); - - // If necessary, wait until the max pending message size comes within its limit. - if (_maxPendingSize > 0) - { - synchronized (_sendPauseMonitor) - { - // Used to keep track of the number of times that send has to wait. - int numWaits = 0; - - // The maximum number of waits before the test gives up and fails. This has been chosen to correspond with - // the test timeout. - int waitLimit = (int) (TIMEOUT_DEFAULT / 10000); - - while (true) - { - // Get the size estimate of sent but not yet received messages. - int unreceived = _unreceived.get(); - int unreceivedSize = - (unreceived * ((_messageSize == 0) ? 1 : _messageSize)) - / (_isPubSub ? getConsumersPerDestination() : 1); - - // log.debug("unreceived = " + unreceived); - // log.debug("unreceivedSize = " + unreceivedSize); - // log.debug("_maxPendingSize = " + _maxPendingSize); - - if (unreceivedSize > _maxPendingSize) - { - // log.debug("unreceived size estimate over limit = " + unreceivedSize); - - // Fail the test if the send has had to wait more than the maximum allowed number of times. - if (numWaits > waitLimit) - { - String errorMessage = - "Send has had to wait for the unreceivedSize (" + unreceivedSize - + ") to come below the maxPendingSize (" + _maxPendingSize + ") more that " + waitLimit - + " times."; - log.warn(errorMessage); - throw new RuntimeException(errorMessage); - } - - // Wait on the send pause barrier for the limit to be re-established. - try - { - long start = System.nanoTime(); - // _sendPauseMonitor.wait(10000); - _sendPauseMonitor.offer(new Object(), 10000, TimeUnit.MILLISECONDS); - long end = System.nanoTime(); - - // Count the wait only if it was for > 99% of the requested wait time. - if (((float) (end - start) / (float) (10000 * 1000000L)) > 0.99) - { - numWaits++; - } - } - catch (InterruptedException e) - { - // Restore the interrupted status - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - } - else - { - break; - } - } - } - } - - // Send the message either to its round robin destination, or its default destination. - // int num = numSent.incrementAndGet(); - // message.setIntProperty("MSG_NUM", num); - setTimestamp(message); - - if (destination == null) - { - _producer.send(message); - } - else - { - _producer.send(destination, message); - } - - // Increase the unreceived size, this may actually happen after the message is received. - // The unreceived size is incremented by the number of consumers that will get a copy of the message, - // in pub/sub mode. - if (_maxPendingSize > 0) - { - int newUnreceivedCount = _unreceived.addAndGet(_isPubSub ? getConsumersPerDestination() : 1); - // log.debug("newUnreceivedCount = " + newUnreceivedCount); - } - - // Apply message rate throttling if a rate limit has been set up. - if (_rateLimiter != null) - { - _rateLimiter.throttle(); - } - - // Call commit every time the commit batch size is reached. - boolean committed = false; - - // Commit on every transaction batch size boundary. Here i + 1 is the count of actual messages sent. - if (((i + 1) % _txBatchSize) == 0) - { - // log.debug("Trying commit on producer session."); - committed = commitTx(_producerSession); - } - - return committed; - } - finally - { - NDC.clear(); - } - } - - /** - * If the specified fail flag is set, this method waits for the user to cause a failure and then indicate to the - * test that the failure has occurred, before the method returns. - * - * @param failFlag The fail flag to test. - * - * @return The new value for the fail flag. If the {@link #_failOnce} flag is set, then each fail flag is only - * used once, then reset. - */ - private boolean waitForUserToPromptOnFailure(boolean failFlag) - { - if (failFlag) - { - if (_failOnce) - { - failFlag = false; - } - - // log.debug("Failing Before Send"); - waitForUser(KILL_BROKER_PROMPT); - } - - return failFlag; - } - - /** - * Implements a single iteration of the ping loop. This sends the number of pings specified by the transaction batch - * size property, and waits for replies to all of them. Any errors cause the publish flag to be cleared, which will - * terminate the pinger. - */ - public void pingLoop() - { - try - { - // Generate a sample message and time stamp it. - Message msg = getTestMessage(_replyDestination, _messageSize, _persistent); - // setTimestamp(msg); - - // Send the message and wait for a reply. - pingAndWaitForReply(msg, TX_BATCH_SIZE_DEFAULT, TIMEOUT_DEFAULT, null); - } - catch (JMSException e) - { - _publish = false; - // log.debug("There was a JMSException: " + e.getMessage(), e); - } - catch (InterruptedException e) - { - _publish = false; - // log.debug("There was an interruption: " + e.getMessage(), e); - } - } - - /** - * Sets a chained message listener. The message listener on this pinger, chains all its messages to the one set - * here. - * - * @param messageListener The chained message listener. - */ - public void setChainedMessageListener(ChainedMessageListener messageListener) - { - _chainedMessageListener = messageListener; - } - - /** Removes any chained message listeners from this pinger. */ - public void removeChainedMessageListener() - { - _chainedMessageListener = null; - } - - /** - * Generates a test message of the specified size, with the specified reply-to destination and persistence flag. - * - * @param replyQueue The reply-to destination for the message. - * @param messageSize The desired size of the message in bytes. - * @param persistent true if the message should use persistent delivery, false otherwise. - * - * @return A freshly generated test message. - * - * @throws javax.jms.JMSException All underlying JMSException are allowed to fall through. - */ - public Message getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException - { - // return TestMessageFactory.newObjectMessage(_producerSession, replyQueue, messageSize, persistent); - return TestUtils.createTestMessageOfSize(_producerSession, messageSize); - } - - /** - * Sets the current time in nanoseconds as the timestamp on the message. - * - * @param msg The message to timestamp. - * - * @throws JMSException Any JMSExceptions are allowed to fall through. - */ - protected void setTimestamp(Message msg) throws JMSException - { - /*if (((AMQSession)_producerSession).isStrictAMQP()) - { - ((AMQMessage)msg).setTimestampProperty(new AMQShortString(MESSAGE_TIMESTAMP_PROPNAME), System.nanoTime()); - } - else - {*/ - msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime()); - // } - } - - /** - * Extracts the nanosecond timestamp from a message. - * - * @param msg The message to extract the time stamp from. - * - * @return The timestamp in nanos. - * - * @throws JMSException Any JMSExceptions are allowed to fall through. - */ - protected long getTimestamp(Message msg) throws JMSException - { - /*if (((AMQSession)_producerSession).isStrictAMQP()) - { - Long value = ((AMQMessage)msg).getTimestampProperty(new AMQShortString(MESSAGE_TIMESTAMP_PROPNAME)); - - return (value == null) ? 0L : value; - } - else - {*/ - return msg.getLongProperty(PingPongProducer.MESSAGE_TIMESTAMP_PROPNAME); - // } - } - - /** - * Stops the ping loop by clearing the publish flag. The current loop will complete when it notices that this flag - * has been cleared. - */ - public void stop() - { - _publish = false; - } - - /** - * Starts the producer and consumer connections. - * - * @throws JMSException Any JMSExceptions are allowed to fall through. - */ - public void start() throws JMSException - { - // log.debug("public void start(): called"); - - _connection.start(); - // log.debug("Producer started."); - - for (int i = 0; i < _noOfConsumers; i++) - { - _consumerConnection[i].start(); - // log.debug("Consumer " + i + " started."); - } - } - - /** Implements a ping loop that repeatedly pings until the publish flag becomes false. */ - public void run() - { - // Keep running until the publish flag is cleared. - while (_publish) - { - pingLoop(); - } - } - - /** - * Callback method, implementing ExceptionListener. This should be registered to listen for exceptions on the - * connection, this clears the publish flag which in turn will halt the ping loop. - * - * @param e The exception that triggered this callback method. - */ - public void onException(JMSException e) - { - // log.debug("public void onException(JMSException e = " + e + "): called", e); - _publish = false; - } - - /** - * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered - * with the runtime system as a shutdown hook. - * - * @return A shutdown hook for the ping loop. - */ - public Thread getShutdownHook() - { - return new Thread(new Runnable() - { - public void run() - { - stop(); - } - }); - } - - /** - * Closes all of the producer and consumer connections. - * - * @throws JMSException All JMSException are allowed to fall through. - */ - public void close() throws JMSException - { - // log.debug("public void close(): called"); - - try - { - if (_connection != null) - { - // log.debug("Before close producer connection."); - _connection.close(); - // log.debug("Closed producer connection."); - } - - for (int i = 0; i < _noOfConsumers; i++) - { - if (_consumerConnection[i] != null) - { - // log.debug("Before close consumer connection " + i + "."); - _consumerConnection[i].close(); - // log.debug("Closed consumer connection " + i + "."); - } - } - } - finally - { - _connection = null; - _producerSession = null; - _consumerSession = null; - _consumerConnection = null; - _producer = null; - _consumer = null; - _pingDestinations = null; - _replyDestination = null; - } - } - - /** - * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not a - * transactional controlSession, this method does nothing (unless the failover after send flag is set). - * - *

If the {@link #_failAfterSend} flag is set, this will prompt the user to kill the broker before the commit is - * applied. This flag applies whether the pinger is transactional or not. - * - *

If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the commit - * is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker after the - * commit is applied. These flags will only apply if using a transactional pinger. - * - * @param session The controlSession to commit - * - * @return true if the controlSession was committed, false if it was not. - * - * @throws javax.jms.JMSException If the commit fails and then the rollback fails. - * - * @todo Consider moving the fail after send logic into the send method. It is confusing to have it in this commit - * method, because commits only apply to transactional pingers, but fail after send applied to transactional and - * non-transactional alike. - */ - protected boolean commitTx(Session session) throws JMSException - { - // log.debug("protected void commitTx(Session session): called"); - - boolean committed = false; - - _failAfterSend = waitForUserToPromptOnFailure(_failAfterSend); - - if (session.getTransacted()) - { - // log.debug("Session is transacted."); - - try - { - _failBeforeCommit = waitForUserToPromptOnFailure(_failBeforeCommit); - - long start = System.nanoTime(); - session.commit(); - committed = true; - // log.debug("Time taken to commit :" + ((System.nanoTime() - start) / 1000000f) + " ms"); - - _failAfterCommit = waitForUserToPromptOnFailure(_failAfterCommit); - - // log.debug("Session Commited."); - } - catch (JMSException e) - { - // log.debug("JMSException on commit:" + e.getMessage(), e); - - try - { - session.rollback(); - // log.debug("Message rolled back."); - } - catch (JMSException jmse) - { - // log.debug("JMSE on rollback:" + jmse.getMessage(), jmse); - - // Both commit and rollback failed. Throw the rollback exception. - throw jmse; - } - } - } - - return committed; - } - - /** - * Outputs a prompt to the console and waits for the user to press return. - * - * @param prompt The prompt to display on the console. - */ - public void waitForUser(String prompt) - { - System.out.println(prompt); - - try - { - System.in.read(); - } - catch (IOException e) - { - // Ignored. - } - - System.out.println("Continuing."); - } - - /** - * Gets the number of consumers that are listening to each destination in the test. - * - * @return int The number of consumers subscribing to each topic. - */ - public int getConsumersPerDestination() - { - return _noOfConsumers; - } - - /** - * Calculates how many pings are expected to be received for the given number sent. - * - * Note : that if you have set noConsumers to 0 then this will also return 0 - * in the case of PubSub testing. This is correct as without consumers there - * will be no-one to receive the sent messages so they will be unable to respond. - * - * @param numpings The number of pings that will be sent. - * - * @return The number that should be received, for the test to pass. - */ - public int getExpectedNumPings(int numpings) - { - // Wow, I'm freaking sorry about this return here... - return ((_failAfterSend || _failBeforeCommit) ? numpings - 1: numpings) * - (_isPubSub ? getConsumersPerDestination() : 1); - } - - /** - * Defines a chained message listener interface that can be attached to this pinger. Whenever this pinger's {@link - * PingPongProducer#onMessageWithConsumerNo} method is called, the chained listener set through the {@link - * PingPongProducer#setChainedMessageListener} method is passed the message, and the remaining expected count of - * messages with that correlation id. - * - *

Provided only one pinger is producing messages with that correlation id, the chained listener will always be - * given unique message counts. It will always be called while the producer waiting for all messages to arrive is - * still blocked. - */ - public static interface ChainedMessageListener - { - /** - * Notifies interested listeners about message arrival and important test stats, the number of messages - * remaining in the test, and the messages send timestamp. - * - * @param message The newly arrived message. - * @param remainingCount The number of messages left to complete the test. - * @param latency The nanosecond latency of the message. - * - * @throws JMSException Any JMS exceptions is allowed to fall through. - */ - public void onMessage(Message message, int remainingCount, long latency) throws JMSException; - } - - /** - * Holds information on each correlation id. The countdown latch, the current timeout timer... More stuff to be - * added to this: read/write lock to make onMessage more concurrent as described in class header comment. - */ - protected static class PerCorrelationId - { - /** Holds a countdown on number of expected messages. */ - CountDownLatch trafficLight; - - /** Holds the last timestamp that the timeout was reset to. */ - Long timeOutStart; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java deleted file mode 100644 index 009254c612..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.requestreply; - -import junit.framework.Assert; -import junit.framework.Test; -import junit.framework.TestSuite; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.AsymptoticTestCase; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.junit.extensions.util.TestContextProperties; - -import javax.jms.*; - -/** - * PingPongTestPerf is a full round trip ping test, that has been written with the intention of being scaled up to run - * many times simultaneously to simluate many clients/producer/connections. A full round trip ping sends a message from - * a producer to a conumer, then the consumer replies to the message on a temporary queue. - * - *

A single run of the test using the default JUnit test runner will result in the sending and timing of the number - * of pings specified by the test size and time how long it takes for all of these to complete. This test may be scaled - * up using a suitable JUnit test runner. See {@link org.apache.qpid.junit.extensions.TKTestRunner} for more - * information on how to do this. - * - *

The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a - * temporary queue for replies. This setup is only established once for all the test repeats, but each test threads - * gets its own connection/producer/consumer, this is only re-established if the connection is lost. - * - *

The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that - * is the name of the temporary queue, fires off many messages on the original queue and waits for them all to come - * back on the temporary queue. - * - *

Configurable test properties: message size, transacted or not, persistent or not. Broker connection details. - * - *

- *
CRC Card
Responsibilities Collaborations - *
- */ -public class PingPongTestPerf extends AsymptoticTestCase -{ - private static Logger _logger = Logger.getLogger(PingPongTestPerf.class); - - /** Thread local to hold the per-thread test setup fields. */ - ThreadLocal threadSetup = new ThreadLocal(); - - // Set up a property reader to extract the test parameters from. Once ContextualProperties is available in - // the project dependencies, use it to get property overrides for configurable tests and to notify the test runner - // of the test parameters to log with the results. It also providers some basic type parsing convenience methods. - // private Properties testParameters = System.getProperties(); - private ParsedProperties testParameters = - TestContextProperties.getInstance(PingPongProducer.defaults /*System.getProperties()*/); - - public PingPongTestPerf(String name) - { - super(name); - - _logger.debug(testParameters); - - // Sets up the test parameters with defaults. - /*testParameters.setPropertyIfNull(PingPongProducer.TX_BATCH_SIZE_PROPNAME, - Integer.toString(PingPongProducer.TX_BATCH_SIZE_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.MESSAGE_SIZE_PROPNAME, - Integer.toString(PingPongProducer.MESSAGE_SIZE_DEAFULT)); - testParameters.setPropertyIfNull(PingPongProducer.PING_QUEUE_NAME_PROPNAME, - PingPongProducer.PING_QUEUE_NAME_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.PERSISTENT_MODE_PROPNAME, - Boolean.toString(PingPongProducer.PERSISTENT_MODE_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.TRANSACTED_PROPNAME, - Boolean.toString(PingPongProducer.TRANSACTED_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.BROKER_PROPNAME, PingPongProducer.BROKER_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.USERNAME_PROPNAME, PingPongProducer.USERNAME_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.PASSWORD_PROPNAME, PingPongProducer.PASSWORD_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.VIRTUAL_HOST_PROPNAME, PingPongProducer.VIRTUAL_HOST_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.VERBOSE_PROPNAME, - Boolean.toString(PingPongProducer.VERBOSE_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.RATE_PROPNAME, Integer.toString(PingPongProducer.RATE_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.PUBSUB_PROPNAME, - Boolean.toString(PingPongProducer.PUBSUB_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.TX_BATCH_SIZE_PROPNAME, - Integer.toString(PingPongProducer.TX_BATCH_SIZE_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.TIMEOUT_PROPNAME, Long.toString(PingPongProducer.TIMEOUT_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.DESTINATION_COUNT_PROPNAME, - Integer.toString(PingPongProducer.DESTINATION_COUNT_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME, - PingPongProducer.FAIL_AFTER_COMMIT_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME, - PingPongProducer.FAIL_BEFORE_COMMIT_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.FAIL_AFTER_SEND_PROPNAME, - PingPongProducer.FAIL_AFTER_SEND_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME, - PingPongProducer.FAIL_BEFORE_SEND_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.FAIL_ONCE_PROPNAME, PingPongProducer.FAIL_ONCE_DEFAULT); - testParameters.setPropertyIfNull(PingPongProducer.UNIQUE_DESTS_PROPNAME, - Boolean.toString(PingPongProducer.UNIQUE_DESTS_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.ACK_MODE_PROPNAME, - Integer.toString(PingPongProducer.ACK_MODE_DEFAULT)); - testParameters.setPropertyIfNull(PingPongProducer.PAUSE_AFTER_BATCH_PROPNAME, - PingPongProducer.PAUSE_AFTER_BATCH_DEFAULT);*/ - } - - /** - * Compile all the tests into a test suite. - */ - public static Test suite() - { - // Build a new test suite - TestSuite suite = new TestSuite("Ping-Pong Performance Tests"); - - // Run performance tests in read committed mode. - suite.addTest(new PingPongTestPerf("testPingPongOk")); - - return suite; - } - - private static void setSystemPropertyIfNull(String propName, String propValue) - { - if (System.getProperty(propName) == null) - { - System.setProperty(propName, propValue); - } - } - - public void testPingPongOk(int numPings) throws Exception - { - // Get the per thread test setup to run the test through. - PerThreadSetup perThreadSetup = threadSetup.get(); - - // Generate a sample message. This message is already time stamped and has its reply-to destination set. - Message msg = - perThreadSetup._testPingProducer.getTestMessage(perThreadSetup._testPingProducer.getReplyDestinations().get(0), - testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME), - testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME)); - - // Send the message and wait for a reply. - int numReplies = - perThreadSetup._testPingProducer.pingAndWaitForReply(msg, numPings, PingPongProducer.TIMEOUT_DEFAULT, null); - - // Fail the test if the timeout was exceeded. - if (numReplies != numPings) - { - Assert.fail("The ping timed out, got " + numReplies + " out of " + numPings); - } - } - - /** - * Performs test fixture creation on a per thread basis. This will only be called once for each test thread. - */ - public void threadSetUp() - { - try - { - PerThreadSetup perThreadSetup = new PerThreadSetup(); - - // Extract the test set up paramaeters. - String brokerDetails = testParameters.getProperty(PingPongProducer.BROKER_PROPNAME); - String username = testParameters.getProperty(PingPongProducer.USERNAME_PROPNAME); - String password = testParameters.getProperty(PingPongProducer.PASSWORD_PROPNAME); - String virtualPath = testParameters.getProperty(PingPongProducer.VIRTUAL_HOST_PROPNAME); - String destinationName = testParameters.getProperty(PingPongProducer.PING_QUEUE_NAME_PROPNAME); - boolean persistent = testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME); - boolean transacted = testParameters.getPropertyAsBoolean(PingPongProducer.TRANSACTED_PROPNAME); - String selector = testParameters.getProperty(PingPongProducer.SELECTOR_PROPNAME); - boolean verbose = testParameters.getPropertyAsBoolean(PingPongProducer.VERBOSE_PROPNAME); - boolean pubsub = testParameters.getPropertyAsBoolean(PingPongProducer.PUBSUB_PROPNAME); - - synchronized (this) - { - // Establish a bounce back client on the ping queue to bounce back the pings. - perThreadSetup._testPingBouncer = - new PingPongBouncer(brokerDetails, username, password, virtualPath, destinationName, persistent, - transacted, selector, verbose, pubsub); - - // Start the connections for client and producer running. - perThreadSetup._testPingBouncer.getConnection().start(); - - // Establish a ping-pong client on the ping queue to send the pings and receive replies with. - perThreadSetup._testPingProducer = new PingPongProducer(testParameters); - perThreadSetup._testPingProducer.establishConnection(true, true); - perThreadSetup._testPingProducer.start(); - } - - // Attach the per-thread set to the thread. - threadSetup.set(perThreadSetup); - } - catch (Exception e) - { - _logger.warn("There was an exception during per thread setup.", e); - } - } - - /** - * Performs test fixture clean - */ - public void threadTearDown() - { - _logger.debug("public void threadTearDown(): called"); - - try - { - // Get the per thread test fixture. - PerThreadSetup perThreadSetup = threadSetup.get(); - - // Close the pingers so that it cleans up its connection cleanly. - synchronized (this) - { - perThreadSetup._testPingProducer.close(); - // perThreadSetup._testPingBouncer.close(); - } - - // Ensure the per thread fixture is reclaimed. - threadSetup.remove(); - } - catch (JMSException e) - { - _logger.warn("There was an exception during per thread tear down."); - } - } - - protected static class PerThreadSetup - { - /** - * Holds the test ping-pong producer. - */ - private PingPongProducer _testPingProducer; - - /** - * Holds the test ping client. - */ - private PingPongBouncer _testPingBouncer; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/topic/Config.java b/java/perftests/src/main/java/org/apache/qpid/topic/Config.java deleted file mode 100644 index d5c0979399..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/topic/Config.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.topic; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.config.ConnectorConfig; -import org.apache.qpid.config.Connector; -import org.apache.qpid.config.AbstractConfig; - -import javax.jms.Connection; - -public class Config extends AbstractConfig implements ConnectorConfig -{ - - private String host = "localhost"; - private int port = 5672; - private String factory = null; - - private int payload = 256; - private int messages = 1000; - private int clients = 1; - private int batch = 1; - private long delay = 1; - private int warmup; - private int ackMode= AMQSession.NO_ACKNOWLEDGE; - private String clientId; - private String subscriptionId; - private String selector; - private String destinationName; - private boolean persistent; - private boolean transacted; - private int destinationsCount; - private int batchSize; - private int rate; - private boolean ispubsub; - private long timeout; - - public Config() - { - } - - public int getAckMode() - { - return ackMode; - } - - public void setPayload(int payload) - { - this.payload = payload; - } - - public int getPayload() - { - return payload; - } - - void setClients(int clients) - { - this.clients = clients; - } - - int getClients() - { - return clients; - } - - void setMessages(int messages) - { - this.messages = messages; - } - - public int getMessages() - { - return messages; - } - - public int getBatchSize() - { - return batchSize; - } - - public int getRate() - { - return rate; - } - - public int getDestinationsCount() - { - return destinationsCount; - } - - public String getHost() - { - return host; - } - - public void setHost(String host) - { - this.host = host; - } - - public int getPort() - { - return port; - } - - public String getFactory() - { - return factory; - } - - public void setPort(int port) - { - this.port = port; - } - - int getBatch() - { - return batch; - } - - void setBatch(int batch) - { - this.batch = batch; - } - - int getWarmup() - { - return warmup; - } - - void setWarmup(int warmup) - { - this.warmup = warmup; - } - - public long getDelay() - { - return delay; - } - - public void setDelay(long delay) - { - this.delay = delay; - } - - public long getTimeout() - { - return timeout; - } - - public void setTimeout(long time) - { - this.timeout = time; - } - - public String getClientId() - { - return clientId; - } - - public String getSubscriptionId() - { - return subscriptionId; - } - - public String getSelector() - { - return selector; - } - - public String getDestination() - { - return destinationName; - } - - public boolean usePersistentMessages() - { - return persistent; - } - - public boolean isTransacted() - { - return transacted; - } - - public boolean isPubSub() - { - return ispubsub; - } - - public void setOption(String key, String value) - { - if("-host".equalsIgnoreCase(key)) - { - setHost(value); - } - else if("-port".equalsIgnoreCase(key)) - { - try - { - setPort(Integer.parseInt(value)); - } - catch(NumberFormatException e) - { - throw new RuntimeException("Bad port number: " + value, e); - } - } - else if("-payload".equalsIgnoreCase(key)) - { - setPayload(parseInt("Bad payload size", value)); - } - else if("-messages".equalsIgnoreCase(key)) - { - setMessages(parseInt("Bad message count", value)); - } - else if("-clients".equalsIgnoreCase(key)) - { - setClients(parseInt("Bad client count", value)); - } - else if("-batch".equalsIgnoreCase(key)) - { - setBatch(parseInt("Bad batch count", value)); - } - else if("-delay".equalsIgnoreCase(key)) - { - setDelay(parseLong("Bad batch delay", value)); - } - else if("-warmup".equalsIgnoreCase(key)) - { - setWarmup(parseInt("Bad warmup count", value)); - } - else if("-ack".equalsIgnoreCase(key)) - { - ackMode = parseInt("Bad ack mode", value); - } - else if("-factory".equalsIgnoreCase(key)) - { - factory = value; - } - else if("-clientId".equalsIgnoreCase(key)) - { - clientId = value; - } - else if("-subscriptionId".equalsIgnoreCase(key)) - { - subscriptionId = value; - } - else if("-persistent".equalsIgnoreCase(key)) - { - persistent = "true".equalsIgnoreCase(value); - } - else if("-transacted".equalsIgnoreCase(key)) - { - transacted = "true".equalsIgnoreCase(value); - } - else if ("-destinationscount".equalsIgnoreCase(key)) - { - destinationsCount = parseInt("Bad destinations count", value); - } - else if ("-batchsize".equalsIgnoreCase(key)) - { - batchSize = parseInt("Bad batch size", value); - } - else if ("-rate".equalsIgnoreCase(key)) - { - rate = parseInt("MEssage rate", value); - } - else if("-pubsub".equalsIgnoreCase(key)) - { - ispubsub = "true".equalsIgnoreCase(value); - } - else if("-selector".equalsIgnoreCase(key)) - { - selector = value; - } - else if("-destinationname".equalsIgnoreCase(key)) - { - destinationName = value; - } - else if("-timeout".equalsIgnoreCase(key)) - { - setTimeout(parseLong("Bad timeout data", value)); - } - else - { - System.out.println("Ignoring unrecognised option: " + key); - } - } - - static String getAckModeDescription(int ackMode) - { - switch(ackMode) - { - case AMQSession.NO_ACKNOWLEDGE: return "NO_ACKNOWLEDGE"; - case AMQSession.AUTO_ACKNOWLEDGE: return "AUTO_ACKNOWLEDGE"; - case AMQSession.CLIENT_ACKNOWLEDGE: return "CLIENT_ACKNOWLEDGE"; - case AMQSession.DUPS_OK_ACKNOWLEDGE: return "DUPS_OK_ACKNOWELDGE"; - case AMQSession.PRE_ACKNOWLEDGE: return "PRE_ACKNOWLEDGE"; - } - return "AckMode=" + ackMode; - } - - public Connection createConnection() throws Exception - { - return new Connector().createConnection(this); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/topic/Listener.java b/java/perftests/src/main/java/org/apache/qpid/topic/Listener.java deleted file mode 100644 index 6dcea42bfe..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/topic/Listener.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.topic; - -import java.util.Random; - -import javax.jms.*; - -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.exchange.ExchangeDefaults; - -/** - * This class has not kept up to date with the topic_listener in the cpp tests. It should provide identical behaviour for - * cross testing the java and cpp clients. - * - *

How the cpp topic_publisher operates: - * It publishes text messages to the default topic exchange, on virtual host "/test", on the topic "topic_control", for - * the specified number of test messages to be sent. - * It publishes a report request message (on same topic), with the header text field "TYPE", value "REPORT_REQUEST", - * optionally within a transaction, and waits for the specified number of consumers to reply to this request. The - * listeners should reply to this message on a queue named "response", on virtual host "/test", with some sort of message - * about the number of messages received and how long it took, although the publisher never looks at the message content. - * The publisher then send a message (on the same topic), with the header text field "TYPE", value "TERMINATION_REQUEST", - * which the listener should close its connection and terminate upon receipt of. - * - * @todo I've added lots of field table types in the report message, just to check if the other end can decode them - * correctly. Not really the right place to test this, so remove them from - * {@link #createReportResponseMessage(String)} once a better test exists. - */ -public class Listener implements MessageListener -{ - private static Logger log = Logger.getLogger(Listener.class); - - public static final String CONTROL_TOPIC = "topic_control"; - public static final String RESPONSE_QUEUE = "response"; - - private final Topic _topic; - //private final Topic _control; - - private final Queue _response; - - /** Holds the connection to listen on. */ - private final Connection _connection; - - /** Holds the producer to send control messages on. */ - private final MessageProducer _controller; - - /** Holds the JMS session. */ - private final javax.jms.Session _session; - - /** Holds a flag to indicate that a timer has begun on the first message. Reset when report is sent. */ - private boolean init; - - /** Holds the count of messages received by this listener. */ - private int count; - - /** Used to hold the start time of the first message. */ - private long start; - private static String clientId; - - Listener(Connection connection, int ackMode, String name) throws Exception - { - log.debug("Listener(Connection connection = " + connection + ", int ackMode = " + ackMode + ", String name = " + name - + "): called"); - - _connection = connection; - _session = connection.createSession(false, ackMode); - - if (_session instanceof AMQSession) - { - _topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, CONTROL_TOPIC); - //_control = new AMQTopic(CONTROL_TOPIC); - _response = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, RESPONSE_QUEUE); - } - else - { - _topic = _session.createTopic(CONTROL_TOPIC); - //_control = _session.createTopic(CONTROL_TOPIC); - _response = _session.createQueue(RESPONSE_QUEUE); - } - - //register for events - if (name == null) - { - log.debug("Calling _factory.createTopicConsumer().setMessageListener(this)"); - createTopicConsumer().setMessageListener(this); - } - else - { - log.debug("Calling createDurableTopicConsumer(name).setMessageListener(this)"); - createDurableTopicConsumer(name).setMessageListener(this); - } - - _connection.start(); - - _controller = createControlPublisher(); - System.out.println("Waiting for messages " + Config.getAckModeDescription(ackMode) - + - ((name == null) - ? "" : (" (subscribed with name " + name + " and client id " + connection.getClientID() + ")")) - + "..."); - } - - public static void main(String[] argv) throws Exception - { - clientId = "Listener-" + System.currentTimeMillis(); - - NDC.push(clientId); - - Config config = new Config(); - config.setOptions(argv); - - //Connection con = config.createConnection(); - Connection con = - new AMQConnection("amqp://guest:guest@testid/test?brokerlist='" + config.getHost() + ":" + config.getPort() - + "'"); - - if (config.getClientId() != null) - { - con.setClientID(config.getClientId()); - } - - new Listener(con, config.getAckMode(), config.getSubscriptionId()); - - NDC.pop(); - NDC.remove(); - } - - /** - * Checks whether or not a text field on a message has the specified value. - * - * @param m The message to check. - * @param fieldName The name of the field to check. - * @param value The expected value of the field to compare with. - * - * @return trueIf the specified field has the specified value, fals otherwise. - * - * @throws JMSException Any JMSExceptions are allowed to fall through. - */ - private static boolean checkTextField(Message m, String fieldName, String value) throws JMSException - { - log.debug("private static boolean checkTextField(Message m = " + m + ", String fieldName = " + fieldName - + ", String value = " + value + "): called"); - - String comp = m.getStringProperty(fieldName); - log.debug("comp = " + comp); - - boolean result = (comp != null) && comp.equals(value); - log.debug("result = " + result); - - return result; - } - - public void onMessage(Message message) - { - NDC.push(clientId); - - log.debug("public void onMessage(Message message = " + message + "): called"); - - if (!init) - { - start = System.nanoTime() / 1000000; - count = 0; - init = true; - } - - try - { - if (isShutdown(message)) - { - log.debug("Got a shutdown message."); - shutdown(); - } - else if (isReport(message)) - { - log.debug("Got a report request message."); - - // Send the report. - report(); - init = false; - } - } - catch (JMSException e) - { - log.warn("There was a JMSException during onMessage.", e); - } - finally - { - NDC.pop(); - } - } - - Message createReportResponseMessage(String msg) throws JMSException - { - Message message = _session.createTextMessage(msg); - - // Shove some more field table type in the message just to see if the other end can handle it. - message.setBooleanProperty("BOOLEAN", true); - message.setByteProperty("BYTE", (byte) 5); - message.setDoubleProperty("DOUBLE", Math.PI); - message.setFloatProperty("FLOAT", 1.0f); - message.setIntProperty("INT", 1); - message.setShortProperty("SHORT", (short) 1); - message.setLongProperty("LONG", (long) 1827361278); - message.setStringProperty("STRING", "hello"); - - return message; - } - - boolean isShutdown(Message m) throws JMSException - { - boolean result = checkTextField(m, "TYPE", "TERMINATION_REQUEST"); - - //log.debug("isShutdown = " + result); - - return result; - } - - boolean isReport(Message m) throws JMSException - { - boolean result = checkTextField(m, "TYPE", "REPORT_REQUEST"); - - //log.debug("isReport = " + result); - - return result; - } - - MessageConsumer createTopicConsumer() throws Exception - { - return _session.createConsumer(_topic); - } - - MessageConsumer createDurableTopicConsumer(String name) throws Exception - { - return _session.createDurableSubscriber(_topic, name); - } - - MessageProducer createControlPublisher() throws Exception - { - return _session.createProducer(_response); - } - - private void shutdown() - { - try - { - _session.close(); - _connection.stop(); - _connection.close(); - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - } - - private void report() - { - log.debug("private void report(): called"); - - try - { - String msg = getReport(); - _controller.send(createReportResponseMessage(msg)); - log.debug("Sent report: " + msg); - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - } - - private String getReport() - { - long time = ((System.nanoTime() / 1000000) - start); - - return "Received " + count + " in " + time + "ms"; - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/topic/MessageFactory.java b/java/perftests/src/main/java/org/apache/qpid/topic/MessageFactory.java deleted file mode 100644 index 4efdc1cb56..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/topic/MessageFactory.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.topic; - -import javax.jms.*; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.exchange.ExchangeDefaults; - -/** - */ -class MessageFactory -{ - private static final char[] DATA = "abcdefghijklmnopqrstuvwxyz".toCharArray(); - - private final Session _session; - private final Topic _topic; - private final Topic _control; - private final byte[] _payload; - - MessageFactory(Session session) throws JMSException - { - this(session, 256); - } - - MessageFactory(Session session, int size) throws JMSException - { - _session = session; - if (session instanceof AMQSession) - { - _topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, "topic_control"); - _control = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, "topictest.control"); - } - else - { - _topic = session.createTopic("topic_control"); - _control = session.createTopic("topictest.control"); - } - - _payload = new byte[size]; - - for (int i = 0; i < size; i++) - { - _payload[i] = (byte) DATA[i % DATA.length]; - } - } - - private static boolean checkText(Message m, String s) - { - try - { - return (m instanceof TextMessage) && ((TextMessage) m).getText().equals(s); - } - catch (JMSException e) - { - e.printStackTrace(System.out); - - return false; - } - } - - Topic getTopic() - { - return _topic; - } - - Message createEventMessage() throws JMSException - { - BytesMessage msg = _session.createBytesMessage(); - msg.writeBytes(_payload); - - return msg; - } - - Message createShutdownMessage() throws JMSException - { - return _session.createTextMessage("SHUTDOWN"); - } - - Message createReportRequestMessage() throws JMSException - { - return _session.createTextMessage("REPORT"); - } - - Message createReportResponseMessage(String msg) throws JMSException - { - return _session.createTextMessage(msg); - } - - boolean isShutdown(Message m) - { - return checkText(m, "SHUTDOWN"); - } - - boolean isReport(Message m) - { - return checkText(m, "REPORT"); - } - - Object getReport(Message m) - { - try - { - return ((TextMessage) m).getText(); - } - catch (JMSException e) - { - e.printStackTrace(System.out); - - return e.toString(); - } - } - - MessageConsumer createTopicConsumer() throws Exception - { - return _session.createConsumer(_topic); - } - - MessageConsumer createDurableTopicConsumer(String name) throws Exception - { - return _session.createDurableSubscriber(_topic, name); - } - - MessageConsumer createControlConsumer() throws Exception - { - return _session.createConsumer(_control); - } - - MessageProducer createTopicPublisher() throws Exception - { - return _session.createProducer(_topic); - } - - MessageProducer createControlPublisher() throws Exception - { - return _session.createProducer(_control); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/topic/Publisher.java b/java/perftests/src/main/java/org/apache/qpid/topic/Publisher.java deleted file mode 100644 index c3b19b558a..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/topic/Publisher.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.topic; - -import javax.jms.*; - -public class Publisher implements MessageListener -{ - private final Object _lock = new Object(); - private final Connection _connection; - private final Session _session; - private final MessageFactory _factory; - private final MessageProducer _publisher; - private int _count; - - Publisher(Connection connection, int size, int ackMode, boolean persistent) throws Exception - { - _connection = connection; - _session = _connection.createSession(false, ackMode); - _factory = new MessageFactory(_session, size); - _publisher = _factory.createTopicPublisher(); - _publisher.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); - System.out.println("Publishing " + (persistent ? "persistent" : "non-persistent") + " messages of " + size + " bytes, " + Config.getAckModeDescription(ackMode) + "."); - } - - private void test(Config config) throws Exception - { - test(config.getBatch(), config.getDelay(), config.getMessages(), config.getClients(), config.getWarmup()); - } - - private void test(int batches, long delay, int msgCount, int consumerCount, int warmup) throws Exception - { - _factory.createControlConsumer().setMessageListener(this); - _connection.start(); - - if (warmup > 0) - { - System.out.println("Runing warmup (" + warmup + " msgs)"); - long time = batch(warmup, consumerCount); - System.out.println("Warmup completed in " + time + "ms"); - } - - long[] times = new long[batches]; - for (int i = 0; i < batches; i++) - { - if (i > 0) - { - Thread.sleep(delay * 1000); - } - times[i] = batch(msgCount, consumerCount); - System.out.println("Batch " + (i + 1) + " of " + batches + " completed in " + times[i] + " ms."); - } - - long min = min(times); - long max = max(times); - System.out.println("min: " + min + ", max: " + max + " avg: " + avg(times, min, max)); - - //request shutdown - _publisher.send(_factory.createShutdownMessage()); - - _connection.stop(); - _connection.close(); - } - - private long batch(int msgCount, int consumerCount) throws Exception - { - _count = consumerCount; - long start = System.currentTimeMillis(); - publish(msgCount); - waitForCompletion(consumerCount); - return System.currentTimeMillis() - start; - } - - private void publish(int count) throws Exception - { - - //send events - for (int i = 0; i < count; i++) - { - _publisher.send(_factory.createEventMessage()); - if ((i + 1) % 100 == 0) - { - System.out.println("Sent " + (i + 1) + " messages"); - } - } - - //request report - _publisher.send(_factory.createReportRequestMessage()); - } - - private void waitForCompletion(int consumers) throws Exception - { - System.out.println("Waiting for completion..."); - synchronized (_lock) - { - while (_count > 0) - { - _lock.wait(); - } - } - } - - - public void onMessage(Message message) - { - System.out.println("Received report " + _factory.getReport(message) + " " + --_count + " remaining"); - if (_count == 0) - { - synchronized (_lock) - { - _lock.notify(); - } - } - } - - static long min(long[] times) - { - long min = times.length > 0 ? times[0] : 0; - for (int i = 0; i < times.length; i++) - { - min = Math.min(min, times[i]); - } - return min; - } - - static long max(long[] times) - { - long max = times.length > 0 ? times[0] : 0; - for (int i = 0; i < times.length; i++) - { - max = Math.max(max, times[i]); - } - return max; - } - - static long avg(long[] times, long min, long max) - { - long sum = 0; - for (int i = 0; i < times.length; i++) - { - sum += times[i]; - } - - int adjustment = 0; - - // Remove min and max if we have run enough batches. - if (times.length > 2) - { - sum -= min; - sum -= max; - adjustment = 2; - } - - return (sum / (times.length - adjustment)); - } - - public static void main(String[] argv) throws Exception - { - Config config = new Config(); - config.setOptions(argv); - - Connection con = config.createConnection(); - int size = config.getPayload(); - int ackMode = config.getAckMode(); - boolean persistent = config.usePersistentMessages(); - new Publisher(con, size, ackMode, persistent).test(config); - } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/topic/TopicWithSelectorsTransientVolumeTest.java b/java/perftests/src/main/java/org/apache/qpid/topic/TopicWithSelectorsTransientVolumeTest.java deleted file mode 100644 index 1d6ec07bb0..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/topic/TopicWithSelectorsTransientVolumeTest.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.topic; - -import java.util.ArrayList; -import java.util.HashMap; - -import javax.jms.BytesMessage; -import javax.jms.DeliveryMode; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; -import javax.jms.Topic; -import javax.jms.TopicConnection; -import javax.jms.TopicPublisher; -import javax.jms.TopicSession; -import javax.jms.TopicSubscriber; -import javax.naming.NamingException; - -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -public class TopicWithSelectorsTransientVolumeTest extends QpidBrokerTestCase -{ - private static final int NUM_MSG_PER_ITERATION = 50;//must be a multiple of 10 - private static final int NUM_ITERATIONS = 1000; - - private static final int NUM_CONSUMERS = 50; - private static final int MSG_SIZE = 1024; - private static final byte[] BYTE_ARRAY = new byte[MSG_SIZE]; - - private ArrayList _subscribers = new ArrayList(); - private HashMap _queueMsgCounts = new HashMap(); - - private final static Object _lock=new Object(); - private boolean _producerFailed; - private static int _finishedCount; - private static int _failedCount; - - protected void setUp() throws Exception - { - super.setUp(); - init(); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } - - private void init() - { - _finishedCount = 0; - _failedCount = 0; - _producerFailed = false; - _subscribers.clear(); - _queueMsgCounts.clear(); - } - - - private Message createMessage(Session session) throws JMSException - { - BytesMessage message = session.createBytesMessage(); - message.writeBytes(BYTE_ARRAY); - - return message; - } - - /** - * 1 Topic with 50 subscribers using a selector, and 1 producer sending 50,000 1K messages with 90% selector success ratio. - */ - public void test50SubscribersWith90PercentMatched() throws Exception - { - Topic topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, "test50ConsumersWith10PercentUnmatched"); - - System.out.println("Creating consumers"); - - MyMessageSubscriber sub; - - for(int i=1; i <= NUM_CONSUMERS; i++) - { - sub = new MyMessageSubscriber(topic, "consumer" + i, ((9 * NUM_MSG_PER_ITERATION * NUM_ITERATIONS) / 10)); - _subscribers.add(sub); - } - - System.out.println("Starting consumers"); - for(MyMessageSubscriber s: _subscribers) - { - Thread consumer = new Thread(s); - consumer.start(); - } - - System.out.println("Creating producer"); - MyMessageProducer prod = new MyMessageProducer(topic); - - long startTime = System.currentTimeMillis(); - - System.out.println("Starting producer"); - Thread producer = new Thread(prod); - producer.start(); - - - // Wait for all the messageConsumers to have finished or failed - synchronized (_lock) - { - while (_finishedCount + _failedCount < NUM_CONSUMERS) - { - try - { - _lock.wait(); - } - catch (InterruptedException e) - { - //ignore - } - } - } - - long endTime = System.currentTimeMillis(); - System.out.println("Elapsed time for messaging: " + (endTime-startTime) + "ms"); - - assertFalse("Producer failed to send all messages", _producerFailed); - - //check if all messages received by consumers, or if there were failures - if (_finishedCount != NUM_CONSUMERS) - { - fail(_failedCount + " consumers did not recieve all their expected messages"); - } - - //check if all queue depths were 0 - for(String consumer: _queueMsgCounts.keySet()) - { - long depth = _queueMsgCounts.get(consumer); - assertEquals(consumer + " subscription queue msg count was not 0", 0, depth); - } - - } - - private class MyMessageProducer implements Runnable - { - private TopicConnection _connection; - private TopicSession _session; - private TopicPublisher _messagePublisher; - - public MyMessageProducer(Topic topic) throws JMSException, NamingException - { - _connection = (TopicConnection) getConnection(); - _session = (TopicSession) _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _messagePublisher = _session.createPublisher(topic); - } - - public void run() - { - try - { - for(int iter = 0; iter < NUM_ITERATIONS; iter++) - { - int i = 0; - - //send 90% matching messages - for (; i < (9 * NUM_MSG_PER_ITERATION)/10; i++) - { - Message message = createMessage(_session); - message.setStringProperty("testprop", "true"); - - _messagePublisher.publish(message, DeliveryMode.NON_PERSISTENT, - Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); - - Thread.yield(); - } - - //send remaining 10% non-matching messages - for (; i < NUM_MSG_PER_ITERATION; i++) - { - Message message = _session.createMessage(); - message.setStringProperty("testprop", "false"); - - _messagePublisher.publish(message, DeliveryMode.NON_PERSISTENT, - Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); - - Thread.yield(); - } - } - - } - catch (Exception exp) - { - System.out.println("producer: caught an exception, probably exiting before all messages sent"); - exp.printStackTrace(); - synchronized (_lock) - { - _producerFailed=true; - _lock.notifyAll(); - } - } - } - } - - - private class MyMessageSubscriber implements Runnable - { - /* The topic this subscriber is subscribing to */ - private Topic _topic; - private String _consumerName; - private int _outstandingMsgCount; - private TopicConnection _connection; - private TopicSession _session; - private TopicSubscriber _durSub; - - public MyMessageSubscriber(Topic topic, String consumerName, int messageCount) throws JMSException, NamingException - { - _outstandingMsgCount = messageCount; - _topic=topic; - _consumerName = consumerName; - _connection = (TopicConnection) getConnection(); - _session = (TopicSession) _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _durSub = _session.createDurableSubscriber(_topic, _consumerName,"testprop='true'", false); - _connection.start(); - } - - public void run() - { - - boolean failed = false; - do - { - Message m = null; - try - { - m = _durSub.receive(10000); - } - catch (JMSException exp) - { - System.out.println(_consumerName + ": caught an exception handling a received message"); - exp.printStackTrace(); - - failed = true; - break; - } - - Thread.yield(); - - _outstandingMsgCount--; - - if(_outstandingMsgCount % 500 == 0) - { - System.out.println(_consumerName + ": outstanding message count: " + _outstandingMsgCount); - } - - if(m == null) - { - if(_outstandingMsgCount != 0) - { - failed = true; - } - break; - } - } - while(_outstandingMsgCount > 0); - - System.out.println(_consumerName + ": outstanding message count: " + _outstandingMsgCount); - - try - { - AMQQueue subcriptionQueue = new AMQQueue(ExchangeDefaults.TOPIC_EXCHANGE_NAME,"clientid" + ":" + _consumerName); - - ((AMQSession)_session).sync(); - Long depth = ((AMQSession)_session).getQueueDepth(subcriptionQueue); - _queueMsgCounts.put(_consumerName, depth); - - System.out.println(_consumerName + ": completion queue msg count: " + depth); - } - catch (AMQException exp) - { - System.out.println(_consumerName + ": caught an exception determining completion queue depth"); - exp.printStackTrace(); - } - finally - { - try - { - _session.unsubscribe(_consumerName); - } - catch (JMSException e) - { - System.out.println(_consumerName + ": caught an exception whilst unsubscribing"); - e.printStackTrace(); - } - } - - synchronized (_lock) - { - if (_outstandingMsgCount == 0 && !failed) - { - _finishedCount++; - System.out.println(_consumerName + ": finished"); - } - else - { - _failedCount++; - System.out.println(_consumerName + ": failed"); - } - _lock.notifyAll(); - } - - } - } - - //helper method to allow easily running against an external standalone broker -// public static void main(String[] args) throws Exception -// { -// System.setProperty("broker.config", "/dev/null"); -// System.setProperty("broker", "external"); -// System.setProperty("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"); -// System.setProperty("java.naming.provider.url", "test-profiles/test-provider.properties"); -// -// TopicWithSelectorsTransientVolumeTest test = new TopicWithSelectorsTransientVolumeTest(); -// test.init(); -// test.test50SubscribersWith90PercentMatched(); -// test.tearDown(); -// } -} diff --git a/java/perftests/src/main/java/org/apache/qpid/topic/topicselectors.properties b/java/perftests/src/main/java/org/apache/qpid/topic/topicselectors.properties deleted file mode 100644 index 1f572af58a..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/topic/topicselectors.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory - - -# register some connection factories -# connectionfactory.[jndiname] = [ConnectionURL] -connectionfactory.default = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672' \ No newline at end of file diff --git a/java/perftests/src/main/resources/perftests.properties b/java/perftests/src/main/resources/perftests.properties new file mode 100644 index 0000000000..d8823f9dc5 --- /dev/null +++ b/java/perftests/src/main/resources/perftests.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory + +connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672' diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/ArgumentParserTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/ArgumentParserTest.java new file mode 100644 index 0000000000..3be82627fe --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/ArgumentParserTest.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class ArgumentParserTest extends QpidTestCase +{ + private static final String TEST_CONFIG_FILENAME = "ControllerRunnerTest-test-config-filename.json"; + private static final String JNDI_CONFIG_FILENAME = "ControllerRunnerTest-jndi-config-filename.properties"; + private static final String DISTRIBUTED_MODE = "true"; + + public static final String TEST_CONFIG_PROP = "test-config"; + public static final String JNDI_CONFIG_PROP = "jndi-config"; + public static final String DISTRIBUTED_PROP = "distributed"; + + public static final String TEST_CONFIG_DEFAULT = "perftests-config.json"; + public static final String JNDI_CONFIG_DEFAULT = "perftests-jndi.properties"; + public static final String DISTRIBUTED_DEFAULT = "false"; + + private Map _options = new HashMap(); + + private ArgumentParser _parser; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _parser = new ArgumentParser(); + + _options.clear(); + _options.put(TEST_CONFIG_PROP, TEST_CONFIG_DEFAULT); + _options.put(JNDI_CONFIG_PROP, JNDI_CONFIG_DEFAULT); + _options.put(DISTRIBUTED_PROP, DISTRIBUTED_DEFAULT); + } + + public void testInvalidArguments() + { + String[] args = new String[]{"nonExistentConfigProperty" + "=" + TEST_CONFIG_FILENAME}; + + try + { + _parser.parseArgumentsIntoConfig(_options, args); + fail("expected exception to be thrown due to provision of a non existent config property"); + } + catch(IllegalArgumentException e) + { + //expected + } + } + + public void testDefaultConfigValues() + { + String[] args = new String[0]; + + _parser.parseArgumentsIntoConfig(_options, args); + + assertEquals("unexpected config value", TEST_CONFIG_DEFAULT, _options.get(TEST_CONFIG_PROP)); + assertEquals("unexpected config value", JNDI_CONFIG_DEFAULT, _options.get(JNDI_CONFIG_PROP)); + assertEquals("unexpected config value", DISTRIBUTED_DEFAULT, _options.get(DISTRIBUTED_PROP)); + } + + public void testConfigurationParsingOverridesDefault() throws Exception + { + String[] args = new String[]{TEST_CONFIG_PROP + "=" + TEST_CONFIG_FILENAME, + JNDI_CONFIG_PROP + "=" + JNDI_CONFIG_FILENAME, + DISTRIBUTED_PROP + "=" + DISTRIBUTED_MODE}; + + _parser.parseArgumentsIntoConfig(_options, args); + + assertEquals("unexpected config value", TEST_CONFIG_FILENAME, _options.get(TEST_CONFIG_PROP)); + assertEquals("unexpected config value", JNDI_CONFIG_FILENAME, _options.get(JNDI_CONFIG_PROP)); + assertEquals("unexpected config value", DISTRIBUTED_MODE, _options.get(DISTRIBUTED_PROP)); + assertFalse("override value was the same as the default", DISTRIBUTED_MODE.equalsIgnoreCase(_options.get(DISTRIBUTED_DEFAULT))); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java new file mode 100644 index 0000000000..12ba3b56ad --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +import org.apache.qpid.disttest.controller.config.Config; +import org.apache.qpid.disttest.controller.config.ConfigReader; + +public class ConfigFileHelper +{ + public static Reader getConfigFileReader(Class testClass, String resourceName) + { + InputStream inputStream = testClass.getResourceAsStream(resourceName); + if(inputStream == null) + { + throw new RuntimeException("Can't find resource " + resourceName + " using classloader of class " + testClass); + } + Reader reader = new InputStreamReader(inputStream); + return reader; + } + + public static Config getConfigFromResource(Class testClass, String resourceName) + { + ConfigReader configReader = new ConfigReader(); + Config config = configReader.readConfig(getConfigFileReader(testClass, resourceName)); + return config; + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java new file mode 100644 index 0000000000..320e7d8c9d --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.Command; + + +public class VisitorTest extends TestCase +{ + + public void testStringVisited() throws Exception + { + Object argument = new String(); + + TestVisitor visitor = new TestVisitor(); + visitor.visit(argument); + + assertSame(argument, visitor._string); + } + + public void testCommandVisited() throws Exception + { + Object argument = new TestCommand(); + + TestVisitor visitor = new TestVisitor(); + visitor.visit(argument); + + assertSame(argument, visitor._testCommand); + } + + public void testNoVisitIntegerImplementatiom() throws Exception + { + Integer argument = Integer.valueOf(1); + + TestVisitor visitor = new TestVisitor(); + + try + { + visitor.visit(argument); + fail("Exception not thrown"); + } + catch (DistributedTestException e) + { + assertNotNull(e.getCause()); + assertEquals(NoSuchMethodException.class, e.getCause().getClass()); + } + } + + class TestVisitor extends Visitor + { + String _string = null; + TestCommand _testCommand = null; + + public void visit(String string) + { + _string = string; + } + + public void visit(TestCommand command) + { + _testCommand = command; + } + } + + class TestCommand extends Command + { + + public TestCommand() + { + super(null); + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java new file mode 100644 index 0000000000..4a82f6719f --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import junit.framework.TestCase; + +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.disttest.message.StartTestCommand; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.apache.qpid.disttest.message.TearDownTestCommand; + +public class ClientCommandVisitorTest extends TestCase +{ + private Client _client; + private ClientCommandVisitor _visitor; + private ClientJmsDelegate _delegate; + + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _client = mock(Client.class); + _delegate = mock(ClientJmsDelegate.class); + _visitor = new ClientCommandVisitor(_client, _delegate); + } + + public void testStopClient() + { + StopClientCommand command = new StopClientCommand(); + _visitor.visit(command); + verify(_client).stop(); + } + + public void testCreateConnection() throws Exception + { + final CreateConnectionCommand command = new CreateConnectionCommand(); + _visitor.visit(command); + verify(_delegate).createConnection(command); + } + + public void testCreateSession() throws Exception + { + final CreateSessionCommand command = new CreateSessionCommand(); + _visitor.visit(command); + verify(_delegate).createSession(command); + } + + public void testCreateProducer() throws Exception + { + final CreateProducerCommand command = new CreateProducerCommand(); + _visitor.visit(command); + verify(_delegate).createProducer(command); + } + + public void testCreateConsumer() throws Exception + { + final CreateConsumerCommand command = new CreateConsumerCommand(); + _visitor.visit(command); + verify(_delegate).createConsumer(command); + } + + public void testStartTest() throws Exception + { + final StartTestCommand command = new StartTestCommand(); + _visitor.visit(command); + verify(_client).startTest(); + } + + public void testStopTest() throws Exception + { + final TearDownTestCommand stopCommand = new TearDownTestCommand(); + _visitor.visit(stopCommand); + verify(_client).tearDownTest(); + } + + public void testCreateMessageProvider() throws Exception + { + final CreateMessageProviderCommand command = new CreateMessageProviderCommand(); + command.setProviderName("test"); + _visitor.visit(command); + verify(_delegate).createMessageProvider(command); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java new file mode 100644 index 0000000000..198baa6ef4 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.Timer; +import java.util.TimerTask; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.mockito.InOrder; +import org.mockito.Mockito; + +public class ClientTest extends TestCase +{ + private Client _client; + private ClientJmsDelegate _delegate; + private ClientCommandVisitor _visitor; + private ParticipantExecutor _participant; + private ParticipantExecutorRegistry _participantRegistry; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _delegate = mock(ClientJmsDelegate.class); + _visitor = mock(ClientCommandVisitor.class); + _client = new Client(_delegate); + _client.setClientCommandVisitor(_visitor); + _participant = mock(ParticipantExecutor.class); + when(_participant.getParticipantName()).thenReturn("testParticipantMock"); + + _participantRegistry = mock(ParticipantExecutorRegistry.class); + when(_participantRegistry.executors()).thenReturn(Collections.singletonList(_participant)); + _client.setParticipantRegistry(_participantRegistry); + } + + public void testInitialState() throws Exception + { + assertEquals("Expected client to be in CREATED state", ClientState.CREATED, _client.getState()); + } + + public void testStart() throws Exception + { + _client.start(); + final InOrder inOrder = inOrder(_delegate); + inOrder.verify(_delegate).setInstructionListener(_client); + inOrder.verify(_delegate).sendRegistrationMessage(); + assertEquals("Expected client to be in STARTED state", ClientState.READY, _client.getState()); + } + + public void testStopClient() throws Exception + { + _client.stop(); + + assertEquals("Expected client to be in STOPPED state", ClientState.STOPPED, _client.getState()); + } + + public void testProcessInstructionVisitsCommandAndResponds() throws Exception + { + // has to be declared to be of supertype Command otherwise Mockito verify() + // refers to wrong method + final Command command = new StopClientCommand(); + _client.processInstruction(command); + + verify(_visitor).visit(command); + verify(_delegate).sendResponseMessage(isA(Response.class)); + } + + public void testWaitUntilStopped() throws Exception + { + stopClientLater(500); + _client.waitUntilStopped(1000); + verify(_delegate).destroy(); + } + + public void testStartTest() throws Exception + { + _client.start(); + _client.addParticipantExecutor(_participant); + + verify(_participantRegistry).add(_participant); + + _client.startTest(); + + InOrder inOrder = Mockito.inOrder(_delegate, _participant); + inOrder.verify(_delegate).startConnections(); + inOrder.verify(_participant).start(_client); + } + + public void testTearDownTest() throws Exception + { + // before we can tear down the test the client needs to be in the "running test" state, which requires a participant + _client.start(); + _client.addParticipantExecutor(_participant); + _client.startTest(); + + _client.tearDownTest(); + + verify(_delegate).closeTestConnections(); + + verify(_participantRegistry).clear(); + } + + public void testResults() throws Exception + { + ParticipantResult testResult = mock(ParticipantResult.class); + _client.sendResults(testResult); + verify(_delegate).sendResponseMessage(testResult); + } + + private void stopClientLater(long delay) + { + doLater(new TimerTask() + { + @Override + public void run() + { + _client.stop(); + } + + }, delay); + } + + private void doLater(TimerTask task, long delayInMillis) + { + Timer timer = new Timer(); + timer.schedule(task, delayInMillis); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java new file mode 100644 index 0000000000..ff7cfd2b41 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import static org.apache.qpid.disttest.client.ParticipantTestHelper.assertExpectedConsumerResults; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import javax.jms.Message; +import javax.jms.Session; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.mockito.InOrder; + +public class ConsumerParticipantTest extends TestCase +{ + private static final String SESSION_NAME1 = "SESSION1"; + private static final String PARTICIPANT_NAME1 = "PARTICIPANT_NAME1"; + private static final long RECEIVE_TIMEOUT = 100; + private static final String CLIENT_NAME = "CLIENT_NAME"; + private static final int PAYLOAD_SIZE_PER_MESSAGE = 1024; + + private final Message _mockMessage = mock(Message.class); + private final CreateConsumerCommand _command = new CreateConsumerCommand(); + private ClientJmsDelegate _delegate; + private ConsumerParticipant _consumerParticipant; + private InOrder _inOrder; + + /** used to check start/end time of results */ + private long _testStartTime; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _delegate = mock(ClientJmsDelegate.class); + _inOrder = inOrder(_delegate); + + _command.setSessionName(SESSION_NAME1); + _command.setParticipantName(PARTICIPANT_NAME1); + _command.setSynchronous(true); + _command.setReceiveTimeout(RECEIVE_TIMEOUT); + + _consumerParticipant = new ConsumerParticipant(_delegate, _command); + + when(_delegate.consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT)).thenReturn(_mockMessage); + when(_delegate.calculatePayloadSizeFrom(_mockMessage)).thenReturn(PAYLOAD_SIZE_PER_MESSAGE); + when(_delegate.getAcknowledgeMode(SESSION_NAME1)).thenReturn(Session.CLIENT_ACKNOWLEDGE); + + _testStartTime = System.currentTimeMillis(); + } + + public void testNoMessagesToReceive() throws Exception + { + _command.setNumberOfMessages(0); + _command.setMaximumDuration(0); + + try + { + _consumerParticipant.doIt(CLIENT_NAME); + fail("Exception not thrown"); + } + catch(DistributedTestException e) + { + // PASS + assertEquals("number of messages and duration cannot both be zero", e.getMessage()); + + } + + verify(_delegate, never()).consumeMessage(anyString(), anyLong()); + } + + public void testReceiveOneMessageSynch() throws Exception + { + int numberOfMessages = 1; + long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages; + _command.setNumberOfMessages(numberOfMessages); + + ParticipantResult result = _consumerParticipant.doIt(CLIENT_NAME); + + assertExpectedConsumerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.CLIENT_ACKNOWLEDGE, null, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null); + + _inOrder.verify(_delegate).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); + _inOrder.verify(_delegate).calculatePayloadSizeFrom(_mockMessage); + _inOrder.verify(_delegate).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testReceiveMessagesForDurationSynch() throws Exception + { + long duration = 100; + _command.setMaximumDuration(duration); + + ParticipantResult result = _consumerParticipant.doIt(CLIENT_NAME); + + assertExpectedConsumerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.CLIENT_ACKNOWLEDGE, null, null, PAYLOAD_SIZE_PER_MESSAGE, null, duration); + + verify(_delegate, atLeastOnce()).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); + verify(_delegate, atLeastOnce()).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, atLeastOnce()).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testReceiveMessagesBatchedSynch() throws Exception + { + int numberOfMessages = 10; + final int batchSize = 3; + long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages; + _command.setNumberOfMessages(numberOfMessages); + _command.setBatchSize(batchSize); + + ParticipantResult result = _consumerParticipant.doIt(CLIENT_NAME); + + assertExpectedConsumerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.CLIENT_ACKNOWLEDGE, batchSize, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null); + + verify(_delegate, times(numberOfMessages)).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); + verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, times(4)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testReceiveMessagesWithVaryingPayloadSize() throws Exception + { + int numberOfMessages = 3; + + int firstPayloadSize = PAYLOAD_SIZE_PER_MESSAGE; + int secondPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * 2; + int thirdPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * 4; + + _command.setNumberOfMessages(numberOfMessages); + + when(_delegate.calculatePayloadSizeFrom(_mockMessage)).thenReturn(firstPayloadSize, secondPayloadSize, thirdPayloadSize); + + ParticipantResult result = _consumerParticipant.doIt(CLIENT_NAME); + + final int expectedPayloadResultPayloadSize = 0; + final long totalPayloadSize = firstPayloadSize + secondPayloadSize + thirdPayloadSize; + assertExpectedConsumerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.CLIENT_ACKNOWLEDGE, null, numberOfMessages, expectedPayloadResultPayloadSize, totalPayloadSize, null); + + verify(_delegate, times(numberOfMessages)).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); + verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, times(numberOfMessages)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testReleaseResources() + { + _consumerParticipant.releaseResources(); + verify(_delegate).closeTestConsumer(PARTICIPANT_NAME1); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java new file mode 100644 index 0000000000..ffc3733eb7 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jms.Message; +import javax.jms.Session; +import javax.jms.TextMessage; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.client.property.ListPropertyValue; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.client.property.SimplePropertyValue; +import org.apache.qpid.disttest.message.CreateProducerCommand; + +public class MessageProviderTest extends TestCase +{ + private Session _session; + private TextMessage _message; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _session = mock(Session.class); + _message = mock(TextMessage.class); + when(_session.createTextMessage(isA(String.class))).thenReturn(_message); + when(_session.createTextMessage()).thenReturn(_message); + } + + public void testGetMessagePayload() throws Exception + { + MessageProvider messageProvider = new MessageProvider(null) + { + public String getMessagePayload(CreateProducerCommand command) + { + return super.getMessagePayload(command); + } + }; + CreateProducerCommand command = new CreateProducerCommand(); + command.setMessageSize(100); + String payloadValue = messageProvider.getMessagePayload(command); + assertNotNull("Mesage payload should not be null", payloadValue); + assertEquals("Unexpected payload size", 100, payloadValue.length()); + } + + public void testNextMessage() throws Exception + { + MessageProvider messageProvider = new MessageProvider(null); + CreateProducerCommand command = new CreateProducerCommand(); + command.setMessageSize(100); + Message message = messageProvider.nextMessage(_session, command); + assertNotNull("Mesage should be returned", message); + verify(_message, atLeastOnce()).setText(isA(String.class)); + } + + public void testNextMessageWithProperties() throws Exception + { + Map properties = new HashMap(); + properties.put("test1", new SimplePropertyValue("testValue1")); + properties.put("test2", new SimplePropertyValue(new Integer(1))); + properties.put("priority", new SimplePropertyValue(new Integer(2))); + List listItems = new ArrayList(); + listItems.add(new SimplePropertyValue(new Double(2.0))); + ListPropertyValue list = new ListPropertyValue(); + list.setItems(listItems); + properties.put("test3", list); + + MessageProvider messageProvider = new MessageProvider(properties); + CreateProducerCommand command = new CreateProducerCommand(); + command.setMessageSize(100); + Message message = messageProvider.nextMessage(_session, command); + assertNotNull("Mesage should be returned", message); + verify(_message, atLeastOnce()).setText(isA(String.class)); + verify(_message, atLeastOnce()).setJMSPriority(2); + verify(_message, atLeastOnce()).setStringProperty("test1", "testValue1"); + verify(_message, atLeastOnce()).setIntProperty("test2", 1); + verify(_message, atLeastOnce()).setDoubleProperty("test3", 2.0); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java new file mode 100644 index 0000000000..f30e4664ff --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.qpid.disttest.client; + +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.mockito.ArgumentMatcher; +import org.mockito.InOrder; + +public class ParticipantExecutorTest extends TestCase +{ + private static final ResultHasError HAS_ERROR = new ResultHasError(); + private static final String CLIENT_NAME = "CLIENT_NAME"; + private static final String PARTICIPANT_NAME = "PARTICIPANT_NAME"; + private ParticipantExecutor _participantExecutor = null; + private Client _client = null; + private Participant _participant = null; + private ParticipantResult _mockResult; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _client = mock(Client.class); + when(_client.getClientName()).thenReturn(CLIENT_NAME); + _participant = mock(Participant.class); + + _participantExecutor = new ParticipantExecutor(_participant); + _participantExecutor.setExecutor(new SynchronousExecutor()); + + _mockResult = mock(ParticipantResult.class); + } + + public void testStart() throws Exception + { + when(_participant.doIt(CLIENT_NAME)).thenReturn(_mockResult); + + _participantExecutor.start(_client); + + InOrder inOrder = inOrder(_participant, _client); + + inOrder.verify(_participant).doIt(CLIENT_NAME); + inOrder.verify(_client).sendResults(_mockResult); + inOrder.verify(_participant).releaseResources(); + } + + public void testParticipantThrowsException() throws Exception + { + when(_participant.doIt(CLIENT_NAME)).thenThrow(DistributedTestException.class); + + _participantExecutor.start(_client); + + InOrder inOrder = inOrder(_participant, _client); + + inOrder.verify(_participant).doIt(CLIENT_NAME); + inOrder.verify(_client).sendResults(argThat(HAS_ERROR)); + inOrder.verify(_participant).releaseResources(); + } + + public void testThreadNameAndDaemonness() throws Exception + { + + ThreadPropertyReportingParticipant participant = new ThreadPropertyReportingParticipant(PARTICIPANT_NAME); + _participantExecutor = new ParticipantExecutor(participant); + + _participantExecutor.start(_client); + participant.awaitExecution(); + + assertTrue("Participant should be run in a thread named after it", participant.threadWasCalled().endsWith(PARTICIPANT_NAME)); + assertTrue("Executor should use daemon threads to avoid them preventing JVM termination", participant.wasDaemon()); + } + + private static final class ThreadPropertyReportingParticipant implements Participant + { + private final String _participantName; + private final CountDownLatch _participantExecuted = new CountDownLatch(1); + private String _threadName; + private boolean _daemon; + + public ThreadPropertyReportingParticipant(String participantName) + { + _participantName = participantName; + } + + public String threadWasCalled() + { + return _threadName; + } + + public boolean wasDaemon() + { + return _daemon; + } + + @Override + public void releaseResources() + { + } + + @Override + public String getName() + { + return _participantName; + } + + @Override + public ParticipantResult doIt(String registeredClientName) throws Exception + { + Thread currentThread = Thread.currentThread(); + _threadName = currentThread.getName(); + _daemon = currentThread.isDaemon(); + + _participantExecuted.countDown(); + + return null; // unused + } + + public void awaitExecution() + { + boolean success = false; + try + { + success = _participantExecuted.await(5, TimeUnit.SECONDS); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + } + + assertTrue("Participant not executed", success); + } + } + + /** avoids our unit test needing to use multiple threads */ + private final class SynchronousExecutor implements Executor + { + @Override + public void execute(Runnable command) + { + command.run(); + } + } + + private static class ResultHasError extends ArgumentMatcher + { + @Override + public boolean matches(Object argument) + { + ParticipantResult result = (ParticipantResult) argument; + return result.hasError(); + } + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java new file mode 100644 index 0000000000..bd0d5a39c8 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.client; + +import static org.mockito.Mockito.mock; +import junit.framework.TestCase; + +public class ParticipantRegistryTest extends TestCase +{ + private ParticipantExecutorRegistry _participantRegistry = new ParticipantExecutorRegistry(); + + private ParticipantExecutor _testParticipant1 = mock(ParticipantExecutor.class); + private ParticipantExecutor _testParticipant2 = mock(ParticipantExecutor.class); + + public void testAdd() + { + assertTrue(_participantRegistry.executors().isEmpty()); + + _participantRegistry.add(_testParticipant1); + + assertTrue(_participantRegistry.executors().contains(_testParticipant1)); + + _participantRegistry.add(_testParticipant2); + + assertTrue(_participantRegistry.executors().contains(_testParticipant2)); + } + + public void testClear() + { + _participantRegistry.add(_testParticipant1); + + assertEquals(1, _participantRegistry.executors().size()); + + _participantRegistry.clear(); + + assertTrue(_participantRegistry.executors().isEmpty()); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java new file mode 100644 index 0000000000..3b21834a5c --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import java.util.Date; + +import javax.jms.DeliveryMode; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateParticpantCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; + +public class ParticipantResultFactoryTest extends TestCase +{ + private static final String PARTICIPANT_NAME = "participantName"; + private static final String REGISTERED_CLIENT_NAME = "registeredClientName"; + + private static final int BATCH_SIZE = 10; + private static final long MAXIMUM_DURATION = 500; + private static final int NUMBER_OF_MESSAGES_PROCESSED = 100; + private static final long TIME_TAKEN = 100; + private static final long TOTAL_PAYLOAD_PROCESSED = 200; + private static final int PAYLOAD_SIZE = 300; + + private static final Date START = new Date(0); + private static final Date END = new Date(START.getTime() + TIME_TAKEN); + + private ParticipantResultFactory _participantResultFactory; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _participantResultFactory = new ParticipantResultFactory(); + } + + public void testCreateForProducer() + { + CreateProducerCommand command = new CreateProducerCommand(); + setCommonCommandFields(command); + + long producerStartDelay = 30; + command.setStartDelay(producerStartDelay); + + int deliveryMode = DeliveryMode.PERSISTENT; + command.setDeliveryMode(deliveryMode); + + int priority = 5; + command.setPriority(priority); + + long producerInterval = 50; + command.setInterval(producerInterval); + + long timeToLive = 60; + command.setTimeToLive(timeToLive); + + int totalNumberOfConsumers = 0; + int totalNumberOfProducers = 1; + + int acknowledgeMode = 1; + + ProducerParticipantResult result = _participantResultFactory.createForProducer(PARTICIPANT_NAME, + REGISTERED_CLIENT_NAME, + command, + acknowledgeMode, + NUMBER_OF_MESSAGES_PROCESSED, + PAYLOAD_SIZE, + TOTAL_PAYLOAD_PROCESSED, + START, END); + + assertCommonResultProperties(result); + + assertEquals(deliveryMode, result.getDeliveryMode()); + assertEquals(acknowledgeMode, result.getAcknowledgeMode()); + assertEquals(priority, result.getPriority()); + assertEquals(producerInterval, result.getInterval()); + assertEquals(producerStartDelay, result.getStartDelay()); + assertEquals(timeToLive, result.getTimeToLive()); + assertEquals(totalNumberOfConsumers, result.getTotalNumberOfConsumers()); + assertEquals(totalNumberOfProducers, result.getTotalNumberOfProducers()); + } + + public void testCreateForConsumer() + { + CreateConsumerCommand command = new CreateConsumerCommand(); + setCommonCommandFields(command); + + boolean topic = true; + command.setTopic(topic); + + boolean durable = true; + command.setDurableSubscription(durable); + + boolean browsingSubscription = false; + command.setBrowsingSubscription(browsingSubscription); + + String selector = "selector"; + boolean isSelector = true; + command.setSelector(selector); + + boolean noLocal = false; + command.setNoLocal(noLocal); + + boolean synchronousConsumer = true; + command.setSynchronous(synchronousConsumer); + + int totalNumberOfConsumers = 1; + int totalNumberOfProducers = 0; + + int acknowledgeMode = 2; + + ConsumerParticipantResult result = _participantResultFactory.createForConsumer(PARTICIPANT_NAME, + REGISTERED_CLIENT_NAME, + command, + acknowledgeMode, + NUMBER_OF_MESSAGES_PROCESSED, + PAYLOAD_SIZE, + TOTAL_PAYLOAD_PROCESSED, + START, END); + + assertCommonResultProperties(result); + + assertEquals(topic, result.isTopic()); + assertEquals(durable, result.isDurableSubscription()); + assertEquals(browsingSubscription, result.isBrowsingSubscription()); + assertEquals(isSelector, result.isSelector()); + assertEquals(noLocal, result.isNoLocal()); + assertEquals(synchronousConsumer, result.isSynchronousConsumer()); + assertEquals(totalNumberOfConsumers, result.getTotalNumberOfConsumers()); + assertEquals(totalNumberOfProducers, result.getTotalNumberOfProducers()); + } + + public void testCreateForError() + { + String errorMessage = "error"; + ParticipantResult result = _participantResultFactory.createForError(PARTICIPANT_NAME, REGISTERED_CLIENT_NAME, errorMessage); + assertEquals(PARTICIPANT_NAME, result.getParticipantName()); + assertEquals(REGISTERED_CLIENT_NAME, result.getRegisteredClientName()); + } + + + private void setCommonCommandFields(CreateParticpantCommand command) + { + command.setBatchSize(BATCH_SIZE); + command.setMaximumDuration(MAXIMUM_DURATION); + } + + + private void assertCommonResultProperties(ParticipantResult result) + { + assertEquals(PARTICIPANT_NAME, result.getParticipantName()); + assertEquals(REGISTERED_CLIENT_NAME, result.getRegisteredClientName()); + assertEquals(BATCH_SIZE, result.getBatchSize()); + assertEquals(MAXIMUM_DURATION, result.getMaximumDuration()); + assertEquals(TIME_TAKEN, result.getTimeTaken()); + assertEquals(NUMBER_OF_MESSAGES_PROCESSED, result.getNumberOfMessagesProcessed()); + assertEquals(TOTAL_PAYLOAD_PROCESSED, result.getTotalPayloadProcessed()); + assertEquals(PAYLOAD_SIZE, result.getPayloadSize()); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantTestHelper.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantTestHelper.java new file mode 100644 index 0000000000..a013cb0a06 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantTestHelper.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import org.apache.qpid.disttest.message.ParticipantResult; + +public class ParticipantTestHelper +{ + + public static void assertAtLeast(String message, final long minimumExpected, final long actual) + { + assertTrue(message + " " + actual, actual >= minimumExpected); + } + + public static void assertExpectedConsumerResults(ParticipantResult result, String participantName, String registeredClientName, long expectedTestStartTime, int expectedAcknowledgeMode, Integer expectedBatchSize, Integer expectedNumberOfMessages, Integer expectedPayloadSize, Long expectedTotalPayloadProcessed, Long expectedMinimumExpectedDuration) + { + assertExpectedResults(result, participantName, registeredClientName, expectedTestStartTime, + expectedAcknowledgeMode, expectedBatchSize, expectedNumberOfMessages, expectedPayloadSize, expectedTotalPayloadProcessed, expectedMinimumExpectedDuration); + assertEquals("Unexpected number of consumers", 1, result.getTotalNumberOfConsumers()); + assertEquals("Unexpected number of producers", 0, result.getTotalNumberOfProducers()); + } + + public static void assertExpectedProducerResults(ParticipantResult result, String participantName, String registeredClientName, long expectedTestStartTime, int expectedAcknowledgeMode, Integer expectedBatchSize, Integer expectedNumberOfMessages, Integer expectedPayloadSize, Long expectedTotalPayloadProcessed, Long expectedMinimumExpectedDuration) + { + assertExpectedResults(result, participantName, registeredClientName, expectedTestStartTime, expectedAcknowledgeMode, expectedBatchSize, expectedNumberOfMessages, expectedPayloadSize, expectedTotalPayloadProcessed, expectedMinimumExpectedDuration); + assertEquals("Unexpected number of producers", 1, result.getTotalNumberOfProducers()); + assertEquals("Unexpected number of consumers", 0, result.getTotalNumberOfConsumers()); + } + + private static void assertExpectedResults(ParticipantResult result, String participantName, String registeredClientName, long expectedTestStartTime, int expectedAcknowledgeMode, Integer expectedBatchSize, Integer expectedNumberOfMessages, Integer expectedPayloadSize, Long expectedTotalPayloadProcessed, Long expectedMinimumExpectedDuration) + { + assertFalse(result.hasError()); + + assertEquals("unexpected participant name", participantName, result.getParticipantName()); + assertEquals("unexpected client name", registeredClientName, result.getRegisteredClientName()); + + assertAtLeast("start time of result is too low", expectedTestStartTime, result.getStartInMillis()); + assertAtLeast("end time of result should be after start time", result.getStartInMillis(), result.getEndInMillis()); + + assertEquals("unexpected acknowledge mode", expectedAcknowledgeMode, result.getAcknowledgeMode()); + + if(expectedNumberOfMessages != null) + { + assertEquals("unexpected number of messages", expectedNumberOfMessages.intValue(), result.getNumberOfMessagesProcessed()); + } + if(expectedBatchSize != null) + { + assertEquals("unexpected batch size", expectedBatchSize.intValue(), result.getBatchSize()); + } + if (expectedPayloadSize != null) + { + assertEquals("unexpected payload size", expectedPayloadSize.intValue(), result.getPayloadSize()); + } + if (expectedTotalPayloadProcessed != null) + { + assertEquals("unexpected total payload processed", expectedTotalPayloadProcessed.longValue(), result.getTotalPayloadProcessed()); + } + if(expectedMinimumExpectedDuration != null) + { + assertAtLeast("participant did not take a sufficient length of time.", expectedMinimumExpectedDuration, result.getTimeTaken()); + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java new file mode 100644 index 0000000000..cf05623e8f --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client; + +import static org.apache.qpid.disttest.client.ParticipantTestHelper.assertExpectedProducerResults; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import javax.jms.DeliveryMode; +import javax.jms.Message; +import javax.jms.Session; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.mockito.InOrder; + +public class ProducerParticipantTest extends TestCase +{ + private ProducerParticipant _producer; + + private static final String SESSION_NAME1 = "SESSION1"; + private static final String PARTICIPANT_NAME1 = "PARTICIPANT_NAME1"; + + private static final String CLIENT_NAME = "CLIENT_NAME"; + private static final int PAYLOAD_SIZE_PER_MESSAGE = 1024; + + + private final Message _mockMessage = mock(Message.class); + private final CreateProducerCommand _command = new CreateProducerCommand(); + private ClientJmsDelegate _delegate; + private InOrder _inOrder; + + /** used to check start/end time of results */ + private long _testStartTime; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _delegate = mock(ClientJmsDelegate.class); + _inOrder = inOrder(_delegate); + + _command.setSessionName(SESSION_NAME1); + _command.setParticipantName(PARTICIPANT_NAME1); + + when(_delegate.sendNextMessage(isA(CreateProducerCommand.class))).thenReturn(_mockMessage); + when(_delegate.calculatePayloadSizeFrom(_mockMessage)).thenReturn(PAYLOAD_SIZE_PER_MESSAGE); + when(_delegate.getAcknowledgeMode(SESSION_NAME1)).thenReturn(Session.AUTO_ACKNOWLEDGE); + + _producer = new ProducerParticipant(_delegate, _command); + + _testStartTime = System.currentTimeMillis(); + } + + public void testStartDelay() throws Exception + { + final long delay = 100; + int numberOfMessages = 1; + long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages; + + _command.setStartDelay(delay); + _command.setNumberOfMessages(numberOfMessages); + + ParticipantResult result = _producer.doIt(CLIENT_NAME); + + long expectedPublishedStartTime = _testStartTime + delay; + assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, expectedPublishedStartTime, Session.AUTO_ACKNOWLEDGE, null, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null); + } + + + public void testNoMessagesToSend() throws Exception + { + _command.setNumberOfMessages(0); + _command.setMaximumDuration(0); + + try + { + _producer.doIt(CLIENT_NAME); + fail("Exception not thrown"); + } + catch (DistributedTestException e) + { + // PASS + assertEquals("number of messages and duration cannot both be zero", e.getMessage()); + } + } + + public void testOneMessageToSend() throws Exception + { + int batchSize = 1; + int numberOfMessages = 1; + long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages; + int deliveryMode = DeliveryMode.PERSISTENT; + + _command.setNumberOfMessages(numberOfMessages); + _command.setBatchSize(batchSize); + _command.setDeliveryMode(deliveryMode); + + ParticipantResult result = (ParticipantResult) _producer.doIt(CLIENT_NAME); + assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.AUTO_ACKNOWLEDGE, null, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null); + + _inOrder.verify(_delegate).sendNextMessage(isA(CreateProducerCommand.class)); + _inOrder.verify(_delegate).calculatePayloadSizeFrom(_mockMessage); + _inOrder.verify(_delegate).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + + } + + public void testSendMessagesForDuration() throws Exception + { + final long duration = 100; + _command.setMaximumDuration(duration); + + ParticipantResult result = _producer.doIt(CLIENT_NAME); + assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.AUTO_ACKNOWLEDGE, null, null, PAYLOAD_SIZE_PER_MESSAGE, null, duration); + + verify(_delegate, atLeastOnce()).sendNextMessage(isA(CreateProducerCommand.class)); + verify(_delegate, atLeastOnce()).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, atLeastOnce()).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testSendMessageBatches() throws Exception + { + final int batchSize = 3; + final int numberOfMessages = 10; + final int expectedNumberOfCommits = 4; // one for each batch of 3 messages, plus one more at the end of the test for the tenth msg. + long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages; + + _command.setNumberOfMessages(numberOfMessages); + _command.setBatchSize(batchSize); + + ParticipantResult result = _producer.doIt(CLIENT_NAME); + assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.AUTO_ACKNOWLEDGE, batchSize, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null); + + verify(_delegate, times(numberOfMessages)).sendNextMessage(isA(CreateProducerCommand.class)); + verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, times(expectedNumberOfCommits)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testSendMessageWithPublishInterval() throws Exception + { + final int batchSize = 3; + final long publishInterval = 100; + int numberOfMessages = 10; + long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages; + + final long expectedTimeToRunTest = batchSize * publishInterval; + + _command.setNumberOfMessages(numberOfMessages); + _command.setBatchSize(batchSize); + _command.setInterval(publishInterval); + + ParticipantResult result = _producer.doIt(CLIENT_NAME); + assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.AUTO_ACKNOWLEDGE, null, numberOfMessages, null, totalPayloadSize, expectedTimeToRunTest); + + verify(_delegate, times(numberOfMessages)).sendNextMessage(isA(CreateProducerCommand.class)); + verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, times(4)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testSendMessageWithVaryingPayloadSize() throws Exception + { + int numberOfMessages = 3; + + int firstPayloadSize = PAYLOAD_SIZE_PER_MESSAGE; + int secondPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * 2; + int thirdPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * 4; + + final long totalPayloadSize = firstPayloadSize + secondPayloadSize + thirdPayloadSize; + + when(_delegate.calculatePayloadSizeFrom(_mockMessage)).thenReturn(firstPayloadSize, secondPayloadSize, thirdPayloadSize); + + _command.setNumberOfMessages(numberOfMessages); + + ParticipantResult result = _producer.doIt(CLIENT_NAME); + + final int expectedPayloadResultPayloadSize = 0; + assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime, + Session.AUTO_ACKNOWLEDGE, null, numberOfMessages, expectedPayloadResultPayloadSize, totalPayloadSize, null); + + verify(_delegate, times(numberOfMessages)).sendNextMessage(isA(CreateProducerCommand.class)); + verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); + verify(_delegate, times(numberOfMessages)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + } + + public void testReleaseResources() + { + _producer.releaseResources(); + verify(_delegate).closeTestProducer(PARTICIPANT_NAME1); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java new file mode 100644 index 0000000000..75a634ba54 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.client.property.ListPropertyValue; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.client.property.SimplePropertyValue; + +public class ListPropertyValueTest extends TestCase +{ + private ListPropertyValue _generator; + private List _items; + + public void setUp() throws Exception + { + super.setUp(); + _generator = new ListPropertyValue(); + _items = new ArrayList(); + _items.add(new SimplePropertyValue(new Integer(1))); + _items.add(new SimplePropertyValue(new Double(2.1))); + _items.add(new SimplePropertyValue(new Boolean(true))); + ListPropertyValue innerList = new ListPropertyValue(); + List innerListItems = new ArrayList(); + innerListItems.add(new SimplePropertyValue("test")); + innerListItems.add(new SimplePropertyValue(new Integer(2))); + innerList.setItems(innerListItems); + _items.add(innerList); + _generator.setItems(_items); + } + + public void testGetItems() + { + List items = _generator.getItems(); + assertEquals("Unexpected list items", _items, items); + } + + public void testGetValue() + { + for (int i = 0; i < 2; i++) + { + assertEquals("Unexpected first item", new Integer(1), _generator.getValue()); + assertEquals("Unexpected second item", new Double(2.1), _generator.getValue()); + assertEquals("Unexpected third item", new Boolean(true), _generator.getValue()); + if (i == 0) + { + assertEquals("Unexpected forth item", "test", _generator.getValue()); + } + else + { + assertEquals("Unexpected forth item", new Integer(2), _generator.getValue()); + } + } + } + + public void testNonCyclicGetValue() + { + _generator.setCyclic(false); + assertFalse("Generator should not be cyclic", _generator.isCyclic()); + assertEquals("Unexpected first item", new Integer(1), _generator.getValue()); + assertEquals("Unexpected second item", new Double(2.1), _generator.getValue()); + assertEquals("Unexpected third item", new Boolean(true), _generator.getValue()); + assertEquals("Unexpected forth item", "test", _generator.getValue()); + assertEquals("Unexpected fifth item", new Integer(2), _generator.getValue()); + assertEquals("Unexpected sixs item", "test", _generator.getValue()); + assertEquals("Unexpected sevens item", new Integer(2), _generator.getValue()); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java new file mode 100644 index 0000000000..2d560163c2 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import junit.framework.TestCase; + +public class PropertyValueFactoryTest extends TestCase +{ + private PropertyValueFactory _factory; + + public void setUp() throws Exception + { + super.setUp(); + _factory = new PropertyValueFactory(); + } + + public void testCreateListPropertyValue() + { + PropertyValue propertyValue = _factory.createPropertyValue("list"); + assertNotNull("List generator is not created", propertyValue); + assertTrue("Unexpected type of list generator", propertyValue instanceof ListPropertyValue); + } + + public void testCreateRangePropertyValue() + { + PropertyValue propertyValue = _factory.createPropertyValue("range"); + assertNotNull("Range generator is not created", propertyValue); + assertTrue("Unexpected type of range generator", propertyValue instanceof RangePropertyValue); + } + + public void testCreateRandomPropertyValue() + { + PropertyValue propertyValue = _factory.createPropertyValue("random"); + assertNotNull("Random generator is not created", propertyValue); + assertTrue("Unexpected type of range generator", propertyValue instanceof RandomPropertyValue); + } + + public void testCreateSimplePropertyValue() + { + PropertyValue propertyValue = _factory.createPropertyValue("simple"); + assertNotNull("Simple property value is not created", propertyValue); + assertTrue("Unexpected type of property value", propertyValue instanceof SimplePropertyValue); + } + + public void testCreateNonExistingPropertyValue() + { + try + { + _factory.createPropertyValue("nonExisting"); + fail("Non existing property value should not be created"); + } + catch (Exception e) + { + // pass + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java new file mode 100644 index 0000000000..bd5de3e370 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import org.apache.qpid.disttest.client.property.RandomPropertyValue; + +import junit.framework.TestCase; + +public class RandomPropertyValueTest extends TestCase +{ + private RandomPropertyValue _generator; + + public void setUp() throws Exception + { + super.setUp(); + _generator = new RandomPropertyValue(); + _generator.setUpper(20.0); + _generator.setLower(10.0); + _generator.setType("double"); + } + + public void testGetters() + { + assertEquals("Unexpected upper boundary", new Double(20.0), _generator.getUpper()); + assertEquals("Unexpected lower boundary", new Double(10.0), _generator.getLower()); + assertEquals("Unexpected type", "double", _generator.getType()); + } + + public void testGetValue() + { + Object value = _generator.getValue(); + assertTrue("Unexpected type", value instanceof Double); + assertTrue("Unexpected value", ((Double) value).doubleValue() >= 10.0 + && ((Double) value).doubleValue() <= 20.0); + } + + public void testGetValueInt() + { + _generator.setType("int"); + Object value = _generator.getValue(); + assertTrue("Unexpected type", value instanceof Integer); + assertTrue("Unexpected value", ((Integer) value).intValue() >= 10 && ((Integer) value).intValue() <= 20); + } + + public void testGetValueLong() + { + _generator.setType("long"); + Object value = _generator.getValue(); + assertTrue("Unexpected type", value instanceof Long); + assertTrue("Unexpected value", ((Long) value).longValue() >= 10 && ((Long) value).longValue() <= 20); + } + + public void testGetValueFloat() + { + _generator.setType("float"); + Object value = _generator.getValue(); + assertTrue("Unexpected type", value instanceof Float); + assertTrue("Unexpected value", ((Float) value).floatValue() >= 10.0 && ((Float) value).floatValue() <= 20.0); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java new file mode 100644 index 0000000000..91791c9d55 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import org.apache.qpid.disttest.client.property.RangePropertyValue; + +import junit.framework.TestCase; + +public class RangePropertyValueTest extends TestCase +{ + private RangePropertyValue _generator; + + public void setUp() throws Exception + { + super.setUp(); + _generator = new RangePropertyValue(); + _generator.setUpper(10.0); + _generator.setLower(0.0); + _generator.setStep(2.0); + _generator.setType("double"); + } + + public void testGetters() + { + assertEquals("Unexpected upper boundary", new Double(10.0), _generator.getUpper()); + assertEquals("Unexpected lower boundary", new Double(0.0), _generator.getLower()); + assertEquals("Unexpected step", new Double(2.0), _generator.getStep()); + assertEquals("Unexpected type", "double", _generator.getType()); + assertTrue("Unexpected cyclic", _generator.isCyclic()); + } + + public void testGetValue() + { + double[] expected = { 0.0, 2.0, 4.0, 6.0, 8.0, 10.0 }; + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Double); + assertEquals("Unexpected value ", expected[i], value); + } + } + } + + public void testGetValueNonCyclic() + { + _generator.setCyclic(false); + double[] expected = { 0.0, 2.0, 4.0, 6.0, 8.0, 10.0 }; + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Double); + assertEquals("Unexpected value ", expected[i], value); + } + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertEquals("Unexpected value ", expected[expected.length - 1], value); + } + } + + public void testGetValueInt() + { + _generator.setType("int"); + int[] expected = { 0, 2, 4, 6, 8, 10 }; + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Integer); + assertEquals("Unexpected value ", expected[i], value); + } + } + } + + public void testGetValueByte() + { + _generator.setType("byte"); + byte[] expected = { 0, 2, 4, 6, 8, 10 }; + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Byte); + assertEquals("Unexpected value ", expected[i], value); + } + } + } + + public void testGetValueLong() + { + _generator.setType("long"); + long[] expected = { 0, 2, 4, 6, 8, 10 }; + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Long); + assertEquals("Unexpected value ", expected[i], value); + } + } + } + + public void testGetValueShort() + { + _generator.setType("short"); + short[] expected = { 0, 2, 4, 6, 8, 10 }; + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Short); + assertEquals("Unexpected value ", expected[i], value); + } + } + } + + public void testGetValueFloat() + { + _generator.setType("float"); + float[] expected = { 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f }; + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < expected.length; i++) + { + Object value = _generator.getValue(); + assertTrue("Should be Double", value instanceof Float); + assertEquals("Unexpected value ", expected[i], value); + } + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java new file mode 100644 index 0000000000..a347d866c7 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.client.property; + +import junit.framework.TestCase; + +public class SimplePropertyValueTest extends TestCase +{ + public void testGetValue() + { + SimplePropertyValue value = new SimplePropertyValue(new Integer(1)); + assertEquals("Unexpected value", new Integer(1), value.getValue()); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java new file mode 100644 index 0000000000..cc969e1ef2 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import java.util.Timer; +import java.util.TimerTask; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.DistributedTestException; + +public class ClientRegistryTest extends TestCase +{ + private static final String CLIENT1_REGISTERED_NAME = "CLIENT1_REGISTERED_NAME"; + private static final String CLIENT2_REGISTERED_NAME = "CLIENT2_REGISTERED_NAME"; + private static final int AWAIT_DELAY = 100; + + private ClientRegistry _clientRegistry = new ClientRegistry(); + + public void testRegisterClient() + { + assertEquals(0, _clientRegistry.getClients().size()); + + _clientRegistry.registerClient(CLIENT1_REGISTERED_NAME); + assertEquals(1, _clientRegistry.getClients().size()); + + } + + public void testRejectsDuplicateClientNames() + { + _clientRegistry.registerClient(CLIENT1_REGISTERED_NAME); + try + { + _clientRegistry.registerClient(CLIENT1_REGISTERED_NAME); + fail("Should have thrown an exception"); + } + catch (final DistributedTestException e) + { + // pass + } + } + + public void testAwaitOneClientWhenClientNotRegistered() + { + int numberOfClientsAbsent = _clientRegistry.awaitClients(1, AWAIT_DELAY); + assertEquals(1, numberOfClientsAbsent); + } + + public void testAwaitOneClientWhenClientAlreadyRegistered() + { + _clientRegistry.registerClient(CLIENT1_REGISTERED_NAME); + + int numberOfClientsAbsent = _clientRegistry.awaitClients(1, AWAIT_DELAY); + assertEquals(0, numberOfClientsAbsent); + } + + public void testAwaitTwoClientWhenClientRegistersWhilstWaiting() + { + _clientRegistry.registerClient(CLIENT1_REGISTERED_NAME); + registerClientLater(CLIENT2_REGISTERED_NAME, 50); + + int numberOfClientsAbsent = _clientRegistry.awaitClients(2, AWAIT_DELAY); + assertEquals(0, numberOfClientsAbsent); + } + + private void registerClientLater(final String clientName, long delayInMillis) + { + doLater(new TimerTask() + { + @Override + public void run() + { + _clientRegistry.registerClient(clientName); + } + }, delayInMillis); + } + + private void doLater(TimerTask task, long delayInMillis) + { + Timer timer = new Timer(); + timer.schedule(task, delayInMillis); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java new file mode 100644 index 0000000000..bc58ea41c5 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.config.Config; +import org.apache.qpid.disttest.controller.config.TestInstance; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.apache.qpid.disttest.results.aggregation.ITestResult; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class ControllerTest extends TestCase +{ + private static final String CLIENT1_REGISTERED_NAME = "client-uid1"; + + private static final long COMMAND_RESPONSE_TIMEOUT = 1000; + private static final long REGISTRATION_TIMEOUT = 1000; + + private Controller _controller; + private ControllerJmsDelegate _respondingJmsDelegate; + private TestRunner _testRunner; + private ClientRegistry _clientRegistry; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _respondingJmsDelegate = mock(ControllerJmsDelegate.class); + _controller = new Controller(_respondingJmsDelegate, REGISTRATION_TIMEOUT, COMMAND_RESPONSE_TIMEOUT); + _testRunner = mock(TestRunner.class); + _clientRegistry = mock(ClientRegistry.class); + + Config configWithOneClient = createMockConfig(1); + _controller.setConfig(configWithOneClient); + _controller.setClientRegistry(_clientRegistry); + _controller.setTestRunnerFactory(createTestFactoryReturningMock()); + + doAnswer(new Answer() + { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable + { + final String clientName = (String)invocation.getArguments()[0]; + final Command command = (Command)invocation.getArguments()[1]; + _controller.processStopClientResponse(new Response(clientName, command.getType())); + return null; + } + }).when(_respondingJmsDelegate).sendCommandToClient(anyString(), isA(Command.class)); + } + + + public void testControllerRejectsEmptyConfiguration() + { + Config configWithZeroClients = createMockConfig(0); + + try + { + _controller.setConfig(configWithZeroClients); + fail("Exception not thrown"); + } + catch (DistributedTestException e) + { + // PASS + } + } + + public void testControllerReceivesTwoExpectedClientRegistrations() + { + Config configWithTwoClients = createMockConfig(2); + _controller.setConfig(configWithTwoClients); + when(_clientRegistry.awaitClients(2, REGISTRATION_TIMEOUT)).thenReturn(0); + + _controller.awaitClientRegistrations(); + } + + public void testControllerDoesntReceiveAnyRegistrations() + { + when(_clientRegistry.awaitClients(1, REGISTRATION_TIMEOUT)).thenReturn(1); + + try + { + _controller.awaitClientRegistrations(); + fail("Exception not thrown"); + } + catch (DistributedTestException e) + { + // PASS + } + } + + public void testRegisterClient() + { + RegisterClientCommand command = new RegisterClientCommand(CLIENT1_REGISTERED_NAME, "dummy"); + _controller.registerClient(command); + + verify(_clientRegistry).registerClient(CLIENT1_REGISTERED_NAME); + verify(_respondingJmsDelegate).registerClient(command); + + } + + public void testControllerSendsClientStopCommandToClient() + { + when(_clientRegistry.getClients()).thenReturn(Collections.singleton(CLIENT1_REGISTERED_NAME)); + + _controller.stopAllRegisteredClients(); + + verify(_respondingJmsDelegate).sendCommandToClient(eq(CLIENT1_REGISTERED_NAME), isA(StopClientCommand.class)); + } + + public void testRunAllTests() + { + Config config = createSimpleConfig(); + _controller.setConfig(config); + + TestResult testResult = new TestResult("test1"); + + when(_testRunner.run()).thenReturn(testResult); + + ResultsForAllTests results = _controller.runAllTests(); + + List testResults = results.getTestResults(); + assertEquals(1, testResults.size()); + assertSame(testResult, testResults.get(0)); + + verify(_testRunner).run(); + } + + private Config createSimpleConfig() + { + Config config = mock(Config.class); + TestInstance testInstance = mock(TestInstance.class); + + List testInstances = Arrays.asList(testInstance); + + when(config.getTests()).thenReturn(testInstances); + when(config.getTotalNumberOfClients()).thenReturn(1); // necessary otherwise controller rejects "invalid" config + + return config; + } + + private Config createMockConfig(int numberOfClients) + { + Config config = mock(Config.class); + when(config.getTotalNumberOfClients()).thenReturn(numberOfClients); + return config; + } + + private TestRunnerFactory createTestFactoryReturningMock() + { + TestRunnerFactory testRunnerFactory = mock(TestRunnerFactory.class); + + when(testRunnerFactory.createTestRunner( + isA(ParticipatingClients.class), + isA(TestInstance.class), + isA(ControllerJmsDelegate.class), + isA(Long.class), + isA(Long.class))) + .thenReturn(_testRunner); + + return testRunnerFactory; + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java new file mode 100644 index 0000000000..284db38f44 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import junit.framework.TestCase; + +public class ParticipatingClientsTest extends TestCase +{ + private static final String CLIENT1_CONFIGURED_NAME = "CLIENT1_CONFIGURED_NAME"; + private static final String CLIENT2_CONFIGURED_NAME = "CLIENT2_CONFIGURED_NAME"; + + private static final String CLIENT1_REGISTERED_NAME = "CLIENT1_REGISTERED_NAME"; + private static final String CLIENT2_REGISTERED_NAME = "CLIENT2_REGISTERED_NAME"; + private static final String CLIENT3_REGISTERED_NAME = "CLIENT3_REGISTERED_NAME"; + private ClientRegistry _clientRegistry; + private List _configuredClientNamesForTest; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _clientRegistry = mock(ClientRegistry.class); + } + + public void testTooFewRegisteredClientsForTest() + { + _configuredClientNamesForTest = Arrays.asList(CLIENT1_CONFIGURED_NAME, CLIENT2_CONFIGURED_NAME); + when(_clientRegistry.getClients()).thenReturn(Arrays.asList(CLIENT1_REGISTERED_NAME)); + + try + { + new ParticipatingClients(_clientRegistry, _configuredClientNamesForTest); + fail("Exception not thrown"); + } + catch (IllegalArgumentException e) + { + // PASS + } + + } + + + public void testSelectOneClientFromPoolOfOne() + { + _configuredClientNamesForTest = Arrays.asList(CLIENT1_CONFIGURED_NAME); + when(_clientRegistry.getClients()).thenReturn(Arrays.asList(CLIENT1_REGISTERED_NAME)); + + ParticipatingClients clients = new ParticipatingClients(_clientRegistry, _configuredClientNamesForTest); + assertBothWays(clients, CLIENT1_REGISTERED_NAME, CLIENT1_CONFIGURED_NAME); + } + + public void testSelectTwoClientFromPoolOfMany() + { + _configuredClientNamesForTest = Arrays.asList(CLIENT1_CONFIGURED_NAME, CLIENT2_CONFIGURED_NAME); + when(_clientRegistry.getClients()).thenReturn(Arrays.asList(CLIENT1_REGISTERED_NAME, CLIENT2_REGISTERED_NAME, CLIENT3_REGISTERED_NAME)); + + ParticipatingClients clients = new ParticipatingClients(_clientRegistry, _configuredClientNamesForTest); + + assertBothWays(clients, CLIENT1_REGISTERED_NAME, CLIENT1_CONFIGURED_NAME); + assertBothWays(clients, CLIENT2_REGISTERED_NAME, CLIENT2_CONFIGURED_NAME); + } + + public void testGetUnrecognisedConfiguredName() + { + _configuredClientNamesForTest = Arrays.asList(CLIENT1_CONFIGURED_NAME); + when(_clientRegistry.getClients()).thenReturn(Arrays.asList(CLIENT1_REGISTERED_NAME)); + + ParticipatingClients clients = new ParticipatingClients(_clientRegistry, _configuredClientNamesForTest); + + testUnrecognisedClientConfiguredName(clients, "unknown"); + testUnrecognisedClientRegisteredName(clients, "unknown"); + } + + public void testGetRegisteredClientNames() + { + _configuredClientNamesForTest = Arrays.asList(CLIENT1_CONFIGURED_NAME); + List registeredNames = Arrays.asList(CLIENT1_REGISTERED_NAME); + when(_clientRegistry.getClients()).thenReturn(registeredNames); + + ParticipatingClients clients = new ParticipatingClients(_clientRegistry, _configuredClientNamesForTest); + + Collection registeredParticipatingNames = clients.getRegisteredNames(); + assertEquals(1, registeredParticipatingNames.size()); + assertTrue(registeredParticipatingNames.contains(CLIENT1_REGISTERED_NAME)); + } + + private void testUnrecognisedClientConfiguredName(ParticipatingClients clients, String unrecognisedClientConfiguredName) + { + try + { + clients.getRegisteredNameFromConfiguredName(unrecognisedClientConfiguredName); + fail("Exception not thrown"); + } + catch (IllegalArgumentException e) + { + // PASS + } + } + + private void testUnrecognisedClientRegisteredName(ParticipatingClients clients, String unrecognisedClientRegisteredName) + { + try + { + clients.getConfiguredNameFromRegisteredName(unrecognisedClientRegisteredName); + fail("Exception not thrown"); + } + catch (IllegalArgumentException e) + { + // PASS + } + } + + private void assertBothWays(ParticipatingClients clients, String registeredName, String configuredName) + { + assertEquals(registeredName, clients.getRegisteredNameFromConfiguredName(configuredName)); + assertEquals(configuredName, clients.getConfiguredNameFromRegisteredName(registeredName)); + } + + + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java new file mode 100644 index 0000000000..983da299b9 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.config.QueueConfig; +import org.apache.qpid.disttest.controller.config.TestInstance; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StartTestCommand; +import org.apache.qpid.disttest.message.TearDownTestCommand; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class TestRunnerTest extends TestCase +{ + private static final String TEST_NAME = "TEST_NAME"; + private static final String PARTICIPANT_NAME = "TEST_PARTICIPANT_NAME"; + private static final int ITERATION_NUMBER = 1; + + private static final String CLIENT1_REGISTERED_NAME = "client-uid1"; + private static final String CLIENT1_CONFIGURED_NAME = "client1"; + + private static final long COMMAND_RESPONSE_TIMEOUT = 1000; + private static final long TEST_RESULT_TIMEOUT = 2000; + private static final long DELAY = 100; + + private TestRunner _testRunner; + private TestInstance _testInstance; + private ControllerJmsDelegate _respondingJmsDelegate; + private ParticipatingClients _participatingClients; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _respondingJmsDelegate = mock(ControllerJmsDelegate.class); + + _participatingClients = mock(ParticipatingClients.class); + when(_participatingClients.getRegisteredNameFromConfiguredName(CLIENT1_CONFIGURED_NAME)).thenReturn(CLIENT1_REGISTERED_NAME); + when(_participatingClients.getConfiguredNameFromRegisteredName(CLIENT1_REGISTERED_NAME)).thenReturn(CLIENT1_CONFIGURED_NAME); + when(_participatingClients.getRegisteredNames()).thenReturn(Collections.singleton(CLIENT1_REGISTERED_NAME)); + + doAnswer(new Answer() + { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable + { + final String clientName = (String)invocation.getArguments()[0]; + final Command command = (Command)invocation.getArguments()[1]; + _testRunner.processCommandResponse(new Response(clientName, command.getType())); + return null; + } + }).when(_respondingJmsDelegate).sendCommandToClient(anyString(), isA(Command.class)); + } + + public void testSendConnectionCommandToClient() + { + _testInstance = createTestInstanceWithConnection(); + + _testRunner = new TestRunner(_participatingClients, _testInstance , _respondingJmsDelegate, COMMAND_RESPONSE_TIMEOUT, TEST_RESULT_TIMEOUT); + _testRunner.sendTestSetupCommands(); + + verify(_respondingJmsDelegate).sendCommandToClient(eq(CLIENT1_REGISTERED_NAME), isA(CreateConnectionCommand.class)); + } + + public void testSendCommandToAllParticipatingClients() + { + _testRunner = new TestRunner(_participatingClients, mock(TestInstance.class), _respondingJmsDelegate, COMMAND_RESPONSE_TIMEOUT, TEST_RESULT_TIMEOUT); + + StartTestCommand startTestCommand = new StartTestCommand(); + _testRunner.sendCommandToParticipatingClients(startTestCommand); + + verify(_respondingJmsDelegate).sendCommandToClient(CLIENT1_REGISTERED_NAME, startTestCommand); + } + + public void testWaitsForCommandResponses() + { + _testInstance = createTestInstanceWithConnection(); + _testRunner = new TestRunner(_participatingClients, _testInstance , _respondingJmsDelegate, COMMAND_RESPONSE_TIMEOUT, TEST_RESULT_TIMEOUT); + + _testRunner.sendTestSetupCommands(); + + _testRunner.awaitCommandResponses(); + } + + public void testClientFailsToSendCommandResponseWithinTimeout() + { + ControllerJmsDelegate jmsDelegate = mock(ControllerJmsDelegate.class); + + _testInstance = createTestInstanceWithConnection(); + _testRunner = new TestRunner(_participatingClients, _testInstance , jmsDelegate, COMMAND_RESPONSE_TIMEOUT, TEST_RESULT_TIMEOUT); + + _testRunner.sendTestSetupCommands(); + // we don't call sendCommandResponseLater so controller should time out + + try + { + _testRunner.awaitCommandResponses(); + fail("Exception not thrown"); + } + catch (DistributedTestException e) + { + // PASS + } + } + + public void testCreateAndDeleteQueues() + { + _testInstance = mock(TestInstance.class); + List queues = mock(List.class); + when(_testInstance.getQueues()).thenReturn(queues); + + _testRunner = new TestRunner(_participatingClients, _testInstance, _respondingJmsDelegate, COMMAND_RESPONSE_TIMEOUT, TEST_RESULT_TIMEOUT); + + _testRunner.createQueues(); + verify(_respondingJmsDelegate).createQueues(queues); + + _testRunner.deleteQueues(); + verify(_respondingJmsDelegate).deleteQueues(queues); + } + + public void testRun() + { + _testInstance = createTestInstanceWithOneParticipant(); + _testRunner = new TestRunner(_participatingClients, _testInstance , _respondingJmsDelegate, COMMAND_RESPONSE_TIMEOUT, TEST_RESULT_TIMEOUT); + + ParticipantResult incomingParticipantResult = new ParticipantResult(PARTICIPANT_NAME); + incomingParticipantResult.setRegisteredClientName(CLIENT1_REGISTERED_NAME); + sendTestResultsLater(_testRunner, incomingParticipantResult); + + TestResult results = _testRunner.run(); + + verify(_respondingJmsDelegate).addCommandListener(isA(TestRunner.TestCommandResponseListener.class)); + verify(_respondingJmsDelegate).addCommandListener(isA(TestRunner.ParticipantResultListener.class)); + + verify(_respondingJmsDelegate).createQueues(isA(List.class)); + + verify(_respondingJmsDelegate).sendCommandToClient(eq(CLIENT1_REGISTERED_NAME), isA(StartTestCommand.class)); + verify(_respondingJmsDelegate).sendCommandToClient(eq(CLIENT1_REGISTERED_NAME), isA(NoOpCommand.class)); + verify(_respondingJmsDelegate).sendCommandToClient(eq(CLIENT1_REGISTERED_NAME), isA(TearDownTestCommand.class)); + + verify(_respondingJmsDelegate).deleteQueues(isA(List.class)); + + verify(_respondingJmsDelegate).removeCommandListener(isA(TestRunner.ParticipantResultListener.class)); + verify(_respondingJmsDelegate).removeCommandListener(isA(TestRunner.TestCommandResponseListener.class)); + + List participantResults = results.getParticipantResults(); + assertEquals(1, participantResults.size()); + ParticipantResult resultingParticipantResult = participantResults.get(0); + + assertResultHasCorrectTestDetails(resultingParticipantResult); + } + + private void assertResultHasCorrectTestDetails(ParticipantResult resultingParticipantResult) + { + assertEquals("Test runner should have set configured name when it received participant results", + CLIENT1_CONFIGURED_NAME, resultingParticipantResult.getConfiguredClientName()); + assertEquals("Test runner should have set test name when it received participant results", + TEST_NAME, resultingParticipantResult.getTestName()); + assertEquals("Test runner should have set test iteration number when it received participant results", + ITERATION_NUMBER, resultingParticipantResult.getIterationNumber()); + } + + + private TestInstance createTestInstanceWithOneParticipant() + { + TestInstance testInstance = mock(TestInstance.class); + + List commands = Arrays.asList( + new CommandForClient(CLIENT1_CONFIGURED_NAME, new NoOpCommand())); + + when(testInstance.createCommands()).thenReturn(commands); + + when(testInstance.getTotalNumberOfParticipants()).thenReturn(1); + + when(testInstance.getName()).thenReturn(TEST_NAME); + + List queues = mock(List.class); + when(testInstance.getQueues()).thenReturn(queues); + + when(testInstance.getIterationNumber()).thenReturn(ITERATION_NUMBER); + + return testInstance; + } + + private TestInstance createTestInstanceWithConnection() + { + TestInstance testInstance = mock(TestInstance.class); + + List commands = Arrays.asList( + new CommandForClient(CLIENT1_CONFIGURED_NAME, new CreateConnectionCommand("conn1", "factory"))); + + when(testInstance.createCommands()).thenReturn(commands); + + return testInstance; + } + + private void sendTestResultsLater(final TestRunner runner, final ParticipantResult result) + { + doLater(new TimerTask() + { + @Override + public void run() + { + runner.processParticipantResult(result); + } + }, DELAY); + } + + private void doLater(TimerTask task, long delayInMillis) + { + Timer timer = new Timer(); + timer.schedule(task, delayInMillis); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java new file mode 100644 index 0000000000..d4af439dea --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import static org.apache.qpid.disttest.controller.config.ConfigTestUtils.assertCommandForClient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.client.property.SimplePropertyValue; +import org.apache.qpid.disttest.controller.CommandForClient; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.disttest.message.NoOpCommand; + +public class ClientConfigTest extends TestCase +{ + private static final String CLIENT1 = "client1"; + + public void testClientConfigHasZeroArgConstructorForGson() + { + ClientConfig c = new ClientConfig(); + assertNotNull(c); + } + + public void testCreateCommands() + { + ClientConfig clientConfig = createClientConfigWithConnectionConfigReturningChildCommands(); + + List commands = clientConfig.createCommands(); + assertEquals(2, commands.size()); + + assertCommandForClient(commands, 0, CLIENT1, NoOpCommand.class); + assertCommandForClient(commands, 1, CLIENT1, NoOpCommand.class); + } + + public void testCreateCommandsForMessageProvider() + { + ClientConfig clientConfig = createClientConfigWithMessageProviderConfigReturningCommands(); + + List commands = clientConfig.createCommands(); + assertEquals(1, commands.size()); + + assertCommandForClient(commands, 0, CLIENT1, CreateMessageProviderCommand.class); + } + + public void testGetTotalNumberOfParticipants() + { + ClientConfig clientConfig = createClientConfigWithTwoParticipants(); + assertEquals(2, clientConfig.getTotalNumberOfParticipants()); + } + + private ClientConfig createClientConfigWithConnectionConfigReturningChildCommands() + { + ConnectionConfig connectionConfig = mock(ConnectionConfig.class); + + List commands = Arrays.asList((Command)new NoOpCommand(), (Command)new NoOpCommand()); + when(connectionConfig.createCommands()).thenReturn(commands); + + return new ClientConfig(CLIENT1, connectionConfig); + } + + private ClientConfig createClientConfigWithMessageProviderConfigReturningCommands() + { + Map messageProperties = new HashMap(); + messageProperties.put("test", new SimplePropertyValue("testValue")); + MessageProviderConfig config = new MessageProviderConfig("test", messageProperties); + + List providerConfigs = new ArrayList(); + providerConfigs.add(config); + + return new ClientConfig(CLIENT1, new ArrayList(), providerConfigs); + } + + private ClientConfig createClientConfigWithTwoParticipants() + { + ConnectionConfig connectionConfig1 = mock(ConnectionConfig.class); + ConnectionConfig connectionConfig2 = mock(ConnectionConfig.class); + + when(connectionConfig1.getTotalNumberOfParticipants()).thenReturn(1); + when(connectionConfig2.getTotalNumberOfParticipants()).thenReturn(1); + + ClientConfig clientConfig = new ClientConfig(CLIENT1, connectionConfig1, connectionConfig2); + return clientConfig; + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java new file mode 100644 index 0000000000..af9ec28db0 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import java.io.Reader; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.ConfigFileHelper; +import org.apache.qpid.disttest.client.MessageProvider; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.controller.CommandForClient; + +public class ConfigReaderTest extends TestCase +{ + private Config _config; + + @Override + protected void setUp() + { + ConfigReader configReader = new ConfigReader(); + Reader reader = ConfigFileHelper.getConfigFileReader(getClass(), "sampleConfig.json"); + _config = configReader.readConfig(reader); + } + + public void testReadTest() + { + List tests = _config.getTestConfigs(); + assertEquals("Unexpected number of tests", 2, tests.size()); + TestConfig test1Config = tests.get(0); + assertNotNull("Test 1 configuration is expected", test1Config); + assertEquals("Unexpected test name", "Test 1", test1Config.getName()); + + TestConfig test2Config = tests.get(1); + assertNotNull("Test 2 configuration is expected", test2Config); + } + + public void testReadsTestWithQueues() + { + TestConfig test1Config = _config.getTestConfigs().get(0); + List queues = test1Config.getQueues(); + assertEquals("Unexpected number of queues", 2, queues.size()); + QueueConfig queue1Config = queues.get(0); + assertNotNull("Expected queue 1 config", queue1Config); + assertEquals("Unexpected queue name", "Json-Queue-Name", queue1Config.getName()); + assertTrue("Unexpected attributes", queue1Config.getAttributes().isEmpty()); + assertFalse("Unexpected durable", queue1Config.isDurable()); + + QueueConfig queue2Config = queues.get(1); + assertNotNull("Expected queue 2 config", queue2Config); + assertEquals("Unexpected queue name", "Json Queue Name 2", queue2Config.getName()); + assertTrue("Unexpected durable", queue2Config.isDurable()); + Map attributes = queue2Config.getAttributes(); + assertNotNull("Expected attributes", attributes); + assertFalse("Attributes are not loaded", attributes.isEmpty()); + assertEquals("Unexpected number of attributes", 1, attributes.size()); + assertEquals("Unexpected attribute 'x-qpid-priorities' value", 10, + ((Number)attributes.get("x-qpid-priorities")).intValue()); + } + + public void testReadsTestWithIterations() + { + TestConfig testConfig = _config.getTestConfigs().get(0); + List iterationValues = testConfig.getIterationValues(); + assertEquals("Unexpected number of iterations", 2, iterationValues.size()); + + IterationValue iteration1 = iterationValues.get(0); + + String messageSizeProperty = "_messageSize"; + + assertEquals("Unexpected value for property " + messageSizeProperty, + "100", + iteration1.getIterationPropertyValuesWithUnderscores().get(messageSizeProperty)); + } + + public void testReadsMessageProviders() + { + TestConfig testConfig = _config.getTestConfigs().get(0); + ClientConfig cleintConfig = testConfig.getClients().get(0); + List configs = cleintConfig.getMessageProviders(); + assertNotNull("Message provider configs should not be null", configs); + assertEquals("Unexpected number of message providers", 1, configs.size()); + MessageProviderConfig messageProvider = configs.get(0); + assertNotNull("Message provider config should not be null", messageProvider); + assertEquals("Unexpected provider name", "testProvider1", messageProvider.getName()); + Map properties = messageProvider.getMessageProperties(); + assertNotNull("Message properties should not be null", properties); + assertEquals("Unexpected number of message properties", 3, properties.size()); + assertNotNull("test property is not found", properties.get("test")); + assertNotNull("priority property is not found", properties.get("priority")); + assertNotNull("id property is not found", properties.get("id")); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java new file mode 100644 index 0000000000..88750b9737 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.List; + +import junit.framework.TestCase; + +public class ConfigTest extends TestCase +{ + public void testGetTestsForTestWithIteratingMessageSizes() + { + Config config = createConfigWithIteratingMessageSizes(); + List testConfigs = config.getTests(); + + assertEquals("should have a test config for each message size", 2, testConfigs.size()); + + TestInstance instance0 = testConfigs.get(0); + assertEquals(0, instance0.getIterationNumber()); + + TestInstance instance1 = testConfigs.get(1); + assertEquals(1, instance1.getIterationNumber()); + } + + private Config createConfigWithIteratingMessageSizes() + { + TestConfig testConfig = mock(TestConfig.class); + + when(testConfig.getIterationValues()).thenReturn(Arrays.asList(new IterationValue(),new IterationValue())); + + Config config = new Config(testConfig); + + return config; + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTestUtils.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTestUtils.java new file mode 100644 index 0000000000..ce5f92724f --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTestUtils.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import java.util.List; + +import org.apache.qpid.disttest.controller.CommandForClient; +import org.apache.qpid.disttest.message.Command; + +public class ConfigTestUtils +{ + public static void assertCommandForClient(final List commandsForClients, final int index, final String expectedRegisteredClientName, final Class expectedCommandClass) + { + final CommandForClient commandForClient = commandsForClients.get(index); + assertEquals(expectedRegisteredClientName, commandForClient.getClientName()); + final Command command = commandForClient.getCommand(); + assertTrue("Command " + index + " is of class " + command.getClass() + " but expecting " + expectedCommandClass, + expectedCommandClass.isAssignableFrom(command.getClass())); + } + + public static void assertCommandEquals(final List commands, final int index, final Class expectedCommandClass) + { + @SuppressWarnings("unchecked") + C command = (C) getCommand(commands, index); //explicit cast added to get round oracle compiler bug (id 6302954) + assertTrue("Command " + index + " is of class " + command.getClass() + " but expecting " + expectedCommandClass, + expectedCommandClass.isAssignableFrom(command.getClass())); + } + + public static C getCommand(final List commands, final int index) + { + @SuppressWarnings("unchecked") + C command = (C) commands.get(index); + return command; + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java new file mode 100644 index 0000000000..7c839ed462 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import static org.apache.qpid.disttest.controller.config.ConfigTestUtils.assertCommandEquals; +import static org.apache.qpid.disttest.controller.config.ConfigTestUtils.getCommand; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.NoOpCommand; + +public class ConnectionConfigTest extends TestCase +{ + private static final String CONNECTION_FACTORY_NAME = "ConnectionFactoryName"; + private static final String CONNECTION_NAME = "ConnectionName"; + + public void testConnectionConfigHasZeroArgConstructorForGson() + { + ConnectionConfig c = new ConnectionConfig(); + assertNotNull(c); + } + + public void testCreateCommandsForConnectionAndChildren() + { + ConnectionConfig connectionConfig = createConnectionConfigWithChildCommands(); + + List commands = connectionConfig.createCommands(); + assertEquals(3, commands.size()); + + assertCommandEquals(commands, 0, CreateConnectionCommand.class); + assertCommandEquals(commands, 1, NoOpCommand.class); + assertCommandEquals(commands, 2, NoOpCommand.class); + + CreateConnectionCommand createConnectionCommand = getCommand(commands, 0); + assertEquals(CONNECTION_NAME, createConnectionCommand.getConnectionName()); + assertEquals(CONNECTION_FACTORY_NAME, createConnectionCommand.getConnectionFactoryName()); + } + + public void testGetTotalNumberOfParticipants() + { + ConnectionConfig connectionConfig = createConnectionConfigWithTwoParticipants(); + assertEquals(2, connectionConfig.getTotalNumberOfParticipants()); + } + + private ConnectionConfig createConnectionConfigWithTwoParticipants() + { + SessionConfig sessionConfig1 = mock(SessionConfig.class); + SessionConfig sessionConfig2 = mock(SessionConfig.class); + + when(sessionConfig1.getTotalNumberOfParticipants()).thenReturn(1); + when(sessionConfig2.getTotalNumberOfParticipants()).thenReturn(1); + + ConnectionConfig connectionConfig = new ConnectionConfig(CONNECTION_NAME, CONNECTION_FACTORY_NAME, sessionConfig1, sessionConfig2); + + return connectionConfig; + } + + private ConnectionConfig createConnectionConfigWithChildCommands() + { + SessionConfig sessionConfig = mock(SessionConfig.class); + + NoOpCommand cmd1 = mock(NoOpCommand.class); + NoOpCommand cmd2 = mock(NoOpCommand.class); + List commands = Arrays.asList((Command)cmd1, (Command)cmd2); + when(sessionConfig.createCommands(CONNECTION_NAME)).thenReturn(commands); + + return new ConnectionConfig(CONNECTION_NAME, CONNECTION_FACTORY_NAME, sessionConfig); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java new file mode 100644 index 0000000000..c011ff4711 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.CreateConsumerCommand; + +public class ConsumerConfigTest extends TestCase +{ + public void testConsumerHasZeroArgConstructorForGson() + { + ConsumerConfig c = new ConsumerConfig(); + assertNotNull(c); + } + + public void testCreateConsumerCommand() + { + boolean isTopic = true; + boolean isDurableSubscription = true; + boolean isBrowsingSubscription = true; + boolean noLocal = true; + long numberOfMessages = 100; + String consumerName = "consumerName"; + String sessionName = "sessionName"; + String destinationName = "destinationName"; + String selector = "selector"; + int batchSize = 10;; + long maximumDuration = 50; + boolean isSynchronousNonDefault = false; + + ConsumerConfig consumerConfig = new ConsumerConfig( + consumerName, + destinationName, + numberOfMessages, + batchSize, + maximumDuration, + isTopic, + isDurableSubscription, + isBrowsingSubscription, + selector, + noLocal, + isSynchronousNonDefault); + + CreateConsumerCommand createConsumerCommand = consumerConfig.createCommand(sessionName); + + assertEquals(sessionName, createConsumerCommand.getSessionName()); + assertEquals(consumerName, createConsumerCommand.getParticipantName()); + assertEquals(destinationName, createConsumerCommand.getDestinationName()); + assertEquals(numberOfMessages, createConsumerCommand.getNumberOfMessages()); + assertEquals(batchSize, createConsumerCommand.getBatchSize()); + assertEquals(maximumDuration, createConsumerCommand.getMaximumDuration()); + + assertEquals(isTopic, createConsumerCommand.isTopic()); + assertEquals(isDurableSubscription, createConsumerCommand.isDurableSubscription()); + assertEquals(isBrowsingSubscription, createConsumerCommand.isBrowsingSubscription()); + assertEquals(selector, createConsumerCommand.getSelector()); + assertEquals(noLocal, createConsumerCommand.isNoLocal()); + assertEquals(isSynchronousNonDefault, createConsumerCommand.isSynchronous()); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java new file mode 100644 index 0000000000..7998eae37e --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +import java.util.Collections; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; + +public class IterationValueTest extends TestCase +{ + private static final int MESSAGE_SIZE = 10; + + private CreateProducerCommand _createProducerCommand; + private CreateConsumerCommand _createConsumerCommand; + private Map _iterationValueMap; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _createProducerCommand = mock(CreateProducerCommand.class); + _createConsumerCommand = mock(CreateConsumerCommand.class); + + _iterationValueMap = Collections.singletonMap("_messageSize", String.valueOf(MESSAGE_SIZE)); + } + + public void testApplyPopulatedIterationValueToCommandWithMatchingProperties() throws Exception + { + IterationValue iterationValue = new IterationValue(_iterationValueMap); + + iterationValue.applyToCommand(_createProducerCommand); + + verify(_createProducerCommand).setMessageSize(MESSAGE_SIZE); + } + + public void testApplyPopulatedIterationValueToCommandWithoutMatchingProperties() throws Exception + { + IterationValue iterationValue = new IterationValue(_iterationValueMap); + + iterationValue.applyToCommand(_createConsumerCommand); + + verifyZeroInteractions(_createConsumerCommand); + } + + public void testApplyUnpopulatedIterationValueToCommand() throws Exception + { + IterationValue iterationValue = new IterationValue(); + + iterationValue.applyToCommand(_createProducerCommand); + + verifyZeroInteractions(_createProducerCommand); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java new file mode 100644 index 0000000000..a3b367a4b4 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.client.property.SimplePropertyValue; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; + +public class MessageProviderConfigTest extends TestCase +{ + public void testCreateCommandsForMessageProvider() + { + Map messageProperties = new HashMap(); + messageProperties.put("test", new SimplePropertyValue("testValue")); + MessageProviderConfig config = new MessageProviderConfig("test", messageProperties); + CreateMessageProviderCommand command = config.createCommand(); + assertNotNull("Command should not be null", command); + assertNotNull("Unexpected name", command.getProviderName()); + assertEquals("Unexpected properties", messageProperties, command.getMessageProperties()); + } + + public void testMessageProviderConfig() + { + Map messageProperties = new HashMap(); + messageProperties.put("test", new SimplePropertyValue("testValue")); + MessageProviderConfig config = new MessageProviderConfig("test", messageProperties); + assertEquals("Unexpected name", "test", config.getName()); + assertEquals("Unexpected properties", messageProperties, config.getMessageProperties()); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java new file mode 100644 index 0000000000..b9e591f113 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import javax.jms.DeliveryMode; +import javax.jms.Message; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.CreateProducerCommand; + +public class ProducerConfigTest extends TestCase +{ + public void testProducerHasZeroArgConstructorForGson() + { + ProducerConfig p = new ProducerConfig(); + assertNotNull(p); + } + + public void testConfigProvidesJmsDefaults() + { + CreateProducerCommand p = new ProducerConfig().createCommand("session1"); + assertEquals(Message.DEFAULT_DELIVERY_MODE, p.getDeliveryMode()); + assertEquals(Message.DEFAULT_PRIORITY, p.getPriority()); + assertEquals(Message.DEFAULT_TIME_TO_LIVE, p.getTimeToLive()); + } + + public void testCreateProducerCommand() + { + String destination = "url:/destination"; + int messageSize = 1000; + int numberOfMessages = 10; + int priority = 4; + long timeToLive = 10000; + int batchSize = 5; + long interval = 60; + long maximumDuration = 70; + long startDelay = 80; + String providerName = "testProvider1"; + + ProducerConfig producerConfig = new ProducerConfig( + "producer1", + destination, + numberOfMessages, + batchSize, + maximumDuration, + DeliveryMode.NON_PERSISTENT, + messageSize, + priority, + timeToLive, + interval, + startDelay, + providerName); + + CreateProducerCommand command = producerConfig.createCommand("session1"); + + assertEquals("session1", command.getSessionName()); + assertEquals("producer1", command.getParticipantName()); + assertEquals(destination, command.getDestinationName()); + assertEquals(numberOfMessages, command.getNumberOfMessages()); + assertEquals(batchSize, command.getBatchSize()); + assertEquals(maximumDuration, command.getMaximumDuration()); + + assertEquals(DeliveryMode.NON_PERSISTENT, command.getDeliveryMode()); + assertEquals(messageSize, command.getMessageSize()); + assertEquals(priority, command.getPriority()); + assertEquals(timeToLive, command.getTimeToLive()); + assertEquals(interval, command.getInterval()); + assertEquals(startDelay, command.getStartDelay()); + assertEquals(providerName, command.getMessageProviderName()); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java new file mode 100644 index 0000000000..8775e4064d --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import static org.apache.qpid.disttest.controller.config.ConfigTestUtils.assertCommandEquals; +import static org.apache.qpid.disttest.controller.config.ConfigTestUtils.getCommand; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.List; + +import javax.jms.Session; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; + +public class SessionConfigTest extends TestCase +{ + private static final String CONNECTION_NAME = "conn1"; + private static final String SESSION = "session1"; + + public void testSessionHasZeroArgConstructorForGson() + { + SessionConfig s = new SessionConfig(); + assertNotNull(s); + } + + public void testCreateCommandsForSessionAndChildren() + { + SessionConfig sessionConfig = createSessionConfigWithChildCommands(); + + List commands = sessionConfig.createCommands(CONNECTION_NAME); + assertEquals(3, commands.size()); + + assertCommandEquals(commands, 0, CreateSessionCommand.class); + assertCommandEquals(commands, 1, CreateProducerCommand.class); + assertCommandEquals(commands, 2, CreateConsumerCommand.class); + + CreateSessionCommand createSessionCommand = getCommand(commands, 0); + assertEquals(Session.AUTO_ACKNOWLEDGE, createSessionCommand.getAcknowledgeMode()); + assertEquals(SESSION, createSessionCommand.getSessionName()); + assertEquals(CONNECTION_NAME, createSessionCommand.getConnectionName()); + } + + public void testGetTotalNumberOfParticipants() + { + SessionConfig sessionConfig = createSessionConfigWithOneConsumerAndOneProducer(); + assertEquals(2, sessionConfig.getTotalNumberOfParticipants()); + } + + private SessionConfig createSessionConfigWithOneConsumerAndOneProducer() + { + return createSessionConfigWithChildCommands(); + } + + private SessionConfig createSessionConfigWithChildCommands() + { + ProducerConfig producerConfig = mock(ProducerConfig.class); + ConsumerConfig consumerConfig = mock(ConsumerConfig.class); + + when(producerConfig.createCommand(SESSION)).thenReturn(mock(CreateProducerCommand.class)); + when(consumerConfig.createCommand(SESSION)).thenReturn(mock(CreateConsumerCommand.class)); + + return new SessionConfig(SESSION, + Session.AUTO_ACKNOWLEDGE, + Collections.singletonList(consumerConfig), + Collections.singletonList(producerConfig)); + } + + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java new file mode 100644 index 0000000000..1212a57606 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.controller.config; + +import static org.apache.qpid.disttest.controller.config.ConfigTestUtils.assertCommandForClient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.controller.CommandForClient; +import org.apache.qpid.disttest.message.NoOpCommand; + +public class TestConfigTest extends TestCase +{ + private static final QueueConfig[] EMPTY_QUEUES_ARRAY = new QueueConfig[0]; + private static final String CLIENT1 = "client1"; + private static final String CLIENT2 = "client2"; + private static final String TEST1 = "test1"; + + public void testConfigHasZeroArgConstructorForGson() + { + TestConfig c = new TestConfig(); + assertNotNull(c); + } + + public void testCreateCommandsForClient() + { + TestConfig config = createTestConfigWithClientConfigReturningChildCommands(); + + List commandsForClients = config.createCommands(); + assertEquals("Unexpected number of commands for client", 3, commandsForClients.size()); + + assertCommandForClient(commandsForClients, 0, CLIENT1, NoOpCommand.class); + assertCommandForClient(commandsForClients, 1, CLIENT1, NoOpCommand.class); + assertCommandForClient(commandsForClients, 2, CLIENT2, NoOpCommand.class); + } + + public void testGetClientNames() + { + TestConfig config = createTestConfigWithTwoClients(); + + assertEquals(2, config.getClientNames().size()); + } + + public void testGetTotalNumberOfClients() + { + TestConfig config = createTestConfigWithTwoClients(); + assertEquals(2, config.getTotalNumberOfClients()); + } + + public void testGetTotalNumberOfParticipants() + { + TestConfig config = createTestConfigWithTwoClients(); + assertEquals(2, config.getTotalNumberOfParticipants()); + } + + private TestConfig createTestConfigWithClientConfigReturningChildCommands() + { + ClientConfig clientConfig1 = createClientConfigReturningCommands(CLIENT1, 2); + ClientConfig clientConfig2 = createClientConfigReturningCommands(CLIENT2, 1); + + TestConfig config = new TestConfig(TEST1, new ClientConfig[] { clientConfig1, clientConfig2 }, EMPTY_QUEUES_ARRAY); + return config; + } + + private ClientConfig createClientConfigReturningCommands(final String clientName, int numberOfCommands) + { + ClientConfig clientConfig = mock(ClientConfig.class); + + List commandList = new ArrayList(); + + for (int i = 1 ; i <= numberOfCommands; i++) + { + commandList.add(new CommandForClient(clientName, new NoOpCommand())); + } + + when(clientConfig.createCommands()).thenReturn(commandList); + return clientConfig; + } + + private TestConfig createTestConfigWithTwoClients() + { + ClientConfig clientConfig1 = mock(ClientConfig.class); + ClientConfig clientConfig2 = mock(ClientConfig.class); + + when(clientConfig1.getTotalNumberOfParticipants()).thenReturn(1); + when(clientConfig2.getTotalNumberOfParticipants()).thenReturn(1); + + TestConfig config = new TestConfig(TEST1, new ClientConfig[] { clientConfig1, clientConfig2 }, EMPTY_QUEUES_ARRAY); + return config; + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java new file mode 100644 index 0000000000..928fbe58cf --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.controller.config; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.controller.CommandForClient; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.NoOpCommand; + +public class TestInstanceTest extends TestCase +{ + private static final String CLIENT_NAME = "CLIENT_NAME"; + private static final int ITERATION_NUMBER = 0; + + private NoOpCommand _noOpCommand; + private CreateProducerCommand _createProducerCommand; + private CreateConsumerCommand _createConsumerCommand; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _noOpCommand = mock(NoOpCommand.class); + _createProducerCommand = mock(CreateProducerCommand.class); + _createConsumerCommand = mock(CreateConsumerCommand.class); + } + + public void testCreateCommandsWithIterationValues() + { + IterationValue iterationValue = mock(IterationValue.class); + + TestConfig config = createTestConfig(); + + TestInstance testInstance = new TestInstance(config, ITERATION_NUMBER, iterationValue); + + List commandsForClients = testInstance.createCommands(); + assertEquals("Unexpected number of commands for client", 3, commandsForClients.size()); + + verify(iterationValue).applyToCommand(_noOpCommand); + verify(iterationValue).applyToCommand(_createProducerCommand); + verify(iterationValue).applyToCommand(_createConsumerCommand); + } + + public void testCreateCommandsWithoutIterationValues() + { + TestConfig config = createTestConfig(); + TestInstance testInstance = new TestInstance(config); + + List commandsForClients = testInstance.createCommands(); + assertEquals("Unexpected number of commands for client", 3, commandsForClients.size()); + } + + public void testGetConfiguredClientNames() + { + TestConfig testConfig = mock(TestConfig.class); + when(testConfig.getClientNames()).thenReturn(Collections.singletonList(CLIENT_NAME)); + TestInstance testInstance = new TestInstance(testConfig); + + List clientNames = testInstance.getClientNames(); + assertEquals(1, clientNames.size()); + assertEquals(CLIENT_NAME, clientNames.get(0)); + } + + private TestConfig createTestConfig() + { + CommandForClient commandForClient1 = new CommandForClient(CLIENT_NAME, _noOpCommand); + CommandForClient commandForClient2 = new CommandForClient(CLIENT_NAME, _createProducerCommand); + CommandForClient commandForClient3 = new CommandForClient(CLIENT_NAME, _createConsumerCommand); + + TestConfig config = mock(TestConfig.class); + when(config.createCommands()).thenReturn(Arrays.asList(commandForClient1, commandForClient2, commandForClient3)); + + return config; + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/sampleConfig.json b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/sampleConfig.json new file mode 100644 index 0000000000..9e1168129b --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/sampleConfig.json @@ -0,0 +1,72 @@ +{ + "_tests": [ + { + "_name": "Test 1", + "_queues": [ + { + "_name": "Json-Queue-Name", + "_durable": false, + "_attributes": {} + }, + { + "_name": "Json Queue Name 2", + "_durable": true, + "_attributes": { + "x-qpid-priorities": 10.0 + } + } + ], + "_iterations": [ + { + "_messageSize": 100, + "_numberOfMessages": 10 + }, + { + "_messageSize": 200, + "_numberOfMessages": 5 + } + ], + "_clients": [ + { + "_connections": [ + { + "_name": "connection1", + "_sessions": [] + } + ]; + "_messageProviders":[ + { + "_name": "testProvider1"; + "_messageProperties": { + "priority": {"@def": "list"; "_items": [1,2,3,4,4]}; + "id": {"@def": "random"; "_upper": 10}; + "test": "test-value" + } + } + ] + } + ] + }, + { + "_name": "Test 2", + "_queues": [ + { + "_name": "Json-Queue-Name", + "_durable": false, + "_attributes": {} + } + ], + "_iterations": [], + "_clients": [ + { + "_connections": [ + { + "_name": "connection1", + "_sessions": [] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java new file mode 100644 index 0000000000..ab0f52263b --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.jms; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; + +public class JmsMessageAdaptorTest extends TestCase +{ + + public void testCheckAllCommandTypes() + { + for (CommandType commandType : CommandType.values()) + { + Class clazz = JmsMessageAdaptor.getCommandClassFromType(commandType); + assertNotNull(clazz); + + } + + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java new file mode 100644 index 0000000000..4a56fff8fe --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.message; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.qpid.disttest.client.property.ListPropertyValue; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.json.JsonHandler; + +public class JsonHandlerTest extends TestCase +{ + private JsonHandler _jsonHandler = null; + private SendChristmasCards _testCommand = null; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _jsonHandler = new JsonHandler(); + + _testCommand = new SendChristmasCards(CommandType.START_TEST, Collections.singletonMap(SendChristmasCards.CardType.FUNNY, 5)); + _testCommand.persons = Arrays.asList(new Person("Phil"), new Person("Andrew")); + } + + public void testMarshallUnmarshall() throws Exception + { + final String jsonString = _jsonHandler.marshall(_testCommand); + + final SendChristmasCards unmarshalledCommand = _jsonHandler.unmarshall(jsonString, SendChristmasCards.class); + + assertEquals("Unmarshalled command should be equal to the original object", _testCommand, unmarshalledCommand); + } + + public void testGeneratorDesrialization() + { + String json = "{_messageProperties: {test: 1; generator: {'@def': 'list'; _cyclic: false; _items: ['first', " + + "{'@def': 'range'; _upper:10; '_type':'int'}]}}}"; + final TestCommand unmarshalledCommand = _jsonHandler.unmarshall(json, TestCommand.class); + Map properties = unmarshalledCommand.getMessageProperties(); + assertNotNull("Properties should not be null", properties); + assertFalse("Properties should not be empty", properties.isEmpty()); + assertEquals("Unexpected properties size", 2, properties.size()); + PropertyValue testProperty = properties.get("test"); + assertNotNull("Unexpected property test", testProperty); + assertTrue("Unexpected property test", testProperty.getValue() instanceof Number); + assertEquals("Unexpected property value", 1, ((Number)testProperty.getValue()).intValue()); + Object generatorObject = properties.get("generator"); + assertTrue("Unexpected generator object", generatorObject instanceof ListPropertyValue); + PropertyValue generator = (PropertyValue)generatorObject; + assertEquals("Unexpected generator value", "first", generator.getValue()); + for (int i = 0; i < 10; i++) + { + assertEquals("Unexpected generator value", new Integer(i), generator.getValue()); + } + String newJson =_jsonHandler.marshall(unmarshalledCommand); + final TestCommand newUnmarshalledCommand = _jsonHandler.unmarshall(newJson, TestCommand.class); + assertEquals("Unmarshalled command should be equal to the original object", unmarshalledCommand, newUnmarshalledCommand); + } + + /** + * A {@link Command} designed to exercise {@link JsonHandler}, e.g does it handle a map of enums?. + * + * This class is non-private to avoid auto-deletion of "unused" fields/methods + */ + static class SendChristmasCards extends Command + { + enum CardType {FUNNY, TRADITIONAL} + + private Map _cardTypes; + private List persons; + + public SendChristmasCards(final CommandType type, Map cardTypes) + { + super(type); + _cardTypes = cardTypes; + } + + public Map getCardTypes() + { + return _cardTypes; + } + + public List getPersons() + { + return persons; + } + + @Override + public boolean equals(final Object obj) + { + return EqualsBuilder.reflectionEquals(this, obj); + } + } + + /** + * This class is non-private to avoid auto-deletion of "unused" fields/methods + */ + static class Person + { + private String _firstName; + + public Person(final String firstName) + { + _firstName = firstName; + } + + public String getFirstName() + { + return _firstName; + } + + @Override + public boolean equals(final Object obj) + { + return EqualsBuilder.reflectionEquals(this, obj); + } + + } + + /** + * Yet another test class + */ + static class TestCommand extends Command + { + + private Map _messageProperties; + + public TestCommand(CommandType type) + { + super(type); + } + + public Map getMessageProperties() + { + return _messageProperties; + } + + public void setMessageProperties(Map _messageProperties) + { + this._messageProperties = _messageProperties; + } + + @Override + public boolean equals(final Object obj) + { + if (obj == null || !(obj instanceof TestCommand)) + { + return false; + } + TestCommand other = (TestCommand)obj; + if (_messageProperties == null && other._messageProperties != null ) + { + return false; + } + return _messageProperties.equals(other._messageProperties); + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java new file mode 100644 index 0000000000..12731c06f4 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.message; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.*; +import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSIING_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; + +import java.util.Date; + +import javax.jms.DeliveryMode; + +import junit.framework.TestCase; + +public class ParticipantResultTest extends TestCase +{ + + public void testSharedParticipantResultAttributes() throws Exception + { + final String participantName = "PARTICIPANT_NAME1"; + final String testName = "TEST_NAME1"; + String clientConfiguredName = "CLIENT_CONFIGURED_NAME"; + String errorMessage = "errorMessage"; + int iterationNumber = 1; + + ParticipantResult result = new ParticipantResult(); + + long numberOfMessages = 500; + long timeTaken = 30; + int batchSize = 10; + + long startTime = System.currentTimeMillis(); + long endTime = startTime + timeTaken; + long maximumDuration = 1000; + + int totalNumberOfConsumers = 1; + int totalNumberOfProducers = 1; + + int acknowledgeMode = 1; + + result.setParticipantName(participantName); + result.setTestName(testName); + result.setIterationNumber(iterationNumber); + result.setConfiguredClientName(clientConfiguredName); + + result.setAcknowledgeMode(acknowledgeMode); + result.setNumberOfMessagesProcessed(numberOfMessages); + result.setConfiguredClientName(clientConfiguredName); + result.setBatchSize(batchSize); + + result.setStartDate(new Date(startTime)); + result.setEndDate(new Date(endTime)); + result.setMaximumDuration(maximumDuration); + + result.setTotalNumberOfConsumers(totalNumberOfConsumers); + result.setTotalNumberOfProducers(totalNumberOfProducers); + + result.setErrorMessage(errorMessage); + + assertEquals(participantName, result.getAttributes().get(PARTICIPANT_NAME)); + assertEquals(testName, result.getAttributes().get(TEST_NAME)); + assertEquals(iterationNumber, result.getAttributes().get(ITERATION_NUMBER)); + assertEquals(clientConfiguredName, result.getAttributes().get(CONFIGURED_CLIENT_NAME)); + assertEquals(numberOfMessages, result.getAttributes().get(NUMBER_OF_MESSAGES_PROCESSED)); + assertEquals(timeTaken, result.getAttributes().get(TIME_TAKEN)); + assertEquals(timeTaken, result.getAttributes().get(TIME_TAKEN)); + assertEquals(timeTaken, result.getAttributes().get(TIME_TAKEN)); + assertEquals(batchSize, result.getAttributes().get(BATCH_SIZE)); + assertEquals(maximumDuration, result.getAttributes().get(MAXIMUM_DURATION)); + assertEquals(totalNumberOfConsumers, result.getAttributes().get(TOTAL_NUMBER_OF_CONSUMERS)); + assertEquals(totalNumberOfProducers, result.getAttributes().get(TOTAL_NUMBER_OF_PRODUCERS)); + assertEquals(acknowledgeMode, result.getAttributes().get(ACKNOWLEDGE_MODE)); + assertEquals(errorMessage, result.getAttributes().get(ERROR_MESSAGE)); + } + + public void testConsumerParticipantResultAttributes() throws Exception + { + ConsumerParticipantResult result = new ConsumerParticipantResult(); + + boolean topic = true; + boolean durable = true; + boolean browsingSubscription = false; + boolean selector = true; + boolean noLocal = false; + boolean synchronousConsumer = true; + + result.setTopic(topic); + result.setDurableSubscription(durable); + result.setBrowsingSubscription(browsingSubscription); + result.setSelector(selector); + result.setNoLocal(noLocal); + result.setSynchronousConsumer(synchronousConsumer); + + assertEquals(topic, result.getAttributes().get(IS_TOPIC)); + assertEquals(durable, result.getAttributes().get(IS_DURABLE_SUBSCRIPTION)); + assertEquals(browsingSubscription, result.getAttributes().get(IS_BROWSIING_SUBSCRIPTION)); + assertEquals(selector, result.getAttributes().get(IS_SELECTOR)); + assertEquals(noLocal, result.getAttributes().get(IS_NO_LOCAL)); + assertEquals(synchronousConsumer, result.getAttributes().get(IS_SYNCHRONOUS_CONSUMER)); + } + + public void testProducerParticipantResultAttributes() throws Exception + { + ProducerParticipantResult result = new ProducerParticipantResult(); + + int priority = 2; + long timeToLive = 30; + long producerStartDelay = 40; + long producerInterval = 50; + int messageSize = 60; + int deliveryMode = DeliveryMode.PERSISTENT; + + result.setPriority(priority); + result.setTimeToLive(timeToLive); + result.setStartDelay(producerStartDelay); + result.setInterval(producerInterval); + result.setPayloadSize(messageSize); + result.setDeliveryMode(deliveryMode); + + + assertEquals(priority, result.getAttributes().get(PRIORITY)); + assertEquals(timeToLive, result.getAttributes().get(TIME_TO_LIVE)); + assertEquals(producerStartDelay, result.getAttributes().get(PRODUCER_START_DELAY)); + assertEquals(producerInterval, result.getAttributes().get(PRODUCER_INTERVAL)); + assertEquals(messageSize, result.getAttributes().get(PAYLOAD_SIZE)); + assertEquals(deliveryMode, result.getAttributes().get(DELIVERY_MODE)); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java new file mode 100644 index 0000000000..393837b4d5 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.aggregation; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; + +public class AggregatorTest extends TestCase +{ + private Aggregator _aggregator = new Aggregator(); + private TestResultAggregator _testResultAggregator = mock(TestResultAggregator.class); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _aggregator.setTestResultAggregator(_testResultAggregator); + } + + public void testAggregrateManyTestResults() throws Exception + { + ResultsForAllTests resultsForAllTests = mock(ResultsForAllTests.class); + ITestResult testResult1 = mock(ITestResult.class); + ITestResult testResult2 = mock(ITestResult.class); + + when(resultsForAllTests.getTestResults()).thenReturn(Arrays.asList(testResult1, testResult2)); + when(_testResultAggregator.aggregateTestResult(testResult1)).thenReturn(mock(AggregatedTestResult.class)); + when(_testResultAggregator.aggregateTestResult(testResult2)).thenReturn(mock(AggregatedTestResult.class)); + + ResultsForAllTests aggregatedResultsForAllTests = _aggregator.aggregateResults(resultsForAllTests); + assertEquals(2, aggregatedResultsForAllTests.getTestResults().size()); + + verify(_testResultAggregator).aggregateTestResult(testResult1); + verify(_testResultAggregator).aggregateTestResult(testResult2); + + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java new file mode 100644 index 0000000000..72743be1d1 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java @@ -0,0 +1,272 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.results.aggregation; + +import java.util.Date; + +import javax.jms.Session; + +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ParticipantResultAggregator; + +import junit.framework.TestCase; + +public class ParticipantResultAggregatorTest extends TestCase +{ + private ParticipantResultAggregator _aggregator = new ParticipantResultAggregator(ParticipantResult.class, AGGREGATED_RESULT_NAME); + + private static final String TEST_NAME = "TEST_NAME"; + private static final String AGGREGATED_RESULT_NAME = "AGGREGATED_RESULT_NAME"; + private static final int TEST_ITERATION_NUMBER = 1; + + private static final long PARTICIPANT1_STARTDATE = 50; + private static final long PARTICIPANT1_ENDDATE = 20000; + private static final long PARTICIPANT1_TOTAL_PROCESSED = 1024; + + private static final long PARTICIPANT2_STARTDATE = 100; + private static final long PARTICIPANT2_ENDDATE = 21000; + private static final long PARTICIPANT2_TOTAL_PROCESSED = 2048; + + private static final long OVERALL_PROCESSED = PARTICIPANT1_TOTAL_PROCESSED + PARTICIPANT2_TOTAL_PROCESSED; + private static final double OVERALL_TIMETAKEN = PARTICIPANT2_ENDDATE - PARTICIPANT1_STARTDATE; + + private static final double EXPECTED_AGGREGATED_ALL_THROUGHPUT = ((OVERALL_PROCESSED)/1024)/((OVERALL_TIMETAKEN)/1000); + + public void testStartAndEndDateForOneParticipantResult() + { + ParticipantResult result = new ParticipantResult(); + result.setStartDate(new Date(PARTICIPANT1_STARTDATE)); + result.setEndDate(new Date(PARTICIPANT1_ENDDATE)); + + _aggregator.aggregate(result); + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(PARTICIPANT1_STARTDATE, aggregratedResult.getStartInMillis()); + assertEquals(PARTICIPANT1_ENDDATE, aggregratedResult.getEndInMillis()); + } + + public void testStartAndEndDateForTwoParticipantResults() + { + ParticipantResult result1 = new ParticipantResult(); + result1.setStartDate(new Date(PARTICIPANT1_STARTDATE)); + result1.setEndDate(new Date(PARTICIPANT1_ENDDATE)); + + ParticipantResult result2 = new ParticipantResult(); + result2.setStartDate(new Date(PARTICIPANT2_STARTDATE)); + result2.setEndDate(new Date(PARTICIPANT2_ENDDATE)); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(PARTICIPANT1_STARTDATE, aggregratedResult.getStartInMillis()); + assertEquals(PARTICIPANT2_ENDDATE, aggregratedResult.getEndInMillis()); + } + + public void testComputeNumberOfMessagesProcessed() + { + ParticipantResult result1 = new ParticipantResult(); + result1.setNumberOfMessagesProcessed(10); + + ParticipantResult result2 = new ParticipantResult(); + result2.setNumberOfMessagesProcessed(15); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(25, aggregratedResult.getNumberOfMessagesProcessed()); + } + + public void testComputeTotalPayloadProcessed() + { + ParticipantResult result1 = new ParticipantResult(); + result1.setTotalPayloadProcessed(PARTICIPANT1_TOTAL_PROCESSED); + + ParticipantResult result2 = new ParticipantResult(); + result2.setTotalPayloadProcessed(PARTICIPANT2_TOTAL_PROCESSED); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(OVERALL_PROCESSED, aggregratedResult.getTotalPayloadProcessed()); + } + + public void testComputeThroughput() + { + ParticipantResult result1 = new ParticipantResult(); + result1.setStartDate(new Date(PARTICIPANT1_STARTDATE)); + result1.setEndDate(new Date(PARTICIPANT1_ENDDATE)); + result1.setTotalPayloadProcessed(PARTICIPANT1_TOTAL_PROCESSED); + + ParticipantResult result2 = new ParticipantResult(); + result2.setStartDate(new Date(PARTICIPANT2_STARTDATE)); + result2.setEndDate(new Date(PARTICIPANT2_ENDDATE)); + result2.setTotalPayloadProcessed(PARTICIPANT2_TOTAL_PROCESSED); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(EXPECTED_AGGREGATED_ALL_THROUGHPUT, aggregratedResult.getThroughput(), 0.1); + } + + public void testConstantTestNameAndIterationNumberRolledUp() throws Exception + { + ParticipantResult result1 = new ParticipantResult(); + result1.setTestName(TEST_NAME); + result1.setIterationNumber(TEST_ITERATION_NUMBER); + + ParticipantResult result2 = new ParticipantResult(); + result2.setTestName(TEST_NAME); + result2.setIterationNumber(TEST_ITERATION_NUMBER); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(TEST_ITERATION_NUMBER, aggregratedResult.getIterationNumber()); + assertEquals(TEST_NAME, aggregratedResult.getTestName()); + } + + public void testConstantPayloadSizesRolledUp() throws Exception + { + final int payloadSize = 1024; + + ParticipantResult result1 = new ParticipantResult(); + result1.setPayloadSize(payloadSize); + + ParticipantResult result2 = new ParticipantResult(); + result2.setPayloadSize(payloadSize); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(payloadSize, aggregratedResult.getPayloadSize()); + } + + public void testDifferingPayloadSizesNotRolledUp() throws Exception + { + final int payload1Size = 1024; + final int payload2Size = 2048; + + ParticipantResult result1 = new ParticipantResult(); + result1.setPayloadSize(payload1Size); + + ParticipantResult result2 = new ParticipantResult(); + result2.setPayloadSize(payload2Size); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(0, aggregratedResult.getPayloadSize()); + } + + public void testConstantBatchSizesRolledUp() throws Exception + { + final int batchSize = 10; + + ParticipantResult result1 = new ParticipantResult(); + result1.setBatchSize(batchSize); + + ParticipantResult result2 = new ParticipantResult(); + result2.setBatchSize(batchSize); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(batchSize, aggregratedResult.getBatchSize()); + } + + public void testDifferingBatchSizesNotRolledUp() throws Exception + { + final int batch1Size = 10; + final int batch2Size = 20; + + ParticipantResult result1 = new ParticipantResult(); + result1.setBatchSize(batch1Size); + + ParticipantResult result2 = new ParticipantResult(); + result2.setBatchSize(batch2Size); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(0, aggregratedResult.getBatchSize()); + } + + public void testConstantAcknowledgeModesRolledUp() throws Exception + { + ParticipantResult result1 = new ParticipantResult(); + result1.setAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE); + + ParticipantResult result2 = new ParticipantResult(); + result2.setAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(Session.DUPS_OK_ACKNOWLEDGE, aggregratedResult.getAcknowledgeMode()); + } + + public void testDifferingAcknowledgeModesNotRolledUp() throws Exception + { + ParticipantResult result1 = new ParticipantResult(); + result1.setBatchSize(Session.AUTO_ACKNOWLEDGE); + + ParticipantResult result2 = new ParticipantResult(); + result2.setBatchSize(Session.SESSION_TRANSACTED); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(-1, aggregratedResult.getAcknowledgeMode()); + } + + public void testSumNumberOfConsumerAndProducers() throws Exception + { + final int expectedNumberOfProducers = 1; + final int expectedNumberOfConsumers = 2; + + ParticipantResult result1 = new ParticipantResult(); + result1.setTotalNumberOfConsumers(1); + + ParticipantResult result2 = new ParticipantResult(); + result2.setTotalNumberOfConsumers(1); + + ParticipantResult result3 = new ParticipantResult(); + result2.setTotalNumberOfProducers(1); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + _aggregator.aggregate(result3); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(expectedNumberOfConsumers, aggregratedResult.getTotalNumberOfConsumers()); + assertEquals(expectedNumberOfProducers, aggregratedResult.getTotalNumberOfProducers()); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java new file mode 100644 index 0000000000..a803120cc6 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.aggregation; + +import java.util.Date; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.controller.TestResult; +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; +import org.apache.qpid.disttest.results.aggregation.AggregatedTestResult; +import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; + +public class TestResultAggregatorTest extends TestCase +{ + + private static final String TEST1_NAME = "TEST1_NAME"; + private static final int TEST1_ITERATION_NUMBER = 1; + + + private static final String CONSUMER_PARTICIPANT_NAME1 = "CONSUMER_PARTICIPANT_NAME1"; + private static final String CONSUMER_PARTICIPANT_NAME2 = "CONSUMER_PARTICIPANT_NAME2"; + + private static final String PRODUCER_PARTICIPANT_NAME = "PRODUCER_PARTICIPANT_NAME"; + + + private static final long CONSUMER1_STARTDATE = 50; + private static final long CONSUMER1_ENDDATE = 20000; + + private static final long CONSUMER2_STARTDATE = 100; + private static final long CONSUMER2_ENDDATE = 21000; + + private static final long PRODUCER_STARTDATE = 0; + private static final long PRODUCER_ENDDATE = 19000; + + private static final long NUMBER_OF_MESSAGES_PROCESSED_PER_CONSUMER = 50; + private static final long NUMBER_OF_MESSAGES_CONSUMED_IN_TOTAL = NUMBER_OF_MESSAGES_PROCESSED_PER_CONSUMER * 2; + private static final long NUMBER_OF_MESSAGES_PRODUCED = NUMBER_OF_MESSAGES_PROCESSED_PER_CONSUMER * 2; + + private static final int PAYLOAD_SIZE = 1024; + private static final long TOTAL_PAYLOAD_PROCESSED_PER_CONSUMER = NUMBER_OF_MESSAGES_PROCESSED_PER_CONSUMER * PAYLOAD_SIZE; + private static final long TOTAL_PAYLOAD_PRODUCED_IN_TOTAL = TOTAL_PAYLOAD_PROCESSED_PER_CONSUMER * 2; + + private static final int EXPECTED_NUMBER_OF_AGGREGATED_RESULTS = 3; + + private static final int BATCH_SIZE = 3; + + private TestResultAggregator _aggregator = new TestResultAggregator(); + + public void testAggregateResultsForTwoConsumerAndOneProducer() throws Exception + { + TestResult originalTestResult = createResultsFromTest(); + + int numberOfOriginalParticipantResults = originalTestResult.getParticipantResults().size(); + int expectedNumberOfResults = numberOfOriginalParticipantResults + EXPECTED_NUMBER_OF_AGGREGATED_RESULTS; + + AggregatedTestResult aggregatedTestResult = _aggregator.aggregateTestResult(originalTestResult); + + aggregatedTestResult.getAllConsumerParticipantResult().getTotalPayloadProcessed(); + assertEquals(expectedNumberOfResults, aggregatedTestResult.getParticipantResults().size()); + + assertMinimalAggregatedResults( + aggregatedTestResult.getAllConsumerParticipantResult(), + TEST1_NAME, TEST1_ITERATION_NUMBER, + BATCH_SIZE, NUMBER_OF_MESSAGES_CONSUMED_IN_TOTAL, 2, 0); + + assertMinimalAggregatedResults( + aggregatedTestResult.getAllProducerParticipantResult(), + TEST1_NAME, TEST1_ITERATION_NUMBER, + BATCH_SIZE, NUMBER_OF_MESSAGES_PRODUCED, 0, 1); + + assertMinimalAggregatedResults( + aggregatedTestResult.getAllParticipantResult(), + TEST1_NAME, TEST1_ITERATION_NUMBER, + BATCH_SIZE, NUMBER_OF_MESSAGES_CONSUMED_IN_TOTAL, 2, 1); + } + + public void testAggregateResultsWhenParticipantErrored() + { + ParticipantResult failedParticipantResult = new ParticipantResult(); + failedParticipantResult.setParticipantName(PRODUCER_PARTICIPANT_NAME); + failedParticipantResult.setErrorMessage("error"); + TestResult result = new TestResult(TEST1_NAME); + result.addParticipantResult(failedParticipantResult); + + AggregatedTestResult aggregatedTestResult = _aggregator.aggregateTestResult(result); + assertEquals(TestResultAggregator.AGGREGATED_ERROR_MESSAGE, aggregatedTestResult.getAllParticipantResult().getErrorMessage()); + } + + private void assertMinimalAggregatedResults(ParticipantResult result, String expectedTestName, int expectedIterationNumber, int expectedBatchSize, long expectedNumberOfMessagesProcessed, int expectedTotalNumberOfConsumers, int expectedTotalNumberOfProducers) + { + assertEquals("Unexpected test name in " + result.getParticipantName(), expectedTestName, result.getTestName()); + assertEquals("Unexpected iteration number in " + result.getParticipantName(), expectedIterationNumber, result.getIterationNumber()); + assertEquals("Unexpected batch size " + result.getParticipantName(), expectedBatchSize, result.getBatchSize()); + assertEquals("Unexpected number of messages processed in " + result.getParticipantName(), expectedNumberOfMessagesProcessed, result.getNumberOfMessagesProcessed()); + assertEquals("Unexpected total number of consumers " + result.getParticipantName(), expectedTotalNumberOfConsumers, result.getTotalNumberOfConsumers()); + assertEquals("Unexpected total number of producers " + result.getParticipantName(), expectedTotalNumberOfProducers, result.getTotalNumberOfProducers()); + } + + private TestResult createResultsFromTest() + { + TestResult testResult = new TestResult(TEST1_NAME); + + ConsumerParticipantResult consumerResult1 = new ConsumerParticipantResult(); + setPropertiesOn(consumerResult1, TEST1_NAME, TEST1_ITERATION_NUMBER, CONSUMER_PARTICIPANT_NAME1, NUMBER_OF_MESSAGES_PROCESSED_PER_CONSUMER, BATCH_SIZE, PAYLOAD_SIZE, TOTAL_PAYLOAD_PROCESSED_PER_CONSUMER, CONSUMER1_STARTDATE, CONSUMER1_ENDDATE, 1, 0); + testResult.addParticipantResult(consumerResult1); + + ConsumerParticipantResult consumerResult2 = new ConsumerParticipantResult(); + setPropertiesOn(consumerResult2, TEST1_NAME, TEST1_ITERATION_NUMBER, CONSUMER_PARTICIPANT_NAME2, NUMBER_OF_MESSAGES_PROCESSED_PER_CONSUMER, BATCH_SIZE, PAYLOAD_SIZE, TOTAL_PAYLOAD_PROCESSED_PER_CONSUMER, CONSUMER2_STARTDATE, CONSUMER2_ENDDATE, 1, 0); + testResult.addParticipantResult(consumerResult2); + + ParticipantResult producerResult = new ProducerParticipantResult(); + setPropertiesOn(producerResult, TEST1_NAME, TEST1_ITERATION_NUMBER, PRODUCER_PARTICIPANT_NAME, NUMBER_OF_MESSAGES_PRODUCED, BATCH_SIZE, PAYLOAD_SIZE, TOTAL_PAYLOAD_PRODUCED_IN_TOTAL, PRODUCER_STARTDATE, PRODUCER_ENDDATE, 0, 1); + testResult.addParticipantResult(producerResult); + + return testResult; + } + + private void setPropertiesOn(ParticipantResult participantResult, String testName, int iterationNumber, String participantName, long numberOfMessagesProcessed, int batchSize, int payloadSize, long totalPayloadProcessed, long start, long end, int totalNumberOfConsumers, int totalNumberOfProducers) + { + participantResult.setParticipantName(participantName); + participantResult.setTestName(testName); + participantResult.setIterationNumber(iterationNumber); + participantResult.setTotalNumberOfConsumers(totalNumberOfConsumers); + participantResult.setTotalNumberOfProducers(totalNumberOfProducers); + + participantResult.setNumberOfMessagesProcessed(numberOfMessagesProcessed); + participantResult.setPayloadSize(payloadSize); + participantResult.setTotalPayloadProcessed(totalPayloadProcessed); + participantResult.setStartDate(new Date(start)); + participantResult.setEndDate(new Date(end)); + participantResult.setBatchSize(batchSize); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java new file mode 100644 index 0000000000..088746d8cd --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.formatting; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.*; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSIING_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.controller.TestResult; +import org.apache.qpid.disttest.message.ParticipantAttribute; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.qmf.QMFProperty.AccessCode; + +public class CSVFormaterTest extends TestCase +{ + private static final String TEST1 = "TEST1"; + private static final String PARTICIPANT = "PARTICIPANT"; + private static final String CONFIGURED_CLIENT1 = "CONFIGURED_CLIENT1"; + + private CSVFormater _formatter = new CSVFormater(); + + public void testResultsFileWithWithOneRow() throws Exception + { + ParticipantResult participantResult = mock(ParticipantResult.class); + Map participantAttributes = getParticipantAttributes(); + + when(participantResult.getAttributes()).thenReturn(participantAttributes); + when(participantResult.getParticipantName()).thenReturn(PARTICIPANT); + + TestResult testResult = new TestResult(TEST1); + testResult.addParticipantResult(participantResult); + + ResultsForAllTests resultsForAllTests = new ResultsForAllTests(); + resultsForAllTests.add(testResult); + + String output = _formatter.format(resultsForAllTests); + + String expectedOutput = readCsvOutputFileAsString("expectedOutput.csv"); + + assertEquals(expectedOutput, output); + } + + private Map getParticipantAttributes() + { + Map participantAttributes = new HashMap(); + + participantAttributes.put(TEST_NAME, TEST1); + participantAttributes.put(ITERATION_NUMBER, 0); + participantAttributes.put(CONFIGURED_CLIENT_NAME, CONFIGURED_CLIENT1); + participantAttributes.put(PARTICIPANT_NAME, PARTICIPANT); + participantAttributes.put(NUMBER_OF_MESSAGES_PROCESSED, 0); + participantAttributes.put(PAYLOAD_SIZE, 1); + participantAttributes.put(PRIORITY, 2); + participantAttributes.put(TIME_TO_LIVE, 3); + participantAttributes.put(ACKNOWLEDGE_MODE, 4); + participantAttributes.put(DELIVERY_MODE, 5); + participantAttributes.put(BATCH_SIZE, 6); + participantAttributes.put(MAXIMUM_DURATION, 7); + participantAttributes.put(PRODUCER_START_DELAY, 8); + participantAttributes.put(PRODUCER_INTERVAL, 9); + participantAttributes.put(IS_TOPIC, true); + participantAttributes.put(IS_DURABLE_SUBSCRIPTION, false); + participantAttributes.put(IS_BROWSIING_SUBSCRIPTION, true); + participantAttributes.put(IS_SELECTOR, false); + participantAttributes.put(IS_NO_LOCAL, true); + participantAttributes.put(IS_SYNCHRONOUS_CONSUMER, false); + participantAttributes.put(TOTAL_NUMBER_OF_CONSUMERS, 1); + participantAttributes.put(TOTAL_NUMBER_OF_PRODUCERS, 2); + participantAttributes.put(TOTAL_PAYLOAD_PROCESSED, 1024); + participantAttributes.put(THROUGHPUT, 2048); + participantAttributes.put(TIME_TAKEN, 1000); + participantAttributes.put(ERROR_MESSAGE, "error"); + + return participantAttributes; + } + + private String readCsvOutputFileAsString(String filename) throws Exception + { + InputStream is = getClass().getResourceAsStream(filename); + assertNotNull(is); + + StringBuilder output = new StringBuilder(); + + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + while((line = br.readLine()) != null) + { + output.append(line); + output.append("\n"); + } + + return output.toString(); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java new file mode 100644 index 0000000000..6cec4b5245 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.formatting; + + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; +import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; +import org.apache.qpid.disttest.results.formatting.CSVOrderParticipantResultComparator; + +public class CSVOrderParticipantResultComparatorTest extends TestCase +{ + CSVOrderParticipantResultComparator _comparator = new CSVOrderParticipantResultComparator(); + + public void testOrderedConsumerParticipants() throws Exception + { + assertCompare( + new ConsumerParticipantResult("apple"), + new ConsumerParticipantResult("banana")); + + } + public void testProducerPrecedesConsumerParticipants() throws Exception + { + assertCompare( + new ProducerParticipantResult(), + new ConsumerParticipantResult()); + } + + public void testProducerPrecedesAllProducersResult() + { + assertCompare( + new ProducerParticipantResult("participantName"), + new ParticipantResult(TestResultAggregator.ALL_PRODUCER_PARTICIPANTS_NAME)); + } + + public void testConsumerPrecedesAllConsumersResult() + { + assertCompare( + new ConsumerParticipantResult("participantName"), + new ParticipantResult(TestResultAggregator.ALL_CONSUMER_PARTICIPANTS_NAME)); + } + + public void testAllParticipantsPrecedesAllConsumersResult() + { + assertCompare( + new ParticipantResult(TestResultAggregator.ALL_PARTICIPANTS_NAME), + new ParticipantResult(TestResultAggregator.ALL_CONSUMER_PARTICIPANTS_NAME)); + } + + public void testAllParticipantsPrecedesAllProducersResult() + { + assertCompare( + new ParticipantResult(TestResultAggregator.ALL_PARTICIPANTS_NAME), + new ParticipantResult(TestResultAggregator.ALL_PRODUCER_PARTICIPANTS_NAME)); + } + + private void assertCompare(ParticipantResult smaller, ParticipantResult bigger) + { + assertEquals("Expected " + smaller + " to 'equal' itself", + 0, + _comparator.compare(smaller, smaller)); + + String failureMsg = "Expected " + smaller + " to be smaller than " + bigger; + + assertTrue(failureMsg, _comparator.compare(smaller, bigger) < 0); + assertTrue(failureMsg, _comparator.compare(bigger, smaller) > 0); + } + +} +// diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv new file mode 100644 index 0000000000..cfffb1e549 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv @@ -0,0 +1,2 @@ +testName,iterationNumber,clientName,participantName,numberOfMessages,payloadSizeB,priority,timeToLiveMs,acknowledgeMode,deliveryMode,batchSize,maximumDurationMs,producerStartDelayMs,producerIntervalMs,isTopic,isDurableSubscription,isBrowsingSubscription,isSelector,isNoLocal,isSynchronousConsumer,totalNumberOfConsumers,totalNumberOfProducers,totalPayloadProcessedB,throughputKbPerS,timeTakenMs,errorMessage +TEST1,0,CONFIGURED_CLIENT1,PARTICIPANT,0,1,2,3,4,5,6,7,8,9,true,false,true,false,true,false,1,2,1024,2048,1000,error \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/DistributedTestSystemTestBase.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/DistributedTestSystemTestBase.java new file mode 100644 index 0000000000..96daf64526 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/DistributedTestSystemTestBase.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.disttest; + +import java.util.Properties; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class DistributedTestSystemTestBase extends QpidBrokerTestCase +{ + protected Context _context; + + protected Connection _connection; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + final Properties properties = new Properties(); + properties.load(DistributedTestSystemTestBase.class.getResourceAsStream("perftests.systests.properties")); + _context = new InitialContext(properties); + + _connection = getConnection(); + _connection.start(); + } + + @Override + protected void tearDown() throws Exception + { + // no need to close connections - this is done by superclass + + super.tearDown(); + } + + public Context getContext() + { + return _context; + } + + @Override + public Connection getConnection() throws JMSException, NamingException + { + final ConnectionFactory connectionFactory = (ConnectionFactory) _context.lookup("connectionfactory"); + final Connection connection = connectionFactory.createConnection(); + _connections.add(connection); + return connection; + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java new file mode 100644 index 0000000000..784e43469e --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.disttest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.Session; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.disttest.controller.config.QueueConfig; +import org.apache.qpid.disttest.jms.QpidQueueCreator; + +public class QpidQueueCreatorTest extends DistributedTestSystemTestBase +{ + private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); + + private QpidQueueCreator _creator; + private Session _session; + private List _configs; + private String _queueName; + + @Override + public void setUp() throws Exception + { + super.setUp(); + Connection connection = getConnection(); + _session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _creator = new QpidQueueCreator(); + _configs = new ArrayList(); + _queueName = "direct://amq.direct//" + getTestQueueName(); + } + + public void testCreateQueueWithoutAttributes() throws Exception + { + _configs.add(new QueueConfig(_queueName, true, EMPTY_ATTRIBUTES)); + + assertQueueBound(_queueName, false); + + _creator.createQueues(_session, _configs); + + assertQueueBound(_queueName, true); + } + + public void testCreateWithAttributes() throws Exception + { + Map attributes = new HashMap(); + attributes.put("x-qpid-priorities", Integer.valueOf(5)); + _configs.add(new QueueConfig(_queueName, true, attributes)); + + assertQueueBound(_queueName, false); + + _creator.createQueues(_session, _configs); + + assertQueueBound(_queueName, true); + } + + public void testDeleteQueues() throws Exception + { + _configs.add(new QueueConfig(_queueName, true, EMPTY_ATTRIBUTES)); + + assertQueueBound(_queueName, false); + + _creator.createQueues(_session, _configs); + assertQueueBound(_queueName, true); + + _creator.deleteQueues(_session, _configs); + assertQueueBound(_queueName, false); + } + + public void testDeleteQueueThatDoesNotExist() throws Exception + { + String queueThatDoesNotExist = _queueName; + List configs = new ArrayList(); + Map attributes = Collections.emptyMap(); + configs.add(new QueueConfig(queueThatDoesNotExist, true, attributes)); + + try + { + _creator.deleteQueues(_session, configs); + fail("Exception not thrown"); + } + catch (DistributedTestException e) + { + // PASS + } + } + + private void assertQueueBound(String queueName, boolean isBound) throws Exception + { + AMQDestination destination = (AMQDestination)_session.createQueue(queueName); + assertEquals("Queue is not in expected bound state", isBound, ((AMQSession)_session).isQueueBound(destination)); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java new file mode 100644 index 0000000000..808b428bc9 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.disttest; + +public abstract class SystemTestConstants +{ + public static final long REGISTRATION_TIMEOUT = 5000; + public static final long COMMAND_RESPONSE_TIMEOUT = 10000; + public static final long TEST_RESULT_TIMEOUT = 5000; + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/BasicDistributedClientTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/BasicDistributedClientTest.java new file mode 100644 index 0000000000..d599bdc5c4 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/BasicDistributedClientTest.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.disttest.clientonly; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.client.ClientState; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.jms.JmsMessageAdaptor; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StopClientCommand; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; + +public class BasicDistributedClientTest extends DistributedTestSystemTestBase +{ + private Session _session = null; + private MessageProducer _clientQueueProducer; + private Client _client; + private ControllerQueue _controllerQueue; + private ClientJmsDelegate _clientJmsDelegate = null; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _controllerQueue = new ControllerQueue(_connection, _context); + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + _clientJmsDelegate = new ClientJmsDelegate(_context); + _client = new Client(_clientJmsDelegate); + _client.start(); + } + + @Override + protected void tearDown() throws Exception + { + try + { + _controllerQueue.close(); + if (_session != null) + { + _session.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testClientSendsRegistrationMessage() throws Exception + { + final RegisterClientCommand regClientCommand = _controllerQueue.getNext(); + + assertNotNull("Client must have a non-null name", regClientCommand.getClientName()); + assertEquals("Unexpected client name", _clientJmsDelegate.getClientName(), regClientCommand.getClientName()); + assertNotNull("Client queue name should not be null", regClientCommand.getClientQueueName()); + } + + public void testClientSendsCommandResponses() throws Exception + { + final RegisterClientCommand registrationCommand = _controllerQueue.getNext(); + createClientQueueProducer(registrationCommand); + + sendCommandToClient(new NoOpCommand()); + + final Response responseCommand = _controllerQueue.getNext(); + assertEquals("Incorrect client message type", CommandType.RESPONSE, responseCommand.getType()); + } + + public void testClientCanBeStoppedViaCommand() throws Exception + { + assertEquals("Expected client to be in STARTED state", ClientState.READY, _client.getState()); + + final RegisterClientCommand registrationCommand = _controllerQueue.getNext(); + createClientQueueProducer(registrationCommand); + + final Command stopClientCommand = new StopClientCommand(); + sendCommandToClient(stopClientCommand); + + _client.waitUntilStopped(1000); + + Response response = _controllerQueue.getNext(); + assertNotNull(response); + assertFalse("response shouldn't contain error", response.hasError()); + + assertEquals("Expected client to be in STOPPED state", ClientState.STOPPED, _client.getState()); + } + + public void testClientCanCreateTestConnection() throws Exception + { + assertEquals("Unexpected number of test connections", 0, _clientJmsDelegate.getNoOfTestConnections()); + + final RegisterClientCommand registration = _controllerQueue.getNext(); + createClientQueueProducer(registration); + + final CreateConnectionCommand createConnectionCommand = new CreateConnectionCommand(); + createConnectionCommand.setConnectionName("newTestConnection"); + createConnectionCommand.setConnectionFactoryName("connectionfactory"); + + sendCommandToClient(createConnectionCommand); + Response response = _controllerQueue.getNext(); + + assertFalse("Response message should not have indicated an error", response.hasError()); + assertEquals("Unexpected number of test connections", 1, _clientJmsDelegate.getNoOfTestConnections()); + } + + public void testClientCanCreateTestSession() throws Exception + { + assertEquals("Unexpected number of test sessions", 0, _clientJmsDelegate.getNoOfTestSessions()); + + final RegisterClientCommand registration = _controllerQueue.getNext(); + createClientQueueProducer(registration); + + final CreateConnectionCommand createConnectionCommand = new CreateConnectionCommand(); + createConnectionCommand.setConnectionName("newTestConnection"); + createConnectionCommand.setConnectionFactoryName("connectionfactory"); + + sendCommandToClient(createConnectionCommand); + Response response = _controllerQueue.getNext(); + assertFalse("Response message should not have indicated an error", response.hasError()); + + final CreateSessionCommand createSessionCommand = new CreateSessionCommand(); + createSessionCommand.setConnectionName("newTestConnection"); + createSessionCommand.setSessionName("newTestSession"); + createSessionCommand.setAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); + + sendCommandToClient(createSessionCommand); + response = _controllerQueue.getNext(); + + assertFalse("Response message should not have indicated an error", response.hasError()); + assertEquals("Unexpected number of test sessions", 1, _clientJmsDelegate.getNoOfTestSessions()); + } + + private void sendCommandToClient(final Command command) throws JMSException + { + final Message message = JmsMessageAdaptor.commandToMessage(_session, command); + _clientQueueProducer.send(message); + } + + private void createClientQueueProducer( + final RegisterClientCommand registration) throws JMSException + { + final Destination clientCommandQueue = createDestinationFromRegistration(registration); + _clientQueueProducer = _session.createProducer(clientCommandQueue); + } + + private Queue createDestinationFromRegistration( + final RegisterClientCommand registrationCommand) + throws JMSException + { + String clientQueueName = registrationCommand.getClientQueueName(); + assertNotNull("Null client queue in register message", clientQueueName); + return _session.createQueue(clientQueueName); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ConsumerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ConsumerParticipantTest.java new file mode 100644 index 0000000000..a3c0430865 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ConsumerParticipantTest.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.disttest.clientonly; + +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; + +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.client.ConsumerParticipant; +import org.apache.qpid.disttest.client.ParticipantExecutor; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; +import org.apache.qpid.systest.disttest.clientonly.ProducerParticipantTest.TestClientJmsDelegate; + +public class ConsumerParticipantTest extends DistributedTestSystemTestBase +{ + private MessageProducer _producer; + private Session _session; + private TestClientJmsDelegate _delegate; + private Client _client; + private ControllerQueue _controllerQueue; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _controllerQueue = new ControllerQueue(_connection, _context); + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _producer = _session.createProducer(getTestQueue()); + + _delegate = new TestClientJmsDelegate(getContext()); + _client = new Client(_delegate); + } + + + @Override + protected void tearDown() throws Exception + { + _controllerQueue.close(); + super.tearDown(); + } + + public void testConsumeNumberOfMessagesSynchronously() throws Exception + { + runTest(Session.AUTO_ACKNOWLEDGE, 10, 0, true); + } + + public void testConsumeNumberOfMessagesAsynchronously() throws Exception + { + runTest(Session.AUTO_ACKNOWLEDGE, 10, 0, false); + } + + public void testSelectors() throws Exception + { + final CreateConsumerCommand command = new CreateConsumerCommand(); + command.setNumberOfMessages(10); + command.setSessionName("testSession"); + command.setDestinationName(getTestQueueName()); + command.setSelector("id=1"); + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + _delegate.addConnection("name-does-not-matter", _connection); + _delegate.addSession(command.getSessionName(), session); + + ConsumerParticipant consumerParticipant = new ConsumerParticipant(_delegate, command); + _delegate.createConsumer(command); + + for (int i = 0; i < 20; i++) + { + Message message = _session.createMessage(); + if (i % 2 == 0) + { + message.setIntProperty("id", 0); + } + else + { + message.setIntProperty("id", 1); + } + _producer.send(message); + } + + new ParticipantExecutor(consumerParticipant).start(_client); + + ParticipantResult results = _controllerQueue.getNext(); + assertNotNull("No results message recieved", results); + assertEquals("Unexpected number of messages received", 10, results.getNumberOfMessagesProcessed()); + + Session testQueueConsumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + final MessageConsumer testQueueConsumer = testQueueConsumerSession.createConsumer(getTestQueue()); + for (int i = 0; i < 10; i++) + { + Message message = testQueueConsumer.receive(2000); + assertNotNull("Message is not received: " + message, message); + assertEquals("Unexpected id value", 0, message.getIntProperty("id")); + } + Message message = testQueueConsumer.receive(2000); + assertNull("Unexpected message remaining on test queue: " + message, message); + + _connection.stop(); + } + + protected void runTest(int acknowledgeMode, int numberOfMessages, int batchSize, boolean synchronous) throws Exception + { + final CreateConsumerCommand command = new CreateConsumerCommand(); + command.setNumberOfMessages(numberOfMessages); + command.setBatchSize(batchSize); + command.setSessionName("testSession"); + command.setDestinationName(getTestQueueName()); + command.setSynchronous(synchronous); + + Session session = _connection.createSession(Session.SESSION_TRANSACTED == acknowledgeMode, acknowledgeMode); + + _delegate.addConnection("name-does-not-matter", _connection); + _delegate.addSession(command.getSessionName(), session); + + ConsumerParticipant consumerParticipant = new ConsumerParticipant(_delegate, command); + _delegate.createConsumer(command); + + for (int i = 0; i < numberOfMessages; i++) + { + _producer.send(_session.createMessage()); + } + + new ParticipantExecutor(consumerParticipant).start(_client); + + ParticipantResult results = _controllerQueue.getNext(); + assertNotNull("No results message recieved", results); + + Session testQueueConsumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + final MessageConsumer testQueueConsumer = testQueueConsumerSession.createConsumer(getTestQueue()); + Message message = testQueueConsumer.receive(2000); + assertNull("Unexpected message remaining on test queue: " + message, message); + + _connection.stop(); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java new file mode 100644 index 0000000000..7f0c23eb38 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java @@ -0,0 +1,90 @@ +package org.apache.qpid.systest.disttest.clientonly; + +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Session; +import javax.naming.Context; + +import junit.framework.Assert; + +import org.apache.qpid.disttest.DistributedTestConstants; +import org.apache.qpid.disttest.jms.JmsMessageAdaptor; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; + +/** + * Helper for unit tests to simplify access to the Controller Queue. + * + * Implicitly creates the queue, so you must create a {@link ControllerQueue} object before + * trying to use the underlying queue. + */ +public class ControllerQueue +{ + private MessageConsumer _controllerQueueMessageConsumer; + private Session _controllerQueueSession; + + /** + * Implicitly creates the queue, so you must create a {@link ControllerQueue} object before + * trying to use the underlying queue. + * + * @param context used for looking up the controller queue {@link Destination} + */ + public ControllerQueue(Connection connection, Context context) throws Exception + { + _controllerQueueSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination controllerQueue = (Destination) context.lookup(DistributedTestConstants.CONTROLLER_QUEUE_JNDI_NAME); + _controllerQueueMessageConsumer = _controllerQueueSession.createConsumer(controllerQueue); + } + + public T getNext(long timeout) throws JMSException + { + final Message message = _controllerQueueMessageConsumer.receive(timeout); + if(message == null) + { + return null; + } + + return (T) JmsMessageAdaptor.messageToCommand(message); + } + + public void addNextResponse(Map responses) throws JMSException + { + Command nextResponse = getNext(); + responses.put(nextResponse.getType(), nextResponse); + } + + @SuppressWarnings("unchecked") + public T getNext() throws JMSException + { + return (T)getNext(true); + } + + public T getNext(boolean assertMessageExists) throws JMSException + { + final Message message = _controllerQueueMessageConsumer.receive(1000); + if(assertMessageExists) + { + Assert.assertNotNull("No message received from control queue", message); + } + + if(message == null) + { + return null; + } + + T command = (T) JmsMessageAdaptor.messageToCommand(message); + + return command; + } + + public void close() throws Exception + { + _controllerQueueMessageConsumer.close(); + _controllerQueueSession.close(); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java new file mode 100644 index 0000000000..4a872a7ee2 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java @@ -0,0 +1,323 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.disttest.clientonly; + +import static org.apache.qpid.disttest.client.ClientState.READY; +import static org.apache.qpid.disttest.client.ClientState.RUNNING_TEST; + +import java.util.HashMap; +import java.util.Map; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.client.ClientState; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.jms.JmsMessageAdaptor; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.disttest.message.CreateConnectionCommand; +import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.disttest.message.StartTestCommand; +import org.apache.qpid.disttest.message.TearDownTestCommand; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; + +public class DistributedClientTest extends DistributedTestSystemTestBase +{ + private static final String TEST_CONSUMER = "newTestConsumer"; + private static final String TEST_DESTINATION = "newDestination"; + private static final String TEST_PRODUCER_NAME = "newTestProducer"; + private static final String TEST_SESSION_NAME = "newTestSession"; + private static final String TEST_CONNECTION_NAME = "newTestConnection"; + + private Session _session = null; + private MessageProducer _clientQueueProducer; + private Client _client; + private ControllerQueue _controllerQueue; + protected ClientJmsDelegate _clientJmsDelegate; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _controllerQueue = new ControllerQueue(_connection, _context); + + _clientJmsDelegate = new ClientJmsDelegate(_context); + _client = new Client(_clientJmsDelegate); + _client.start(); + + final RegisterClientCommand registrationCommand = _controllerQueue.getNext(); + createClientQueueProducer(registrationCommand); + + createTestConnection(TEST_CONNECTION_NAME); + createTestSession(TEST_CONNECTION_NAME, TEST_SESSION_NAME); + + assertEquals("Expected no test producers at start of test", 0, _clientJmsDelegate.getNoOfTestProducers()); + assertEquals("Expected no test consumers at start of test", 0, _clientJmsDelegate.getNoOfTestConsumers()); + } + + @Override + protected void tearDown() throws Exception + { + try + { + _controllerQueue.close(); + if (_session != null) + { + _session.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testClientCanCreateTestProducer() throws Exception + { + assertEquals("Should initially have zero producers", 0, _clientJmsDelegate.getNoOfTestProducers()); + + createTestProducer(TEST_SESSION_NAME, TEST_PRODUCER_NAME, TEST_DESTINATION); + + assertEquals("Should now have one test producer", 1, _clientJmsDelegate.getNoOfTestProducers()); + } + + public void testClientCanCreateTestConsumer() throws Exception + { + assertEquals("Should initially have no test consumers", 0, _clientJmsDelegate.getNoOfTestConsumers()); + + createTestConsumer(TEST_SESSION_NAME, TEST_CONSUMER, TEST_DESTINATION); + + assertEquals("Should now have one test consumer", 1, _clientJmsDelegate.getNoOfTestConsumers()); + } + + public void testClientFailsToCreateSessionUsingInvalidConnection() throws Exception + { + int initialNoOfTestSessions = _clientJmsDelegate.getNoOfTestSessions(); + + createTestSession("nonExistentConnection", TEST_SESSION_NAME, false /* shouldSucceed */); + + assertEquals("Number of test sessions should not have changed", initialNoOfTestSessions, _clientJmsDelegate.getNoOfTestSessions()); + } + + public void testClientFailsToCreateProducerUsingInvalidSession() throws Exception + { + int initialNoOfTestProducers = _clientJmsDelegate.getNoOfTestProducers(); + + createTestProducer("invalidSessionName", TEST_PRODUCER_NAME, TEST_DESTINATION, false /* shouldSucceed */); + + assertEquals("Number of test producers should not have changed", initialNoOfTestProducers, _clientJmsDelegate.getNoOfTestProducers()); + } + + public void testClientFailsToCreateConsumerUsingInvalidSession() throws Exception + { + int initialNoOfTestConsumers = _clientJmsDelegate.getNoOfTestConsumers(); + + createTestConsumer("invalidSessionName", TEST_CONSUMER, TEST_DESTINATION, false /* shouldSucceed */); + + assertEquals("Number of test consumers should not have changed", initialNoOfTestConsumers, _clientJmsDelegate.getNoOfTestConsumers()); + } + + public void testClientCanStartPerformingTests() throws Exception + { + createTestProducer(TEST_SESSION_NAME, TEST_PRODUCER_NAME, TEST_DESTINATION); + + sendCommandToClient(new StartTestCommand()); + + validateStartTestResponseAndParticipantResults(CommandType.PRODUCER_PARTICIPANT_RESULT); + + assertState(_client, RUNNING_TEST); + } + + public void testParticipantsSendResults() throws JMSException + { + createTestProducer(TEST_SESSION_NAME, TEST_PRODUCER_NAME, TEST_DESTINATION); + + sendCommandToClient(new StartTestCommand()); + + validateStartTestResponseAndParticipantResults(CommandType.PRODUCER_PARTICIPANT_RESULT); + } + + /** + * Need to validate both of these responses together because their order is non-deterministic + * @param expectedParticipantResultCommandType TODO + */ + private void validateStartTestResponseAndParticipantResults(CommandType expectedParticipantResultCommandType) throws JMSException + { + Map responses = new HashMap(); + _controllerQueue.addNextResponse(responses); + _controllerQueue.addNextResponse(responses); + + ParticipantResult results = (ParticipantResult) responses.get(expectedParticipantResultCommandType); + validateResponse(null, results, true); + + Response startTestResponse = (Response) responses.get(CommandType.RESPONSE); + validateResponse(CommandType.START_TEST, startTestResponse, true); + } + + public void testClientCannotStartPerformingTestsInNonReadyState() throws Exception + { + assertState(_client, READY); + sendCommandAndValidateResponse(new StartTestCommand(), true); + assertState(_client, RUNNING_TEST); + + // Send another start test command + sendCommandAndValidateResponse(new StartTestCommand(), false /*should reject duplicate start command*/); + assertState(_client, RUNNING_TEST); + } + + public void testNonRunningClientIsUnaffectedByStopTestCommand() throws Exception + { + assertState(_client, READY); + + sendCommandAndValidateResponse(new TearDownTestCommand(), false); + + assertState(_client, READY); + } + + private void sendCommandToClient(final Command command) throws JMSException + { + final Message message = JmsMessageAdaptor.commandToMessage(_session, command); + _clientQueueProducer.send(message); + } + + private void sendCommandAndValidateResponse(final Command command, boolean shouldSucceed) throws JMSException + { + sendCommandToClient(command); + Response response = _controllerQueue.getNext(); + validateResponse(command.getType(), response, shouldSucceed); + } + + private void sendCommandAndValidateResponse(final Command command) throws JMSException + { + sendCommandAndValidateResponse(command, true); + } + + private void createTestConnection(String connectionName) throws Exception + { + int initialNumberOfConnections = _clientJmsDelegate.getNoOfTestConnections(); + + final CreateConnectionCommand createConnectionCommand = new CreateConnectionCommand(); + createConnectionCommand.setConnectionName(connectionName); + createConnectionCommand.setConnectionFactoryName("connectionfactory"); + + sendCommandAndValidateResponse(createConnectionCommand); + + int expectedNumberOfConnections = initialNumberOfConnections + 1; + + assertEquals("unexpected number of test connections", expectedNumberOfConnections, _clientJmsDelegate.getNoOfTestConnections()); + } + + private void createTestSession(String connectionName, String sessionName, boolean shouldSucceed) throws Exception + { + int initialNumberOfSessions = _clientJmsDelegate.getNoOfTestSessions(); + + final CreateSessionCommand createSessionCommand = new CreateSessionCommand(); + createSessionCommand.setConnectionName(connectionName); + createSessionCommand.setSessionName(sessionName); + createSessionCommand.setAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); + + sendCommandAndValidateResponse(createSessionCommand, shouldSucceed); + + int expectedNumberOfSessions = initialNumberOfSessions + (shouldSucceed ? 1 : 0); + + assertEquals("unexpected number of test sessions", expectedNumberOfSessions, _clientJmsDelegate.getNoOfTestSessions()); + } + + private void createTestSession(String connectionName, String sessionName) throws Exception + { + createTestSession(connectionName, sessionName, true); + } + + private void createTestProducer(String sessionName, String producerName, String destinationName, boolean shouldSucceed) throws JMSException + { + final CreateProducerCommand createProducerCommand = new CreateProducerCommand(); + createProducerCommand.setParticipantName(producerName); + createProducerCommand.setSessionName(sessionName); + createProducerCommand.setDestinationName(destinationName); + createProducerCommand.setNumberOfMessages(100); + + sendCommandAndValidateResponse(createProducerCommand, shouldSucceed); + } + + private void createTestProducer(String sessionName, String producerName, String destinationName) throws JMSException + { + createTestProducer(sessionName, producerName, destinationName, true); + } + + private void createTestConsumer(String sessionName, String consumerName, String destinationName, boolean shouldSucceed) throws JMSException + { + final CreateConsumerCommand createConsumerCommand = new CreateConsumerCommand(); + createConsumerCommand.setSessionName(sessionName); + createConsumerCommand.setDestinationName(destinationName); + createConsumerCommand.setParticipantName(consumerName); + createConsumerCommand.setNumberOfMessages(1); + + sendCommandAndValidateResponse(createConsumerCommand, shouldSucceed); + } + + private void createTestConsumer(String sessionName, String consumerName, String destinationName) throws JMSException + { + createTestConsumer(sessionName, consumerName, destinationName, true); + } + + private void validateResponse(CommandType originatingCommandType, Response response, boolean shouldSucceed) throws JMSException + { + assertEquals("Response is a reply to the wrong command: " + response, + originatingCommandType, + response.getInReplyToCommandType()); + + boolean shouldHaveError = !shouldSucceed; + assertEquals("Response message " + response + " should have indicated hasError=" + shouldHaveError, + shouldHaveError, + response.hasError()); + } + + private void createClientQueueProducer(final RegisterClientCommand registration) throws JMSException + { + final Destination clientCommandQueue = createDestinationFromRegistration(registration); + _clientQueueProducer = _session.createProducer(clientCommandQueue); + } + + private Queue createDestinationFromRegistration(final RegisterClientCommand registrationCommand) throws JMSException + { + String clientQueueName = registrationCommand.getClientQueueName(); + assertNotNull("Null client queue in register message", clientQueueName); + return _session.createQueue(clientQueueName); + } + + private static void assertState(Client client, ClientState expectedState) + { + ClientState clientState = client.getState(); + assertEquals("Client should be in state: " + expectedState + " but is in state " + clientState, expectedState, clientState); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/MessageProviderTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/MessageProviderTest.java new file mode 100644 index 0000000000..dcbff6518b --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/MessageProviderTest.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.disttest.clientonly; + +import java.util.HashMap; +import java.util.Map; + +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.qpid.disttest.client.MessageProvider; +import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.disttest.client.property.SimplePropertyValue; +import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; +import org.apache.qpid.systest.disttest.clientonly.ProducerParticipantTest.TestClientJmsDelegate; + +public class MessageProviderTest extends DistributedTestSystemTestBase +{ + private MessageConsumer _consumer; + private Session _session; + private TestClientJmsDelegate _delegate; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _consumer = _session.createConsumer(getTestQueue()); + _delegate = new TestClientJmsDelegate(getContext()); + } + + public void testMessageSize() throws Exception + { + runSizeTest(0); + runSizeTest(5); + runSizeTest(512); + } + + public void runSizeTest(int size) throws Exception + { + CreateProducerCommand command = new CreateProducerCommand(); + command.setMessageSize(size); + MessageProvider messageProvider = new MessageProvider(null); + Message message = messageProvider.nextMessage(_session, command); + assertNotNull("Message is not generated", message); + assertTrue("Wrong message type", message instanceof TextMessage); + TextMessage textMessage = (TextMessage)message; + String text = textMessage.getText(); + assertNotNull("Message payload is not generated", text); + assertEquals("Message payload size is incorrect", size, text.length()); + } + + public void testCreateMessageProviderAndSendMessage() throws Exception + { + final CreateMessageProviderCommand messageProviderCommand = new CreateMessageProviderCommand(); + messageProviderCommand.setProviderName("test1"); + Map messageProperties = new HashMap(); + messageProperties.put("test", new SimplePropertyValue("testValue")); + messageProperties.put("priority", new SimplePropertyValue(new Integer(9))); + messageProviderCommand.setMessageProperties(messageProperties); + _delegate.createMessageProvider(messageProviderCommand); + + final CreateProducerCommand producerCommand = new CreateProducerCommand(); + producerCommand.setNumberOfMessages(1); + producerCommand.setDeliveryMode(DeliveryMode.PERSISTENT); + producerCommand.setPriority(6); + producerCommand.setParticipantName("test"); + producerCommand.setMessageSize(10); + producerCommand.setSessionName("testSession"); + producerCommand.setDestinationName(getTestQueueName()); + producerCommand.setMessageProviderName(messageProviderCommand.getProviderName()); + + Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); + _delegate.addConnection("name-does-not-matter", _connection); + _delegate.addSession(producerCommand.getSessionName(), session); + _delegate.createProducer(producerCommand); + + Message message = _delegate.sendNextMessage(producerCommand); + session.commit(); + assertMessage(message); + + _connection.start(); + Message receivedMessage = _consumer.receive(1000l); + assertMessage(receivedMessage); + } + + protected void assertMessage(Message message) throws JMSException + { + assertNotNull("Message should not be null", message); + assertEquals("Unexpected test property", "testValue", message.getStringProperty("test")); + assertEquals("Unexpected priority property", 9, message.getJMSPriority()); + assertTrue("Unexpected message type", message instanceof TextMessage); + String text = ((TextMessage)message).getText(); + assertNotNull("Message text should not be null", text); + assertNotNull("Unexpected message size ", text.length()); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ProducerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ProducerParticipantTest.java new file mode 100644 index 0000000000..54bb9efa98 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ProducerParticipantTest.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.disttest.clientonly; + +import javax.jms.Connection; +import javax.jms.DeliveryMode; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.Context; + +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.client.ParticipantExecutor; +import org.apache.qpid.disttest.client.ProducerParticipant; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; + +public class ProducerParticipantTest extends DistributedTestSystemTestBase +{ + private MessageConsumer _consumer; + private TestClientJmsDelegate _delegate; + private Client _client; + private ControllerQueue _controllerQueue; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _controllerQueue = new ControllerQueue(_connection, _context); + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _consumer = session.createConsumer(getTestQueue()); + + _delegate = new TestClientJmsDelegate(getContext()); + _client = new Client(_delegate); + } + + + + @Override + protected void tearDown() throws Exception + { + _controllerQueue.close(); + super.tearDown(); + } + + + + public void testProduceNumberOfMessages() throws Exception + { + runTest(Session.AUTO_ACKNOWLEDGE, 100, 10, 0, 0); + } + + protected void runTest(int acknowledgeMode, int messageSize, int numberOfMessages, int batchSize, long publishInterval) throws Exception + { + final CreateProducerCommand command = new CreateProducerCommand(); + command.setNumberOfMessages(numberOfMessages); + command.setDeliveryMode(DeliveryMode.PERSISTENT); + command.setParticipantName("test"); + command.setMessageSize(messageSize); + command.setBatchSize(batchSize); + command.setInterval(publishInterval); + command.setSessionName("testSession"); + command.setDestinationName(getTestQueueName()); + + Session session = _connection.createSession(Session.SESSION_TRANSACTED == acknowledgeMode, acknowledgeMode); + + _delegate.addConnection("name-does-not-matter", _connection); + _delegate.addSession(command.getSessionName(), session); + _delegate.createProducer(command); + + final ProducerParticipant producer = new ProducerParticipant(_delegate, command); + + new ParticipantExecutor(producer).start(_client); + + _connection.start(); + for (int i = 0; i < numberOfMessages; i++) + { + final Message m = _consumer.receive(1000l); + assertNotNull("Expected message [" + i + "] is not received", m); + assertTrue("Unexpected message", m instanceof TextMessage); + } + Message m = _consumer.receive(500l); + assertNull("Unexpected message", m); + + ParticipantResult results = _controllerQueue.getNext(); + + assertNotNull("no results", results); + assertFalse(results.getStartInMillis() == 0); + assertFalse(results.getEndInMillis() == 0); + } + + static class TestClientJmsDelegate extends ClientJmsDelegate + { + + public TestClientJmsDelegate(Context context) + { + super(context); + } + + @Override + public void addSession(final String sessionName, final Session newSession) + { + super.addSession(sessionName, newSession); + } + + @Override + public void addConnection(final String connectionName, final Connection newConnection) + { + super.addConnection(connectionName, newConnection); + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java new file mode 100644 index 0000000000..9fd90d3215 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.disttest.controllerandclient; + +import static org.apache.qpid.systest.disttest.SystemTestConstants.COMMAND_RESPONSE_TIMEOUT; +import static org.apache.qpid.systest.disttest.SystemTestConstants.REGISTRATION_TIMEOUT; +import static org.apache.qpid.systest.disttest.SystemTestConstants.TEST_RESULT_TIMEOUT; + +import java.util.List; + +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.naming.NamingException; + +import org.apache.qpid.disttest.ConfigFileHelper; +import org.apache.qpid.disttest.client.Client; +import org.apache.qpid.disttest.client.ClientState; +import org.apache.qpid.disttest.controller.Controller; +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.controller.TestResult; +import org.apache.qpid.disttest.controller.config.Config; +import org.apache.qpid.disttest.jms.ClientJmsDelegate; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.message.ConsumerParticipantResult; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.message.ProducerParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ControllerAndClientTest extends DistributedTestSystemTestBase +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ControllerAndClientTest.class); + private static final long CLIENT_BACKGROUND_THREAD_WAIT_TIME = 5000; + + private Controller _controller; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _controller = new Controller(new ControllerJmsDelegate(_context), REGISTRATION_TIMEOUT, COMMAND_RESPONSE_TIMEOUT); + _controller.setTestResultTimeout(TEST_RESULT_TIMEOUT); + } + + public void testProducerAndConsumerInSeparateClients() throws Exception + { + List resultList = runTestsForTwoClients("producerAndConsumerInSeparateClients.json", 1); + + TestResult testResult1 = resultList.get(0); + assertEquals("Unexpected test name", "Test 1", testResult1.getName()); + List test1ParticipantResults = testResult1.getParticipantResults(); + assertEquals("Unexpected number of participant results for test 1", 2, test1ParticipantResults.size()); + assertParticipantNames(test1ParticipantResults, "participantConsumer1", "participantProducer1"); + } + + public void testProducerClient() throws Exception + { + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Queue queue = session.createQueue("producerClient"); + MessageConsumer consumer = session.createConsumer(queue); + + // queue is not declared in configuration + // controller is not able to clean it + // cleaning manually + while(consumer.receive(1000l) != null); + + final Config config = ConfigFileHelper.getConfigFromResource(getClass(), "produceClient.json"); + _controller.setConfig(config); + final Client client1 = new Client(new ClientJmsDelegate(_context)); + final Thread client1Thread = createBackgroundClientThread(client1); + _controller.awaitClientRegistrations(); + + ResultsForAllTests results = _controller.runAllTests(); + _controller.stopAllRegisteredClients(); + + assertClientThreadsShutdown(client1Thread); + assertClientsStopped(ClientState.STOPPED, client1); + assertFalse("Test should have no errors", results.hasErrors()); + List allTestResults = results.getTestResults(); + assertEquals("Unexpected number of test results", 1, allTestResults.size()); + ITestResult testResult1 = allTestResults.get(0); + assertEquals("Unexpected test name", "Test 1", testResult1.getName()); + List test1ParticipantResults = testResult1.getParticipantResults(); + assertEquals("Unexpected number of participant results for test 1", 1, test1ParticipantResults.size()); + assertParticipantNames(test1ParticipantResults, "participantProducer1"); + + // check message properties + for (int i=0; i< 10; i++) + { + Message message = consumer.receive(1000l); + assertNotNull("Message " + i + " is not received", message); + assertEquals("Unexpected priority", i, message.getJMSPriority()); + assertEquals("Unexpected id", i, message.getIntProperty("id")); + assertEquals("Unexpected test", "test-value", message.getStringProperty("test")); + } + } + + public void testProducerAndThreeConsumersInSeparateClients() throws Exception + { + List resultList = runTestsForTwoClients("producerAndThreeConsumersInSeparateClients.json", 1); + + TestResult testResult1 = resultList.get(0); + List test1ParticipantResults = testResult1.getParticipantResults(); + assertEquals("Unexpected number of participant results for test", 4, test1ParticipantResults.size()); + + assertParticipantNames(test1ParticipantResults, "participantConsumer1", "participantConsumer2", "participantConsumer3", "participantProducer1"); + + ConsumerParticipantResult consumer1 = (ConsumerParticipantResult) test1ParticipantResults.get(0); + assertEquals(3, consumer1.getNumberOfMessagesProcessed()); + assertEquals(true, consumer1.isSynchronousConsumer()); + + ProducerParticipantResult producer1 = (ProducerParticipantResult) test1ParticipantResults.get(3); + assertEquals(9, producer1.getNumberOfMessagesProcessed()); + assertEquals(2, producer1.getBatchSize()); + assertEquals(50, producer1.getInterval()); + } + + public void testIteratingFeature() throws Exception + { + List resultList = runTestsForTwoClients("iteratingFeature.json", 2); + + assertTestResultMessageSize(resultList.get(0), 0, 100, 10); + assertTestResultMessageSize(resultList.get(1), 1, 200, 5); + + } + + private void assertTestResultMessageSize(TestResult testResult, int iterationNumber, int expectedMessageSize, int expectedNumberOfMessages) + { + List test1ParticipantResults = testResult.getParticipantResults(); + assertEquals("Unexpected number of participant results for test", 2, test1ParticipantResults.size()); + + ParticipantResult producer1 = (ParticipantResult) test1ParticipantResults.get(1); + + assertEquals(expectedMessageSize, producer1.getPayloadSize()); + assertEquals(iterationNumber, producer1.getIterationNumber()); + } + + public void testTwoTests() throws Exception + { + List resultList = runTestsForTwoClients("testWithTwoTests.json", 2); + + assertEquals("Test 1", resultList.get(0).getName()); + assertEquals("Test 2", resultList.get(1).getName()); + } + + private List runTestsForTwoClients(String jsonConfigFile, int expectedNumberOfTests) throws NamingException, InterruptedException + { + final Config config = ConfigFileHelper.getConfigFromResource(getClass(), jsonConfigFile); + _controller.setConfig(config); + + final Client client1 = new Client(new ClientJmsDelegate(_context)); + final Client client2 = new Client(new ClientJmsDelegate(_context)); + + final Thread client1Thread = createBackgroundClientThread(client1); + final Thread client2Thread = createBackgroundClientThread(client2); + + _controller.awaitClientRegistrations(); + + ResultsForAllTests results = _controller.runAllTests(); + _controller.stopAllRegisteredClients(); + + assertClientThreadsShutdown(client1Thread, client2Thread); + assertClientsStopped(ClientState.STOPPED, client1, client2); + + assertFalse("Test should have no errors", results.hasErrors()); + + List allTestResults = (List)results.getTestResults(); + assertEquals("Unexpected number of test results", expectedNumberOfTests, allTestResults.size()); + + return allTestResults; + } + + + private void assertParticipantNames(List participants, String... expectedOrderedParticipantNames) + { + assertEquals("Size of list of expected participant names is different from actual", expectedOrderedParticipantNames.length, participants.size()); + + for (int i = 0; i < expectedOrderedParticipantNames.length; i++) + { + String expectedParticipantName = expectedOrderedParticipantNames[i]; + ParticipantResult participant = participants.get(i); + assertEquals(expectedParticipantName, participant.getParticipantName()); + } + } + + private void assertClientsStopped(ClientState expectedState, final Client... clients) + { + for (Client client : clients) + { + assertEquals(client.getClientName() + " in unexpected state", expectedState, client.getState()); + } + } + + private void assertClientThreadsShutdown(final Thread... clientThreads) + throws InterruptedException + { + for (Thread clientThread : clientThreads) + { + clientThread.join(2000); + assertFalse(clientThread.getName() + " should have shutdown", clientThread.isAlive()); + } + } + + private Thread createBackgroundClientThread(final Client client) throws NamingException + { + final String clientThreadName = client.getClientName() + "-thread"; + final Thread clientThread = new Thread(new Runnable() + { + @Override + public void run() + { + try + { + client.start(); + client.waitUntilStopped(CLIENT_BACKGROUND_THREAD_WAIT_TIME); + } + finally + { + LOGGER.debug("Client thread {} finished", clientThreadName); + } + } + }, clientThreadName); + clientThread.start(); + return clientThread; + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/iteratingFeature.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/iteratingFeature.json new file mode 100644 index 0000000000..89123302b7 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/iteratingFeature.json @@ -0,0 +1,63 @@ +{ + "_tests":[ + { + "_name": "Test iteration feature", + "_iterations":[ + { + "_messageSize": 100, + "_numberOfMessages": 10 + }, + { + "_messageSize": 200, + "_numberOfMessages": 5 + } + ], + "_queues":[ + { + "_name": "direct://amq.direct//testQueue" + } + ], + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer1", + "_destinationName": "direct://amq.direct//testQueue" + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_consumers": [ + { + "_name": "participantConsumer1", + "_destinationName": "direct://amq.direct//testQueue" + } + ] + } + ] + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/produceClient.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/produceClient.json new file mode 100644 index 0000000000..605e5cb585 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/produceClient.json @@ -0,0 +1,41 @@ +{ + "_tests":[ + { + "_name": "Test 1"; + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer1", + "_destinationName": "direct://amq.direct//producerClient", + "_numberOfMessages": 10; + "_messageProviderName": "testProvider1" + } + ] + } + ] + } + ]; + "_messageProviders":[ + { + "_name": "testProvider1"; + "_messageProperties": { + "priority": {"@def": "list"; "_items": [0,1,2,3,4,5,6,7,8,9]}; + "id": {"@def": "range"; "_upper": 10; "_type": "int"}; + "test": "test-value" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json new file mode 100644 index 0000000000..8d210dce84 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json @@ -0,0 +1,55 @@ +{ + "_tests":[ + { + "_name": "Test 1"; + "_queues":[ + { + "_name": "direct://amq.direct//testQueue" + } + ]; + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_consumers": [ + { + "_name": "participantConsumer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndThreeConsumersInSeparateClients.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndThreeConsumersInSeparateClients.json new file mode 100644 index 0000000000..f94c4f0ae0 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndThreeConsumersInSeparateClients.json @@ -0,0 +1,77 @@ +{ + "_tests":[ + { + "_name": "ProducerAndThreeConsumersInSeparateClients"; + "_queues":[ + { + "_name": "direct://amq.direct//testQueue" + } + ]; + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 9, + "_batchSize": 2, + "_interval": 50 + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_consumers": [ + { + "_name": "participantConsumer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 3 + } + ] + }, + { + "_sessionName": "session2", + "_consumers": [ + { + "_name": "participantConsumer2", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 3 + } + ] + }, + { + "_sessionName": "session3", + "_consumers": [ + { + "_name": "participantConsumer3", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 3 + } + ] + } + ] + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/testWithTwoTests.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/testWithTwoTests.json new file mode 100644 index 0000000000..4abd7f4feb --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/testWithTwoTests.json @@ -0,0 +1,107 @@ +{ + "_tests":[ + { + "_name": "Test 1"; + "_queues":[ + { + "_name": "direct://amq.direct//testQueue" + } + ]; + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_consumers": [ + { + "_name": "participantconsumer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + } + ] + }, + { + "_name": "Test 2"; + "_queues":[ + { + "_name": "direct://amq.direct//testQueue2" + } + ]; + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer2", + "_destinationName": "direct://amq.direct//testQueue2", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_consumers": [ + { + "_name": "participantConsumer2", + "_destinationName": "direct://amq.direct//testQueue2", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java new file mode 100644 index 0000000000..ad7f0e0682 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.disttest.controlleronly; + +import static org.apache.qpid.systest.disttest.SystemTestConstants.COMMAND_RESPONSE_TIMEOUT; +import static org.apache.qpid.systest.disttest.SystemTestConstants.REGISTRATION_TIMEOUT; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TemporaryQueue; + +import org.apache.qpid.disttest.ConfigFileHelper; +import org.apache.qpid.disttest.controller.Controller; +import org.apache.qpid.disttest.controller.config.Config; +import org.apache.qpid.disttest.jms.ControllerJmsDelegate; +import org.apache.qpid.disttest.jms.JmsMessageAdaptor; +import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.disttest.message.RegisterClientCommand; +import org.apache.qpid.disttest.message.Response; +import org.apache.qpid.systest.disttest.DistributedTestSystemTestBase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DistributedControllerTest extends DistributedTestSystemTestBase +{ + private static final Logger LOGGER = LoggerFactory.getLogger(DistributedControllerTest.class); + + private static final String CLIENT1 = "client1"; + private Controller _controller = null; + private Session _session = null; + private Connection _connection = null; + private Destination _controllerQueue = null; + private TemporaryQueue _clientQueue = null; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _controllerQueue = (Destination) _context.lookup("controllerqueue"); + + final ConnectionFactory connectionFactory = (ConnectionFactory) _context.lookup("connectionfactory"); + _connection = connectionFactory.createConnection(); + _connection.start(); + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _clientQueue = _session.createTemporaryQueue(); + + _controller = new Controller(new ControllerJmsDelegate(_context), REGISTRATION_TIMEOUT, COMMAND_RESPONSE_TIMEOUT); + } + + @Override + protected void tearDown() throws Exception + { + try + { + if (_connection != null) + { + _connection.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testControllerSendsOneCommandToSingleClient() throws Exception + { + Config config = ConfigFileHelper.getConfigFromResource(getClass(), "distributedControllerTest.json"); + _controller.setConfig(config); + + sendRegistration(CLIENT1); + _controller.awaitClientRegistrations(); + + final ArrayBlockingQueue commandList = new ArrayBlockingQueue(4); + final MessageConsumer clientConsumer = _session.createConsumer(_clientQueue); + final AtomicReference listenerException = new AtomicReference(); + final MessageProducer producer = _session.createProducer(_controllerQueue); + clientConsumer.setMessageListener(new MessageListener() + { + @Override + public void onMessage(Message message) + { + try + { + Command command = JmsMessageAdaptor.messageToCommand(message); + LOGGER.debug("Test client received " + command); + commandList.add(command); + producer.send(JmsMessageAdaptor.commandToMessage(_session, new Response(CLIENT1, command.getType()))); + } + catch(Exception e) + { + listenerException.set(e); + } + } + }); + + _controller.runAllTests(); + assertCommandType(CommandType.CREATE_CONNECTION, commandList); + assertCommandType(CommandType.START_TEST, commandList); + assertCommandType(CommandType.TEAR_DOWN_TEST, commandList); + + _controller.stopAllRegisteredClients(); + assertCommandType(CommandType.STOP_CLIENT, commandList); + assertNull("Unexpected exception occured", listenerException.get()); + Command command = commandList.poll(1l, TimeUnit.SECONDS); + assertNull("Unexpected command is received", command); + } + + private void assertCommandType(CommandType expectedType, BlockingQueue commandList) throws InterruptedException + { + Command command = commandList.poll(1l, TimeUnit.SECONDS); + assertNotNull("Command of type " + expectedType + " is not received", command); + assertEquals("Unexpected command type", expectedType, command.getType()); + } + + private void sendRegistration(final String clientId) throws JMSException + { + final MessageProducer registrationProducer = _session.createProducer(_controllerQueue); + + final Command command = new RegisterClientCommand(clientId, _clientQueue.getQueueName()); + final Message registrationMessage = JmsMessageAdaptor.commandToMessage(_session, command); + registrationProducer.send(registrationMessage); + LOGGER.debug("sent registrationMessage: " + registrationMessage); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/distributedControllerTest.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/distributedControllerTest.json new file mode 100644 index 0000000000..b49603ef23 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/distributedControllerTest.json @@ -0,0 +1,17 @@ +{ + "_tests":[ + { + "_name": "Test 1"; + "_clients":[ + { + "_name": "client1", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory" + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java new file mode 100644 index 0000000000..63c9b42858 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.disttest.endtoend; + +import static org.apache.qpid.disttest.AbstractRunner.JNDI_CONFIG_PROP; +import static org.apache.qpid.disttest.ControllerRunner.OUTPUT_DIR_PROP; +import static org.apache.qpid.disttest.ControllerRunner.TEST_CONFIG_PROP; + +import java.io.File; +import java.io.IOException; + +import org.apache.qpid.disttest.ControllerRunner; +import org.apache.qpid.disttest.message.ParticipantAttribute; +import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.util.FileUtils; + +public class EndToEndTest extends QpidBrokerTestCase +{ + private ControllerRunner _runner; + private static final String TEST_CONFIG = "perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json"; + private static final String JNDI_CONFIG_FILE = "perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties"; + + public void testRunner() throws Exception + { + File csvOutputDir = createTemporaryCsvDirectory(); + assertTrue("CSV output dir must not exist",csvOutputDir.isDirectory()); + + final String[] args = new String[] {TEST_CONFIG_PROP + "=" + TEST_CONFIG, + JNDI_CONFIG_PROP + "=" + JNDI_CONFIG_FILE, + OUTPUT_DIR_PROP + "=" + csvOutputDir.getAbsolutePath()}; + _runner = new ControllerRunner(); + _runner.parseArgumentsIntoConfig(args); + _runner.runController(); + + File expectedCsvOutputFile = new File(csvOutputDir, "endtoend.csv"); + assertTrue("CSV output file must exist", expectedCsvOutputFile.exists()); + final String csvContents = FileUtils.readFileAsString(expectedCsvOutputFile); + final String[] csvLines = csvContents.split("\n"); + + int numberOfHeaders = 1; + int numberOfParticipants = 2; + int numberOfSummaries = 3; + + int numberOfExpectedRows = numberOfHeaders + numberOfParticipants + numberOfSummaries; + assertEquals("Unexpected number of lines in CSV", numberOfExpectedRows, csvLines.length); + + assertDataRowsHaveCorrectTestAndClientName("End To End 1", "producingClient", "participantProducer1", csvLines[1], 1); + assertDataRowsHaveCorrectTestAndClientName("End To End 1", "consumingClient", "participantConsumer1", csvLines[2], 1); + + assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_PARTICIPANTS_NAME, csvLines[3], 1); + assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_CONSUMER_PARTICIPANTS_NAME, csvLines[4], 1); + assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_PRODUCER_PARTICIPANTS_NAME, csvLines[5], 1); + + } + + private void assertDataRowsHaveCorrectTestAndClientName(String testName, String clientName, String participantName, String csvLine, int expectedNumberOfMessagesProcessed) + { + final int DONT_STRIP_EMPTY_LAST_FIELD_FLAG = -1; + String[] cells = csvLine.split(",", DONT_STRIP_EMPTY_LAST_FIELD_FLAG); + // All attributes become cells in the CSV, so this will be true + assertEquals("Unexpected number of cells in CSV line " + csvLine, ParticipantAttribute.values().length, cells.length); + assertEquals("Unexpected test name in CSV line " + csvLine, testName, cells[0]); + assertEquals("Unexpected client name in CSV line " + csvLine, clientName, cells[2]); + assertEquals("Unexpected participant name in CSV line " + csvLine, participantName, cells[3]); + assertEquals("Unexpected number of messages processed in CSV line " + csvLine, String.valueOf(expectedNumberOfMessagesProcessed), cells[4]); + + } + + private File createTemporaryCsvDirectory() throws IOException + { + String tmpDir = System.getProperty("java.io.tmpdir"); + File csvDir = new File(tmpDir, "csv"); + csvDir.mkdir(); + csvDir.deleteOnExit(); + return csvDir; + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json new file mode 100644 index 0000000000..1b7cc51265 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json @@ -0,0 +1,65 @@ +{ + "_tests":[ + { + "_name": "End To End 1"; + "_queues":[ + { + "_name": "direct://amq.direct//testQueue" + } + ]; + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_producers": [ + { + "_name": "participantProducer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 1 + } + ] + } + ]; + "_messageProviders":[ + { + "_name": "testProvider1"; + "_messageProperties": { + "priority": {"@def": "list"; "_items": [1,2,3,4,4]}; + "id": {"@def": "random"; "_upper": 10}; + "test": "test-value" + } + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_consumers": [ + { + "_name": "participantConsumer1", + "_destinationName": "direct://amq.direct//testQueue", + "_numberOfMessages": 1 + } + ] + } + ] + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties new file mode 100644 index 0000000000..b5d053227c --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties @@ -0,0 +1,26 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# this file is used for running system tests of the performance test framework, +# (i.e. not for running the performance tests themselves!) + +java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory + +# use QpidBrokerTestCase's default port +connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:15672' + +destination.controllerqueue = direct://amq.direct//controllerqueue diff --git a/java/perftests/visualisation-jfc/build.xml b/java/perftests/visualisation-jfc/build.xml new file mode 100644 index 0000000000..b838855e8b --- /dev/null +++ b/java/perftests/visualisation-jfc/build.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The JFreeChart library is required to use this optional module. + +The jar file may be downloaded by either: + + Seperately running the following command from the qpid/java/perftests/visualisation-jfc dir: ant download-jfree + + OR + + Adding -Ddownload-jfree=true to your regular build command. + The JFreechart JARs were not found + + + + + + + + + + *NOTE* The JFreeChart and JFreeCommon libraries required by this optional module are licensed under the LGPL Licence, which is not compatible with the Apache Licence v2.0. + +For a copy of the LGPL Licence, please see: +http://www.gnu.org/licenses/lgpl.html + + + + + + + + + + + + + + + + + The CSVJDBC library is required to use this optional module. + +The jar file may be downloaded by either: + + Seperately running the following command from the qpid/java/perftests/visualisation-jfc dir: ant download-csvjdbc + + OR + + Adding -Ddownload-csvjdbc=true to your regular build command. + The CSVJDBC JAR was not found + + + + + *NOTE* The CSVJDBC library required by this optional module is licensed under the LGPL Licence, which is not compatible with the Apache Licence v2.0. + +For a copy of the LGPL Licence, please see: +http://www.gnu.org/licenses/lgpl.html + + + + + + + + + + + + Downloading JFreeChart + + + + + + + + + + + Downloading csvjdbc + + + + + + + diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java new file mode 100644 index 0000000000..2803f2d767 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting; + +public enum ChartType +{ + LINE, BAR + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingException.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingException.java new file mode 100644 index 0000000000..120a4dc750 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingException.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting; + +public class ChartingException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public ChartingException() + { + super(); + } + + public ChartingException(String message) + { + super(message); + } + + public ChartingException(Throwable cause) + { + super(cause); + } + + public ChartingException(String message, Throwable cause) + { + super(message, cause); + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java new file mode 100644 index 0000000000..a149d1a097 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java @@ -0,0 +1,135 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.disttest.ArgumentParser; +import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilder; +import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilderFactory; +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ChartingUtil +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ChartingUtil.class); + + public static final String OUTPUT_DIR_PROP = "outputdir"; + public static final String OUTPUT_DIR_DEFAULT = "."; + + public static final String CHART_DEFINITIONS_PROP = "chart-defs"; + public static final String CHART_DEFINITIONS_DEFAULT = "."; + + private Map _cliOptions = new HashMap(); + { + _cliOptions.put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); + _cliOptions.put(CHART_DEFINITIONS_PROP, CHART_DEFINITIONS_DEFAULT); + } + + public static void main(String[] args) throws Exception + { + try + { + LOGGER.debug("Starting charting"); + + ChartingUtil chartingUtil = new ChartingUtil(); + chartingUtil.parseArgumentsIntoConfig(args); + chartingUtil.produceAllCharts(); + } + finally + { + LOGGER.debug("Charting complete"); + } + } + + private void produceAllCharts() + { + final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); + List definitions = loadChartDefinitions(chartingDefsDir); + + LOGGER.debug("There are {} chart(s) to produce", definitions.size()); + + for (ChartingDefinition chartingDefinition : definitions) + { + ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder(chartingDefinition.getChartType()); + JFreeChart chart = chartBuilder.buildChart(chartingDefinition); + writeChartToFileSystem(chart, chartingDefinition.getChartStemName()); + } + } + + private void writeChartToFileSystem(JFreeChart chart, String chartStemName) + { + OutputStream pngOutputStream = null; + try + { + + File pngFile = new File(chartStemName + ".png"); + pngOutputStream = new BufferedOutputStream(new FileOutputStream(pngFile)); + ChartUtilities.writeChartAsPNG(pngOutputStream, chart, 600, 400, true, 0); + pngOutputStream.close(); + + LOGGER.debug("Written {} chart", pngFile); + } + catch (IOException e) + { + throw new ChartingException("Failed to create chart", e); + } + finally + { + if (pngOutputStream != null) + { + try + { + pngOutputStream.close(); + } + catch (IOException e) + { + throw new ChartingException("Failed to create chart", e); + } + } + } + } + + private List loadChartDefinitions(String chartingDefsDir) + { + ChartingDefinitionCreator chartingDefinitionLoader = new ChartingDefinitionCreator(); + return chartingDefinitionLoader.createFromFileOrDirectory(chartingDefsDir); + } + + private void parseArgumentsIntoConfig(String[] args) + { + ArgumentParser argumentParser = new ArgumentParser(); + argumentParser.parseArgumentsIntoConfig(_cliOptions, args); + } + + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java new file mode 100644 index 0000000000..302263a604 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.category.DefaultCategoryDataset; + +public class BarChartBuilder extends DataSetBasedChartBuilder +{ + + @Override + public JFreeChart createChartImpl(String title, String xAxisTitle, + String yAxisTitle, final DefaultCategoryDataset dataset, PlotOrientation plotOrientation, + boolean showLegend, boolean showToolTips, boolean showUrls) + { + JFreeChart chart = ChartFactory.createBarChart(title, + xAxisTitle, + yAxisTitle, + dataset, + plotOrientation, + showLegend, + showToolTips, + showUrls); + return chart; + } + + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java new file mode 100644 index 0000000000..c6f5ecc175 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.jfree.chart.JFreeChart; + +public interface ChartBuilder +{ + + public JFreeChart buildChart(ChartingDefinition chartingDefinition); + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java new file mode 100644 index 0000000000..4c5d4fa09f --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.ChartType; + +public class ChartBuilderFactory +{ + + public static ChartBuilder createChartBuilder(ChartType chartType) + { + switch (chartType) + { + case LINE: + return new LineChartBuilder(); + case BAR: + return new BarChartBuilder(); + default: + throw new IllegalArgumentException("Unknown chart type " + chartType); + } + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java new file mode 100644 index 0000000000..a47df0e8af --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; + +public interface DataPointCallback +{ + public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object xValue, Object yValue); +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java new file mode 100644 index 0000000000..6e2491c883 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.category.DefaultCategoryDataset; + +public abstract class DataSetBasedChartBuilder implements ChartBuilder +{ + private static final CategoryLabelPositions LABEL_POSITION = CategoryLabelPositions.UP_45; + private static final PlotOrientation PLOT_ORIENTATION = PlotOrientation.VERTICAL; + + @Override + public JFreeChart buildChart(ChartingDefinition chartingDefinition) + { + String title = chartingDefinition.getChartTitle(); + String xAxisTitle = chartingDefinition.getXAxisTitle(); + String yAxisTitle = chartingDefinition.getYAxisTitle(); + + final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + + SeriesBuilder seriesBuilder = new SeriesBuilder(new DataPointCallback() + { + @Override + public void addDataPointToSeries(SeriesDefinition seriesDefinition, + Object xValue, Object yValue) + { + String x = (String) xValue; + double y = (Double) yValue; + dataset.addValue( y, seriesDefinition.getSeriesLegend(), x); + } + }); + + seriesBuilder.build(chartingDefinition.getSeries()); + + JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, + dataset, PLOT_ORIENTATION, true, false, false); + + chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(LABEL_POSITION); + + return chart; + } + + public abstract JFreeChart createChartImpl(String title, String xAxisTitle, + String yAxisTitle, final DefaultCategoryDataset dataset, PlotOrientation plotOrientation, + boolean showLegend, boolean showToolTips, boolean showUrls); +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java new file mode 100644 index 0000000000..697dfdcf3e --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.category.DefaultCategoryDataset; + +public class LineChartBuilder extends DataSetBasedChartBuilder +{ + @Override + public JFreeChart createChartImpl(String title, String xAxisTitle, + String yAxisTitle, final DefaultCategoryDataset dataset, PlotOrientation plotOrientation, + boolean showLegend, boolean showToolTips, boolean showUrls) + { + JFreeChart chart = ChartFactory.createLineChart(title, + xAxisTitle, + yAxisTitle, + dataset, + plotOrientation, + showLegend, + showToolTips, + showUrls); + return chart; + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java new file mode 100644 index 0000000000..de717792db --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Iterator; +import java.util.List; + +import org.apache.qpid.disttest.charting.ChartingException; +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; + +public class SeriesBuilder +{ + static + { + registerCsvDriver(); + } + + private final DataPointCallback _dataPointCallback; + + public SeriesBuilder(DataPointCallback dataPointCallback) + { + _dataPointCallback = dataPointCallback; + } + + public void build(List seriesDefinitions) + { + for (Iterator iterator = seriesDefinitions.iterator(); iterator.hasNext();) + { + SeriesDefinition series = iterator.next(); + buildDataSetForSingleSeries(series); + } + } + + private void buildDataSetForSingleSeries(SeriesDefinition seriesDefinition) + { + Connection conn = null; + Statement stmt = null; + try + { + File seriesDir = getValidatedSeriesDirectory(seriesDefinition); + + conn = DriverManager.getConnection("jdbc:relique:csv:" + seriesDir.getAbsolutePath()); + + final String seriesStatement = seriesDefinition.getSeriesStatement(); + + stmt = conn.createStatement(); + ResultSet results = stmt.executeQuery(seriesStatement); + + while (results.next()) + { + Object xValue = results.getString(1); + Object yValue = results.getDouble(2); + + _dataPointCallback.addDataPointToSeries(seriesDefinition, xValue, yValue); + } + } + catch (SQLException e) + { + throw new ChartingException("Failed to create chart dataset", e); + } + finally + { + if (stmt != null) + { + try + { + stmt.close(); + } + catch (SQLException e) + { + throw new RuntimeException("Failed to close statement", e); + } + } + if (conn != null) + { + try + { + conn.close(); + } + catch (SQLException e) + { + throw new RuntimeException("Failed to close connection", e); + } + } + } + } + + private File getValidatedSeriesDirectory(SeriesDefinition series) + { + File seriesDir = new File(series.getSeriesDirectory()); + if (!seriesDir.isDirectory()) + { + throw new ChartingException("seriesDirectory must be a directory : " + seriesDir); + } + return seriesDir; + } + + private static void registerCsvDriver() throws ExceptionInInitializerError + { + try + { + Class.forName("org.relique.jdbc.csv.CsvDriver"); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException("Could not load CSV/JDBC driver", e); + } + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java new file mode 100644 index 0000000000..82b59b6d6e --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.definition; + +import java.util.Collections; +import java.util.List; + +import org.apache.qpid.disttest.charting.ChartType; + +public class ChartingDefinition +{ + private final String _chartStemName; + private final ChartType _chartType; + private final String _chartTitle; + private final String _xaxisTitle; + private final String _yaxisTitle; + private final List _seriesDefinitions; + + + public ChartingDefinition(final String chartStemName, + final ChartType chartType, + final String chartTitle, + final String xaxisTitle, + final String yaxisTitle, List seriesDefinitions) + { + _chartStemName = chartStemName; + _chartType = chartType; + _chartTitle = chartTitle; + _xaxisTitle = xaxisTitle; + _yaxisTitle = yaxisTitle; + _seriesDefinitions = seriesDefinitions; + } + + public String getChartStemName() + { + return _chartStemName; + } + + public String getChartTitle() + { + return _chartTitle; + } + + + public String getXAxisTitle() + { + return _xaxisTitle; + } + + + public String getYAxisTitle() + { + return _yaxisTitle; + } + + + + public ChartType getChartType() + { + return _chartType; + } + + public List getSeries() + { + return Collections.unmodifiableList(_seriesDefinitions); + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java new file mode 100644 index 0000000000..8a3d313519 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.definition; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileFilter; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.qpid.disttest.charting.ChartType; +import org.apache.qpid.disttest.charting.ChartingException; + +public class ChartingDefinitionCreator +{ + public static final String CHARTDEF_FILE_EXTENSION = ".chartdef"; + + public static final String CHART_TYPE_KEY = "chartType"; + public static final String CHART_TITLE_KEY = "chartTitle"; + public static final String XAXIS_TITLE_KEY = "xAxisTitle"; + public static final String YAXIS_TITLE_KEY = "yAxisTitle"; + + private SeriesDefinitionCreator _seriesDefinitionCreator = new SeriesDefinitionCreator(); + + public List createFromFileOrDirectory(String chartingDefinitionFileOrDirectory) + { + List definitions = new ArrayList(); + + File fileOrDirectory = new File(chartingDefinitionFileOrDirectory); + if (fileOrDirectory.isDirectory()) + { + File[] matchingFiles = fileOrDirectory.listFiles(new CHARTDEF_FILE_FILTER()); + + for (File file : matchingFiles) + { + final ChartingDefinition chartDefinition = createChartDefinition(file); + definitions.add(chartDefinition); + } + } + else + { + final ChartingDefinition chartDefinition = createChartDefinition(fileOrDirectory); + definitions.add(chartDefinition); + } + + return definitions; + } + + private ChartingDefinition createChartDefinition(File file) + { + Reader reader = null; + try + { + reader = new BufferedReader(new FileReader(file)); + Properties props = new Properties(); + props.load(reader); + + final String chartStemName = getStemNameFrom(file); + + final ChartType chartType = ChartType.valueOf(props.getProperty(CHART_TYPE_KEY)); + final String chartTitle = props.getProperty(CHART_TITLE_KEY); + final String xAxisTitle = props.getProperty(XAXIS_TITLE_KEY); + final String yAxisTitle = props.getProperty(YAXIS_TITLE_KEY); + + final List seriesDefinitions = createSeriesDefinitions(props); + + final ChartingDefinition chartDefinition = new ChartingDefinition(chartStemName, + chartType, + chartTitle, + xAxisTitle, + yAxisTitle, + seriesDefinitions); + return chartDefinition; + } + catch (IOException e) + { + throw new ChartingException("Unable to open file " + file, e); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + throw new ChartingException(e); + } + } + } + + } + + private String getStemNameFrom(File file) + { + final String nameWithExtension = file.getName(); + final String nameWithoutExtensionPart = nameWithExtension.replaceAll("\\.[^\\.]*$", ""); + return nameWithoutExtensionPart; + } + + private List createSeriesDefinitions(Properties props) + { + return _seriesDefinitionCreator.createFromProperties(props); + } + + private final class CHARTDEF_FILE_FILTER implements FileFilter + { + @Override + public boolean accept(File pathname) + { + return pathname.isFile() && pathname.getName().endsWith(CHARTDEF_FILE_EXTENSION); + } + } + + + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java new file mode 100644 index 0000000000..a39e906957 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.definition; + +public class SeriesDefinition +{ + private final String _seriesStatement; + private final String _seriesLegend; + private final String _seriesDirectory; + + public SeriesDefinition(String seriesStatement, String seriesLegend, String seriesDirectory) + { + _seriesStatement = seriesStatement; + _seriesLegend = seriesLegend; + _seriesDirectory = seriesDirectory; + } + + public String getSeriesStatement() + { + return _seriesStatement; + } + + public String getSeriesLegend() + { + return _seriesLegend; + } + + public String getSeriesDirectory() + { + return _seriesDirectory; + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java new file mode 100644 index 0000000000..fcc11807c8 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.definition; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.lang.text.StrSubstitutor; + +public class SeriesDefinitionCreator +{ + public static final String SERIES_STATEMENT_KEY_FORMAT = "series.%d.statement"; + public static final String SERIES_LEGEND_KEY_FORMAT = "series.%d.legend"; + public static final String SERIES_DIRECTORY_KEY_FORMAT = "series.%d.dir"; + + public List createFromProperties(Properties properties) + { + final List seriesDefinitions = new ArrayList(); + + int index = 1; + boolean moreSeriesDefinitions = true; + while(moreSeriesDefinitions) + { + String seriesStatement = properties.getProperty(String.format(SERIES_STATEMENT_KEY_FORMAT, index)); + String seriesLegend = properties.getProperty(String.format(SERIES_LEGEND_KEY_FORMAT, index)); + String seriesDir = StrSubstitutor.replaceSystemProperties(properties.getProperty(String.format(SERIES_DIRECTORY_KEY_FORMAT, index))); + + if (seriesStatement != null) + { + final SeriesDefinition seriesDefinition = new SeriesDefinition(seriesStatement, seriesLegend, seriesDir); + seriesDefinitions.add(seriesDefinition); + } + else + { + moreSeriesDefinitions = false; + } + index++; + } + return seriesDefinitions; + } + +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java new file mode 100644 index 0000000000..bdbbc4a585 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.ChartType; + +import junit.framework.TestCase; + +public class ChartBuilderFactoryTest extends TestCase +{ + public void testLineChart() + { + ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.LINE); + assertTrue(builder instanceof LineChartBuilder); + } + + public void testBarChart() + { + ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR); + assertTrue(builder instanceof BarChartBuilder); + } + +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java new file mode 100644 index 0000000000..1b1c9969b3 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.util.Collections; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; + +public class SeriesBuilderTest extends TestCase +{ + private static final String TEST_SERIES_1_SELECT_STATEMENT = "SELECT A, B FROM test"; + private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND"; + + private DataPointCallback _dataPointCallback = mock(DataPointCallback.class); + private SeriesBuilder _seriesBuilder = new SeriesBuilder(_dataPointCallback); + + private File _testTempDir; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _testTempDir = createTestTemporaryDirectory(); + } + + public void testBuildOneSeries() throws Exception + { + createTestCsvIn(_testTempDir); + SeriesDefinition seriesDefinition = createTestSeriesDefinition(); + + _seriesBuilder.build(Collections.singletonList(seriesDefinition)); + + verify(_dataPointCallback).addDataPointToSeries(seriesDefinition, (Object)"elephant", (Object)2.0); + verify(_dataPointCallback).addDataPointToSeries(seriesDefinition, (Object)"lion", (Object)3.0); + verify(_dataPointCallback).addDataPointToSeries(seriesDefinition, (Object)"tiger", (Object)4.0); + } + + private void createTestCsvIn(File testDir) throws Exception + { + File csv = new File(_testTempDir, "test.csv"); + + PrintWriter csvWriter = new PrintWriter(new BufferedWriter(new FileWriter(csv))); + csvWriter.println("A,B"); + csvWriter.println("elephant,2"); + csvWriter.println("lion,3"); + csvWriter.println("tiger,4"); + csvWriter.close(); + } + + private SeriesDefinition createTestSeriesDefinition() + { + SeriesDefinition definition = new SeriesDefinition(TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, _testTempDir.getAbsolutePath()); + return definition; + } + + private File createTestTemporaryDirectory() throws Exception + { + File tmpDir = new File(System.getProperty("java.io.tmpdir"), "testdef" + System.nanoTime()); + tmpDir.mkdirs(); + tmpDir.deleteOnExit(); + return tmpDir; + } + +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java new file mode 100644 index 0000000000..80d1cc3d21 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.definition; + +import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TITLE_KEY; +import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TYPE_KEY; +import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.XAXIS_TITLE_KEY; +import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.YAXIS_TITLE_KEY; +import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_STATEMENT_KEY_FORMAT; + +import java.io.File; +import java.io.FileWriter; +import java.util.List; +import java.util.Properties; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.charting.ChartType; +import org.apache.qpid.disttest.charting.ChartingException; + +public class ChartingDefinitionCreatorTest extends TestCase +{ + private static final String TEST_CHART_TITLE = "CHART_TITLE"; + private static final String TEST_XAXIS_TITLE = "XAXIS_TITLE"; + private static final String TEST_YAXIS_TITLE = "YAXIS_TITLE"; + private static final ChartType TEST_CHART_TYPE = ChartType.LINE; + + private static final String TEST_SERIES_SELECT_STATEMENT = "SERIES_SELECT_STATEMENT"; + + private ChartingDefinitionCreator _chartingDefinitionLoader = new ChartingDefinitionCreator(); + private File _testTempDir; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _testTempDir = createTestTemporaryDirectory(); + } + + public void testLoadTwoDefinitionsFromDirectory() throws Exception + { + createTestDefinitionWithin(_testTempDir); + createTestDefinitionWithin(_testTempDir); + + List definitions = _chartingDefinitionLoader.createFromFileOrDirectory(_testTempDir.getAbsolutePath()); + assertEquals(2, definitions.size()); + } + + public void testLoadOneDefinitionFromFile() throws Exception + { + File testDefFile = createTestDefinitionWithin(_testTempDir); + + List definitions = _chartingDefinitionLoader.createFromFileOrDirectory(testDefFile.getAbsolutePath()); + assertEquals(1, definitions.size()); + + ChartingDefinition definition1 = definitions.get(0); + assertEquals(TEST_CHART_TITLE, definition1.getChartTitle()); + } + + public void testDefinitionsProperties() throws Exception + { + File testDefFile = createTestDefinitionWithin(_testTempDir); + + List definitions = _chartingDefinitionLoader.createFromFileOrDirectory(testDefFile.getAbsolutePath()); + assertEquals(1, definitions.size()); + + ChartingDefinition definition1 = definitions.get(0); + assertEquals(TEST_CHART_TITLE, definition1.getChartTitle()); + assertEquals(TEST_XAXIS_TITLE, definition1.getXAxisTitle()); + assertEquals(TEST_YAXIS_TITLE, definition1.getYAxisTitle()); + assertEquals(TEST_CHART_TYPE, definition1.getChartType()); + + String stemOnly = testDefFile.getName().replaceFirst("\\.chartdef", ""); + assertEquals(stemOnly, definition1.getChartStemName()); + + final List seriesDefinitions = definition1.getSeries(); + assertEquals(1, seriesDefinitions.size()); + SeriesDefinition seriesDefinition = seriesDefinitions.get(0); + assertEquals(TEST_SERIES_SELECT_STATEMENT, seriesDefinition.getSeriesStatement()); + } + + public void testDefinitionFileNotFound() throws Exception + { + File notFound = new File(_testTempDir,"notfound.chartdef"); + assertFalse(notFound.exists()); + + try + { + _chartingDefinitionLoader.createFromFileOrDirectory(notFound.getAbsolutePath()); + fail("Exception not thrown"); + } + catch(ChartingException ce) + { + // PASS + } + } + + private File createTestDefinitionWithin(File _testTempDir) throws Exception + { + final String testDefFileName = "test." + System.nanoTime() + ".chartdef"; + File chartDef = new File(_testTempDir, testDefFileName); + chartDef.createNewFile(); + + Properties props = new Properties(); + props.setProperty(CHART_TYPE_KEY, TEST_CHART_TYPE.name()); + props.setProperty(CHART_TITLE_KEY, TEST_CHART_TITLE); + props.setProperty(XAXIS_TITLE_KEY, TEST_XAXIS_TITLE); + props.setProperty(YAXIS_TITLE_KEY, TEST_YAXIS_TITLE); + + props.setProperty(String.format(SERIES_STATEMENT_KEY_FORMAT, 1), TEST_SERIES_SELECT_STATEMENT); + + final FileWriter writer = new FileWriter(chartDef); + try + { + props.store(writer, "Test chart definition file"); + } + finally + { + writer.close(); + } + + return chartDef; + } + + private File createTestTemporaryDirectory() throws Exception + { + File tmpDir = new File(System.getProperty("java.io.tmpdir"), "testdef" + System.nanoTime()); + tmpDir.mkdirs(); + tmpDir.deleteOnExit(); + return tmpDir; + } +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java new file mode 100644 index 0000000000..2187793c53 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.definition; + +import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_DIRECTORY_KEY_FORMAT; +import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_LEGEND_KEY_FORMAT; +import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_STATEMENT_KEY_FORMAT; + +import java.util.List; +import java.util.Properties; + +import junit.framework.TestCase; + +public class SeriesDefinitionCreatorTest extends TestCase +{ + private static final String TEST_SERIES_1_SELECT_STATEMENT = "SERIES_1_SELECT_STATEMENT"; + private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND"; + private static final String TEST_SERIES_1_DIR = "SERIES_1_DIR"; + + private static final String TEST_SERIES_1_DIR_WITH_SYSPROP = "${java.io.tmpdir}/mydir"; + + private static final String TEST_SERIES_2_SELECT_STATEMENT = "SERIES_2_SELECT_STATEMENT"; + private static final String TEST_SERIES_2_LEGEND = "SERIES_2_LEGEND"; + private static final String TEST_SERIES_2_DIR = "SERIES_2_DIR"; + + private Properties _properties = new Properties(); + + private SeriesDefinitionCreator _seriesDefinitionLoader = new SeriesDefinitionCreator(); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + } + + public void testOneSeriesDefinition() throws Exception + { + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR); + + List definitions = _seriesDefinitionLoader.createFromProperties(_properties); + assertEquals(1, definitions.size()); + + SeriesDefinition definition = definitions.get(0); + assertEquals(TEST_SERIES_1_SELECT_STATEMENT, definition.getSeriesStatement()); + assertEquals(TEST_SERIES_1_LEGEND, definition.getSeriesLegend()); + assertEquals(TEST_SERIES_1_DIR, definition.getSeriesDirectory()); + } + + public void testTwoSeriesDefinitions() throws Exception + { + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR); + createTestProperties(2, TEST_SERIES_2_SELECT_STATEMENT, TEST_SERIES_2_LEGEND, TEST_SERIES_2_DIR); + + List definitions = _seriesDefinitionLoader.createFromProperties(_properties); + assertEquals(2, definitions.size()); + + SeriesDefinition seriesDefinition1 = definitions.get(0); + assertEquals(TEST_SERIES_1_SELECT_STATEMENT, seriesDefinition1.getSeriesStatement()); + assertEquals(TEST_SERIES_1_LEGEND, seriesDefinition1.getSeriesLegend()); + assertEquals(TEST_SERIES_1_DIR, seriesDefinition1.getSeriesDirectory()); + + SeriesDefinition seriesDefinition2 = definitions.get(1); + assertEquals(TEST_SERIES_2_SELECT_STATEMENT, seriesDefinition2.getSeriesStatement()); + assertEquals(TEST_SERIES_2_LEGEND, seriesDefinition2.getSeriesLegend()); + assertEquals(TEST_SERIES_2_DIR, seriesDefinition2.getSeriesDirectory()); + } + + public void testNonSequentialSeriesDefinitionsIgnored() throws Exception + { + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR); + createTestProperties(3, TEST_SERIES_2_SELECT_STATEMENT, TEST_SERIES_2_LEGEND, TEST_SERIES_2_DIR); + + List definitions = _seriesDefinitionLoader.createFromProperties(_properties); + assertEquals(1, definitions.size()); + } + + public void testSeriesDirectorySubstitution() throws Exception + { + final String tmpDir = System.getProperty("java.io.tmpdir"); + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR_WITH_SYSPROP); + + List definitions = _seriesDefinitionLoader.createFromProperties(_properties); + assertEquals(1, definitions.size()); + + SeriesDefinition seriesDefinition1 = definitions.get(0); + assertTrue(seriesDefinition1.getSeriesDirectory().startsWith(tmpDir)); + } + + private void createTestProperties(int index, String selectStatement, String seriesLegend, String seriesDir) throws Exception + { + _properties.setProperty(String.format(SERIES_STATEMENT_KEY_FORMAT, index), selectStatement); + _properties.setProperty(String.format(SERIES_LEGEND_KEY_FORMAT, index), seriesLegend); + _properties.setProperty(String.format(SERIES_DIRECTORY_KEY_FORMAT, index), seriesDir); + } + +} diff --git a/java/systests/build.xml b/java/systests/build.xml index fb2bae1d47..6adce705cd 100644 --- a/java/systests/build.xml +++ b/java/systests/build.xml @@ -7,9 +7,9 @@ nn - or more contributor license agreements. See the NOTICE file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - + - - http://www.apache.org/licenses/LICENSE-2.0 - - + - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -27,7 +27,7 @@ nn - or more contributor license agreements. See the NOTICE file - + diff --git a/java/systests/etc/bin/testclients.sh b/java/systests/etc/bin/testclients.sh deleted file mode 100755 index 002f3d98bb..0000000000 --- a/java/systests/etc/bin/testclients.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -for x in `seq 1 $1`; -do - java -cp qpid-integrationtests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar -Dlog4j.configuration=file:/home/rupert/qpid/trunk/qpid/java/etc/mylog4j.xml org.apache.qpid.test.framework.distributedtesting.TestClient -n java$x & -done diff --git a/java/systests/etc/virtualhosts-systests-bdb-settings.xml b/java/systests/etc/virtualhosts-systests-bdb-settings.xml index ce16523f13..216046b40b 100644 --- a/java/systests/etc/virtualhosts-systests-bdb-settings.xml +++ b/java/systests/etc/virtualhosts-systests-bdb-settings.xml @@ -26,7 +26,7 @@ localhost - org.apache.qpid.server.store.berkeleydb.BDBMessageStore + org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory ${work}/bdbstore/localhost-store @@ -36,7 +36,7 @@ development - org.apache.qpid.server.store.berkeleydb.BDBMessageStore + org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory ${work}/bdbstore/development-store @@ -46,7 +46,7 @@ test - org.apache.qpid.server.store.berkeleydb.BDBMessageStore + org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory ${work}/bdbstore/test-store diff --git a/java/systests/etc/virtualhosts-systests-derby-settings.xml b/java/systests/etc/virtualhosts-systests-derby-settings.xml index ed5ffbb1fd..d494768e91 100644 --- a/java/systests/etc/virtualhosts-systests-derby-settings.xml +++ b/java/systests/etc/virtualhosts-systests-derby-settings.xml @@ -26,7 +26,7 @@ - org.apache.qpid.server.store.DerbyMessageStore + org.apache.qpid.server.store.derby.DerbyMessageStoreFactory ${QPID_WORK}/derbyDB/localhost-store @@ -35,8 +35,8 @@ - org.apache.qpid.server.store.DerbyMessageStore - ${QPID_WORK}/derbyDB/development-store + org.apache.qpid.server.store.derby.DerbyMessageStoreFactory + ${QPID_WORK}/derbyDB/development-store @@ -44,7 +44,7 @@ - org.apache.qpid.server.store.DerbyMessageStore + org.apache.qpid.server.store.derby.DerbyMessageStoreFactory ${QPID_WORK}/derbyDB/test-store diff --git a/java/systests/etc/virtualhosts-systests-firewall-2.xml b/java/systests/etc/virtualhosts-systests-firewall-2.xml index 20908e6eb4..f8e9fde8ca 100644 --- a/java/systests/etc/virtualhosts-systests-firewall-2.xml +++ b/java/systests/etc/virtualhosts-systests-firewall-2.xml @@ -26,7 +26,7 @@ test - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStoreFactory @@ -35,7 +35,7 @@ test2 - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStoreFactory diff --git a/java/systests/etc/virtualhosts-systests-firewall-3.xml b/java/systests/etc/virtualhosts-systests-firewall-3.xml index 90377f345f..95db02672a 100644 --- a/java/systests/etc/virtualhosts-systests-firewall-3.xml +++ b/java/systests/etc/virtualhosts-systests-firewall-3.xml @@ -26,7 +26,7 @@ test - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStoreFactory @@ -35,7 +35,7 @@ test2 - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStoreFactory diff --git a/java/systests/src/main/java/org/apache/qpid/client/AsynchMessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/AsynchMessageListenerTest.java new file mode 100644 index 0000000000..09402c140d --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/AsynchMessageListenerTest.java @@ -0,0 +1,362 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ +package org.apache.qpid.client; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.util.LogMonitor; + +/** + * Tests the behaviour of JMS asynchronous message listeners as provided by + * {@link MessageListener#onMessage(Message)}. + * + */ +public class AsynchMessageListenerTest extends QpidBrokerTestCase +{ + private static final int MSG_COUNT = 10; + private static final long AWAIT_MESSAGE_TIMEOUT = 2000; + private static final long AWAIT_MESSAGE_TIMEOUT_NEGATIVE = 250; + private final String _testQueueName = getTestQueueName(); + private Connection _consumerConnection; + private Session _consumerSession; + private MessageConsumer _consumer; + private Queue _queue; + + protected void setUp() throws Exception + { + super.setUp(); + + _consumerConnection = getConnection(); + _consumerConnection.start(); + _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _queue = _consumerSession.createQueue(_testQueueName); + _consumer = _consumerSession.createConsumer(_queue); + + // Populate queue + Connection producerConnection = getConnection(); + Session producerSession = producerConnection.createSession(true, Session.SESSION_TRANSACTED); + sendMessage(producerSession, _queue, MSG_COUNT); + producerConnection.close(); + + } + + public void testMessageListener() throws Exception + { + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT); + _consumer.setMessageListener(countingMessageListener); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + assertEquals("Unexpected number of outstanding messages", 0, countingMessageListener.getOutstandingCount()); + } + + public void testSynchronousReceiveFollowedByMessageListener() throws Exception + { + // Receive initial message synchronously + assertNotNull("Could not receive first message synchronously", _consumer.receive(AWAIT_MESSAGE_TIMEOUT) != null); + final int numberOfMessagesToReceiveByMessageListener = MSG_COUNT - 1; + + // Consume remainder asynchronously + CountingMessageListener countingMessageListener = new CountingMessageListener(numberOfMessagesToReceiveByMessageListener); + _consumer.setMessageListener(countingMessageListener); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + assertEquals("Unexpected number of outstanding messages", 0, countingMessageListener.getOutstandingCount()); + } + + public void testMessageListenerSetDisallowsSynchronousReceive() throws Exception + { + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT); + _consumer.setMessageListener(countingMessageListener); + + try + { + _consumer.receive(); + fail("Exception not thrown"); + } + catch (JMSException e) + { + // PASS + assertEquals("A listener has already been set.", e.getMessage()); + } + } + + + public void testConnectionStopThenStart() throws Exception + { + int messageToReceivedBeforeConnectionStop = 2; + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT, messageToReceivedBeforeConnectionStop); + + // Consume at least two messages + _consumer.setMessageListener(countingMessageListener); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + _consumerConnection.stop(); + + assertTrue("Too few messages received afer Connection#stop()", countingMessageListener.getReceivedCount() >= messageToReceivedBeforeConnectionStop); + countingMessageListener.resetLatch(); + + // Restart connection + _consumerConnection.start(); + + // Consume the remainder + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + assertEquals("Unexpected number of outstanding messages", 0, countingMessageListener.getOutstandingCount()); + } + + public void testConnectionStopAndMessageListenerChange() throws Exception + { + int messageToReceivedBeforeConnectionStop = 2; + CountingMessageListener countingMessageListener1 = new CountingMessageListener(MSG_COUNT, messageToReceivedBeforeConnectionStop); + + // Consume remainder asynchronously + _consumer.setMessageListener(countingMessageListener1); + countingMessageListener1.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + _consumerConnection.stop(); + assertTrue("Too few messages received afer Connection#stop()", countingMessageListener1.getReceivedCount() >= messageToReceivedBeforeConnectionStop); + + CountingMessageListener countingMessageListener2 = new CountingMessageListener(countingMessageListener1.getOutstandingCount()); + + // Reset Message Listener + _consumer.setMessageListener(countingMessageListener2); + + _consumerConnection.start(); + + // Consume the remainder + countingMessageListener2.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + assertEquals("Unexpected number of outstanding messages", 0, countingMessageListener2.getOutstandingCount()); + + } + + public void testConnectionStopHaltsDeliveryToListener() throws Exception + { + int messageToReceivedBeforeConnectionStop = 2; + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT, messageToReceivedBeforeConnectionStop); + + // Consume at least two messages + _consumer.setMessageListener(countingMessageListener); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + _consumerConnection.stop(); + + // Connection should now be stopped and listener should receive no more + final int outstandingCountAtStop = countingMessageListener.getOutstandingCount(); + countingMessageListener.resetLatch(); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT_NEGATIVE); + + assertEquals("Unexpected number of outstanding messages", outstandingCountAtStop, countingMessageListener.getOutstandingCount()); + } + + public void testSessionCloseHaltsDelivery() throws Exception + { + int messageToReceivedBeforeConnectionStop = 2; + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT, messageToReceivedBeforeConnectionStop); + + // Consume at least two messages + _consumer.setMessageListener(countingMessageListener); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + _consumerSession.close(); + + // Once a session is closed, the listener should receive no more + final int outstandingCountAtClose = countingMessageListener.getOutstandingCount(); + countingMessageListener.resetLatch(); + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT_NEGATIVE); + + assertEquals("Unexpected number of outstanding messages", outstandingCountAtClose, countingMessageListener.getOutstandingCount()); + } + + public void testImmediatePrefetchWithMessageListener() throws Exception + { + // Close connection provided by setup so we can set IMMEDIATE_PREFETCH + _consumerConnection.close(); + setTestClientSystemProperty(AMQSession.IMMEDIATE_PREFETCH, "true"); + + _consumerConnection = getConnection(); + _consumerConnection.start(); + _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _consumer = _consumerSession.createConsumer(_queue); + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT); + _consumer.setMessageListener(countingMessageListener); + + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + + assertEquals("Unexpected number of messages received", MSG_COUNT, countingMessageListener.getReceivedCount()); + } + + public void testReceiveTwoConsumers() throws Exception + { + Session consumerSession2 = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer _consumer2 = consumerSession2.createConsumer(_queue); + + CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT); + _consumer.setMessageListener(countingMessageListener); + _consumer2.setMessageListener(countingMessageListener); + + countingMessageListener.awaitMessages(AWAIT_MESSAGE_TIMEOUT); + assertEquals("Unexpected number of messages received", MSG_COUNT, countingMessageListener.getReceivedCount()); + } + + /** + * Tests the case where the message listener throws an java.lang.Error. + * TODO - a useful test?. + */ + public void testMessageListenerThrowsError() throws Exception + { + int expectedMessages = 1; // The error will kill the dispatcher so only one message will be delivered. + final CountDownLatch awaitMessages = new CountDownLatch(expectedMessages); + final AtomicInteger receivedCount = new AtomicInteger(0); + final String javaLangErrorMessageText = "MessageListener failed with java.lang.Error"; + CountingExceptionListener countingExceptionListener = new CountingExceptionListener(); + _consumerConnection.setExceptionListener(countingExceptionListener); + + _consumer.setMessageListener(new MessageListener() + { + @Override + public void onMessage(Message message) + { + try + { + throw new Error(javaLangErrorMessageText); + } + finally + { + receivedCount.incrementAndGet(); + awaitMessages.countDown(); + } + } + }); + + awaitMessages.await(AWAIT_MESSAGE_TIMEOUT, TimeUnit.MILLISECONDS); + + assertEquals("Unexpected number of messages received", expectedMessages, receivedCount.get()); + assertEquals("onException should NOT have been called", 0, countingExceptionListener.getErrorCount()); + + // Check that Error has been written to the application log. + + LogMonitor _monitor = new LogMonitor(_outputFile); + assertTrue("The expected message not written to log file.", + _monitor.waitForMessage(javaLangErrorMessageText, LOGMONITOR_TIMEOUT)); + + if (_consumerConnection != null) + { + try + { + _consumerConnection.close(); + } + catch (JMSException e) + { + // Ignore connection close errors for this test. + } + finally + { + _consumerConnection = null; + } + } + } + + private final class CountingExceptionListener implements ExceptionListener + { + private final AtomicInteger _errorCount = new AtomicInteger(); + + @Override + public void onException(JMSException arg0) + { + _errorCount.incrementAndGet(); + } + + public int getErrorCount() + { + return _errorCount.intValue(); + } + } + + private final class CountingMessageListener implements MessageListener + { + private volatile CountDownLatch _awaitMessages; + private final AtomicInteger _receivedCount; + private final AtomicInteger _outstandingMessageCount; + + public CountingMessageListener(final int totalExpectedMessageCount) + { + this(totalExpectedMessageCount, totalExpectedMessageCount); + } + + + public CountingMessageListener(int totalExpectedMessageCount, int numberOfMessagesToAwait) + { + _receivedCount = new AtomicInteger(0); + _outstandingMessageCount = new AtomicInteger(totalExpectedMessageCount); + _awaitMessages = new CountDownLatch(numberOfMessagesToAwait); + } + + public int getOutstandingCount() + { + return _outstandingMessageCount.get(); + } + + public int getReceivedCount() + { + return _receivedCount.get(); + } + + public void resetLatch() + { + _awaitMessages = new CountDownLatch(_outstandingMessageCount.get()); + } + + @Override + public void onMessage(Message message) + { + _receivedCount.incrementAndGet(); + _outstandingMessageCount.decrementAndGet(); + _awaitMessages.countDown(); + } + + public boolean awaitMessages(long timeout) + { + try + { + return _awaitMessages.await(timeout, TimeUnit.MILLISECONDS); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + return false; + } + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java deleted file mode 100644 index 3537dd0533..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.client; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.naming.Context; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery queue - *

- * The message delivery process: - * Mina puts a message on _queue in AMQSession and the dispatcher thread take()s - * from here and dispatches to the _consumers. If the _consumer doesn't have a message listener set at connection start - * then messages are stored on _synchronousQueue (which needs to be > 1 to pass JMS TCK as multiple consumers on a - * session can run in any order and a synchronous put/poll will block the dispatcher). - *

- * When setting the message listener later the _synchronousQueue is just poll()'ed and the first message delivered - * the remaining messages will be left on the queue and lost, subsequent messages on the session will arrive first. - */ -public class DispatcherTest extends QpidBrokerTestCase -{ - private static final Logger _logger = LoggerFactory.getLogger(DispatcherTest.class); - - private Context _context; - - private static final int MSG_COUNT = 6; - private int _receivedCount = 0; - private int _receivedCountWhileStopped = 0; - private Connection _clientConnection, _producerConnection; - private MessageConsumer _consumer; - private MessageProducer _producer; - private Session _clientSession, _producerSession; - - private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(1); // all messages Sent Lock - private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(1); // all messages Sent Lock - - private volatile boolean _connectionStopped = false; - - protected void setUp() throws Exception - { - super.setUp(); - - // Create Client 1 - _clientConnection = getConnection(); - - _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - Queue queue = _clientSession.createQueue(this.getClass().getName()); - _consumer = _clientSession.createConsumer(queue); - - // Create Producer - _producerConnection = getConnection(); - - _producerConnection.start(); - - _producerSession = _producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - _producer = _producerSession.createProducer(queue); - - for (int msg = 0; msg < MSG_COUNT; msg++) - { - _producer.send(_producerSession.createTextMessage("Message " + msg)); - } - } - - protected void tearDown() throws Exception - { - - _clientConnection.close(); - - _producerConnection.close(); - super.tearDown(); - } - - public void testAsynchronousRecieve() - { - _logger.info("Test Start"); - - assertTrue(!((AMQConnection) _clientConnection).started()); - - // Set default Message Listener - try - { - _consumer.setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _logger.info("Client 1 ML 1 Received Message(" + _receivedCount + "):" + message); - - _receivedCount++; - - if (_receivedCount == MSG_COUNT) - { - _allFirstMessagesSent.countDown(); - } - - if (_connectionStopped) - { - _logger.info("Running with Message:" + _receivedCount); - } - - if (_connectionStopped && (_allFirstMessagesSent.getCount() == 0)) - { - _receivedCountWhileStopped++; - } - - if (_allFirstMessagesSent.getCount() == 0) - { - if (_receivedCount == (MSG_COUNT * 2)) - { - _allSecondMessagesSent.countDown(); - } - } - } - }); - - assertTrue("Connecion should not be started", !((AMQConnection) _clientConnection).started()); - _clientConnection.start(); - } - catch (JMSException e) - { - _logger.error("Error Setting Default ML on consumer1"); - } - - try - { - _allFirstMessagesSent.await(1000, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) - { - // do nothing - } - - try - { - assertTrue("Connecion should be started", ((AMQConnection) _clientConnection).started()); - _clientConnection.stop(); - _connectionStopped = true; - } - catch (JMSException e) - { - _logger.error("Error stopping connection"); - } - - try - { - _logger.error("Send additional messages"); - - for (int msg = 0; msg < MSG_COUNT; msg++) - { - _producer.send(_producerSession.createTextMessage("Message " + msg)); - } - } - catch (JMSException e) - { - _logger.error("Unable to send additional messages", e); - } - - try - { - Thread.sleep(1000); - } - catch (InterruptedException e) - { - // ignore - } - - try - { - _logger.info("Restarting connection"); - - _connectionStopped = false; - _clientConnection.start(); - } - catch (JMSException e) - { - _logger.error("Error Setting Better ML on consumer1", e); - } - - _logger.info("Waiting upto 2 seconds for messages"); - - try - { - _allSecondMessagesSent.await(1000, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) - { - // do nothing - } - - assertEquals("Messages not received correctly", 0, _allFirstMessagesSent.getCount()); - assertEquals("Messages not received correctly", 0, _allSecondMessagesSent.getCount()); - assertEquals("Client didn't get all messages", MSG_COUNT * 2, _receivedCount); - assertEquals("Messages received while stopped is not 0", 0, _receivedCountWhileStopped); - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(DispatcherTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java deleted file mode 100644 index 7461f6c200..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.client; - -/** - * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery - * queue

The message delivery process: Mina puts a message on _queue in AMQSession and the dispatcher thread - * take()s from here and dispatches to the _consumers. If the _consumer1 doesn't have a message listener set at - * connection start then messages are stored on _synchronousQueue (which needs to be > 1 to pass JMS TCK as multiple - * consumers on a session can run in any order and a synchronous put/poll will block the dispatcher).

When setting - * the message listener later the _synchronousQueue is just poll()'ed and the first message delivered the remaining - * messages will be left on the queue and lost, subsequent messages on the session will arrive first. - */ -public class MessageListenerMultiConsumerImmediatePrefetch extends MessageListenerMultiConsumerTest -{ - protected void setUp() throws Exception - { - System.setProperty(AMQSession.IMMEDIATE_PREFETCH, "true"); - super.setUp(); - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(MessageListenerMultiConsumerImmediatePrefetch.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java deleted file mode 100644 index 4fd10a0134..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.client; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.naming.Context; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery - * queue

The message delivery process: Mina puts a message on _queue in AMQSession and the dispatcher thread - * take()s from here and dispatches to the _consumers. If the _consumer1 doesn't have a message listener set at - * connection start then messages are stored on _synchronousQueue (which needs to be > 1 to pass JMS TCK as multiple - * consumers on a session can run in any order and a synchronous put/poll will block the dispatcher).

When setting - * the message listener later the _synchronousQueue is just poll()'ed and the first message delivered the remaining - * messages will be left on the queue and lost, subsequent messages on the session will arrive first. - */ -public class MessageListenerMultiConsumerTest extends QpidBrokerTestCase -{ - private static final Logger _logger = LoggerFactory.getLogger(MessageListenerMultiConsumerTest.class); - - private Context _context; - - private static final int MSG_COUNT = 6; - private int receivedCount1 = 0; - private int receivedCount2 = 0; - private Connection _clientConnection; - private MessageConsumer _consumer1; - private MessageConsumer _consumer2; - private Session _clientSession1; - private Queue _queue; - private final CountDownLatch _allMessagesSent = new CountDownLatch(2); // all messages Sent Lock - private static final String QUEUE_NAME = "queue" + UUID.randomUUID().toString(); - - protected void setUp() throws Exception - { - super.setUp(); - - // Create Client 1 - _clientConnection = getConnection("guest", "guest"); - - _clientConnection.start(); - - _clientSession1 = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - _queue =_clientSession1.createQueue(QUEUE_NAME); - - _consumer1 = _clientSession1.createConsumer(_queue); - - // Create Client 2 - Session clientSession2 = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - _consumer2 = clientSession2.createConsumer(_queue); - - // Create Producer - Connection producerConnection = getConnection("guest", "guest"); - - producerConnection.start(); - - Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - MessageProducer producer = producerSession.createProducer(_queue); - - for (int msg = 0; msg < MSG_COUNT; msg++) - { - producer.send(producerSession.createTextMessage("Message " + msg)); - } - - producerConnection.close(); - - } - - protected void tearDown() throws Exception - { - _clientConnection.close(); - super.tearDown(); - } - - public void testRecieveInterleaved() throws Exception - { - int msg = 0; - int MAX_LOOPS = MSG_COUNT * 2; - for (int loops = 0; (msg < MSG_COUNT) || (loops < MAX_LOOPS); loops++) - { - - if (_consumer1.receive(1000) != null) - { - msg++; - } - - if (_consumer2.receive(1000) != null) - { - msg++; - } - } - - assertEquals("Not all messages received.", MSG_COUNT, msg); - } - - public void testAsynchronousRecieve() throws Exception - { - _consumer1.setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _logger.info("Client 1 Received Message(" + receivedCount1 + "):" + message); - - receivedCount1++; - - if (receivedCount1 == (MSG_COUNT / 2)) - { - _allMessagesSent.countDown(); - } - - } - }); - - _consumer2.setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _logger.info("Client 2 Received Message(" + receivedCount2 + "):" + message); - - receivedCount2++; - if (receivedCount2 == (MSG_COUNT / 2)) - { - _allMessagesSent.countDown(); - } - } - }); - - _logger.info("Waiting upto 2 seconds for messages"); - - try - { - _allMessagesSent.await(4000, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) - { - // do nothing - } - - assertEquals(MSG_COUNT, receivedCount1 + receivedCount2); - } - - public void testRecieveC2Only() throws Exception - { - if ( - !Boolean.parseBoolean( - System.getProperties().getProperty(AMQSession.IMMEDIATE_PREFETCH, - AMQSession.IMMEDIATE_PREFETCH_DEFAULT))) - { - _logger.info("Performing Receive only on C2"); - for (int msg = 0; msg < MSG_COUNT; msg++) - { - assertTrue(MSG_COUNT + " msg should be received. Only received:" + msg, _consumer2.receive(1000) != null); - } - } - } - - public void testRecieveBoth() throws Exception - { - if ( - !Boolean.parseBoolean( - System.getProperties().getProperty(AMQSession.IMMEDIATE_PREFETCH, - AMQSession.IMMEDIATE_PREFETCH_DEFAULT))) - { - _logger.info("Performing Receive only with two consumers on one session "); - - //Create a new consumer on session one that we don't use - _clientSession1.createConsumer(_queue); - - int msg; - for (msg = 0; msg < (MSG_COUNT / 2); msg++) - { - - // Attempt to receive up to half the messages - // The other half may have gone to the consumer above - final Message message = _consumer1.receive(1000); - if(message == null) - { - break; - } - - } - - _consumer1.close(); - // This will close the unused consumer above. - _clientSession1.close(); - - - // msg will now have recorded the number received on session 1 - // attempt to retrieve the rest on session 2 - for (; msg < MSG_COUNT ; msg++) - { - assertTrue("Failed at msg id" + msg, _consumer2.receive(1000) != null); - } - - } - else - { - _logger.info("Performing Receive only on both C1 and C2"); - - for (int msg = 0; msg < (MSG_COUNT / 2); msg++) - { - - assertTrue(_consumer1.receive(3000) != null); - } - - for (int msg = 0; msg < (MSG_COUNT / 2); msg++) - { - assertTrue(_consumer2.receive(3000) != null); - } - } - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(MessageListenerMultiConsumerTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java deleted file mode 100644 index 142f301bd0..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.client; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.util.LogMonitor; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.naming.Context; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery - * queue

The message delivery process: Mina puts a message on _queue in AMQSession and the dispatcher thread - * take()s from here and dispatches to the _consumers. If the _consumer doesn't have a message listener set at - * connection start then messages are stored on _synchronousQueue (which needs to be > 1 to pass JMS TCK as multiple - * consumers on a session can run in any order and a synchronous put/poll will block the dispatcher).

When setting - * the message listener later the _synchronousQueue is just poll()'ed and the first message delivered the remaining - * messages will be left on the queue and lost, subsequent messages on the session will arrive first. - */ -public class MessageListenerTest extends QpidBrokerTestCase implements MessageListener, ExceptionListener -{ - private static final Logger _logger = LoggerFactory.getLogger(MessageListenerTest.class); - - private Context _context; - - private static final int MSG_COUNT = 5; - private int _receivedCount = 0; - private int _errorCount = 0; - private MessageConsumer _consumer; - private Connection _clientConnection; - private CountDownLatch _awaitMessages = new CountDownLatch(MSG_COUNT); - - protected void setUp() throws Exception - { - super.setUp(); - - // Create Client - _clientConnection = getConnection("guest", "guest"); - - _clientConnection.start(); - - Session clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - Queue queue =clientSession.createQueue("message-listener-test-queue"); - - _consumer = clientSession.createConsumer(queue); - - // Create Producer - - Connection producerConnection = getConnection("guest", "guest"); - - producerConnection.start(); - - Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - MessageProducer producer = producerSession.createProducer(queue); - - for (int msg = 0; msg < MSG_COUNT; msg++) - { - producer.send(producerSession.createTextMessage("Message " + msg)); - } - - producerConnection.close(); - - } - - protected void tearDown() throws Exception - { - if (_clientConnection != null) - { - _clientConnection.close(); - } - super.tearDown(); - } - - public void testSynchronousReceive() throws Exception - { - for (int msg = 0; msg < MSG_COUNT; msg++) - { - assertTrue(_consumer.receive(2000) != null); - } - } - - public void testSynchronousReceiveNoWait() throws Exception - { - for (int msg = 0; msg < MSG_COUNT; msg++) - { - assertTrue("Failed to receive message " + msg, _consumer.receiveNoWait() != null); - } - } - - public void testAsynchronousReceive() throws Exception - { - _consumer.setMessageListener(this); - - _logger.info("Waiting 3 seconds for messages"); - - try - { - _awaitMessages.await(3000, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) - { - // do nothing - } - // Should have received all async messages - assertEquals(MSG_COUNT, _receivedCount); - - } - - public void testReceiveThenUseMessageListener() throws Exception - { - _logger.error("Test disabled as initial receive is not called first"); - // Perform initial receive to start connection - assertTrue(_consumer.receive(2000) != null); - _receivedCount++; - - // Sleep to ensure remaining 4 msgs end up on _synchronousQueue - Thread.sleep(1000); - - // Set the message listener and wait for the messages to come in. - _consumer.setMessageListener(this); - - _logger.info("Waiting 3 seconds for messages"); - - try - { - _awaitMessages.await(3000, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) - { - // do nothing - } - // Should have received all async messages - assertEquals(MSG_COUNT, _receivedCount); - - _clientConnection.close(); - - Connection conn = getConnection("guest", "guest"); - Session clientSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - Queue queue = clientSession.createQueue("message-listener-test-queue"); - MessageConsumer cons = clientSession.createConsumer(queue); - conn.start(); - - // check that the messages were actually dequeued - assertTrue(cons.receive(2000) == null); - } - - /** - * Tests the case where the message listener throws an java.lang.Error. - * - */ - public void testMessageListenerThrowsError() throws Exception - { - final String javaLangErrorMessageText = "MessageListener failed with java.lang.Error"; - _clientConnection.setExceptionListener(this); - - _awaitMessages = new CountDownLatch(1); - - _consumer.setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - try - { - _logger.debug("onMessage called"); - _receivedCount++; - - - throw new Error(javaLangErrorMessageText); - } - finally - { - _awaitMessages.countDown(); - } - } - }); - - - _logger.info("Waiting 3 seconds for message"); - _awaitMessages.await(3000, TimeUnit.MILLISECONDS); - - assertEquals("onMessage should have been called", 1, _receivedCount); - assertEquals("onException should NOT have been called", 0, _errorCount); - - // Check that Error has been written to the application log. - - LogMonitor _monitor = new LogMonitor(_outputFile); - assertTrue("The expected message not written to log file.", - _monitor.waitForMessage(javaLangErrorMessageText, LOGMONITOR_TIMEOUT)); - - if (_clientConnection != null) - { - try - { - _clientConnection.close(); - } - catch (JMSException e) - { - // Ignore connection close errors for this test. - } - finally - { - _clientConnection = null; - } - } - } - - public void onMessage(Message message) - { - _logger.info("Received Message(" + _receivedCount + "):" + message); - - _receivedCount++; - _awaitMessages.countDown(); - } - - public void onException(JMSException e) - { - _logger.info("Exception received", e); - _errorCount++; - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(MessageListenerTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java deleted file mode 100644 index 6ff6681c47..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.client; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.naming.Context; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery - * queue

The message delivery process: Mina puts a message on _queue in AMQSession and the dispatcher thread - * take()s from here and dispatches to the _consumers. If the _consumer1 doesn't have a message listener set at - * connection start then messages are stored on _synchronousQueue (which needs to be > 1 to pass JMS TCK as multiple - * consumers on a session can run in any order and a synchronous put/poll will block the dispatcher).

When setting - * the message listener later the _synchronousQueue is just poll()'ed and the first message delivered the remaining - * messages will be left on the queue and lost, subsequent messages on the session will arrive first. - */ -public class ResetMessageListenerTest extends QpidBrokerTestCase -{ - private static final Logger _logger = LoggerFactory.getLogger(ResetMessageListenerTest.class); - - private Context _context; - - private static final int MSG_COUNT = 6; - private Connection _clientConnection, _producerConnection; - private MessageConsumer _consumer1; - private MessageProducer _producer; - private Session _clientSession, _producerSession; - - private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(MSG_COUNT); // all messages Sent Lock - private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(MSG_COUNT); // all messages Sent Lock - - protected void setUp() throws Exception - { - super.setUp(); - - _clientConnection = getConnection("guest", "guest"); - _clientConnection.start(); - // Create Client 1 - - _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - Queue queue = _clientSession.createQueue("reset-message-listener-test-queue"); - - _consumer1 = _clientSession.createConsumer(queue); - - // Create Producer - _producerConnection = getConnection("guest", "guest"); - - _producerConnection.start(); - - _producerSession = _producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - _producer = _producerSession.createProducer(queue); - - TextMessage m = _producerSession.createTextMessage(); - m.setStringProperty("rank", "first"); - for (int msg = 0; msg < MSG_COUNT; msg++) - { - m.setText("Message " + msg); - _producer.send(m); - } - } - - protected void tearDown() throws Exception - { - _clientConnection.close(); - - super.tearDown(); - } - - public void testAsynchronousRecieve() - { - - _logger.info("Test Start"); - - try - { - _consumer1.setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - try - { - if (message.getStringProperty("rank").equals("first")) - { - _allFirstMessagesSent.countDown(); - } - } - catch (JMSException e) - { - e.printStackTrace(); - fail("error receiving message"); - } - } - }); - } - catch (JMSException e) - { - _logger.error("Error Setting Default ML on consumer1"); - } - try - { - assertTrue("Did not receive all first batch of messages", - _allFirstMessagesSent.await(MSG_COUNT, TimeUnit.SECONDS)); - _logger.info("Received first batch of messages"); - } - catch (InterruptedException e) - { - // do nothing - } - - try - { - _clientConnection.stop(); - } - catch (JMSException e) - { - _logger.error("Error stopping connection"); - } - - _logger.info("Reset Message Listener "); - try - { - _consumer1.setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - try - { - if (message.getStringProperty("rank").equals("first")) - { - // Something ugly will happen, it'll probably kill the dispatcher - fail("All first set of messages should have been received"); - } - else - { - _allSecondMessagesSent.countDown(); - } - } - catch (JMSException e) - { - e.printStackTrace(); - // Something ugly will happen, it'll probably kill the dispatcher - fail("error receiving message"); - } - } - }); - - _clientConnection.start(); - } - catch (javax.jms.IllegalStateException e) - { - _logger.error("Connection not stopped while setting ML", e); - fail("Unable to change message listener:" + e.getCause()); - } - catch (JMSException e) - { - _logger.error("Error Setting Better ML on consumer1", e); - } - - try - { - _logger.info("Send additional messages"); - TextMessage m = _producerSession.createTextMessage(); - m.setStringProperty("rank", "second"); - for (int msg = 0; msg < MSG_COUNT; msg++) - { - m.setText("Message " + msg); - _producer.send(m); - } - } - catch (JMSException e) - { - _logger.error("Unable to send additional messages", e); - } - - _logger.info("Waiting for messages"); - - try - { - assertTrue(_allSecondMessagesSent.await(MSG_COUNT, TimeUnit.SECONDS)); - } - catch (InterruptedException e) - { - // do nothing - } - assertEquals("First batch of messages not received correctly", 0, _allFirstMessagesSent.getCount()); - assertEquals("Second batch of messages not received correctly", 0, _allSecondMessagesSent.getCount()); - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(ResetMessageListenerTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/SessionCreateTest.java b/java/systests/src/main/java/org/apache/qpid/client/SessionCreateTest.java index d7295b298e..08ed2258b2 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/SessionCreateTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/SessionCreateTest.java @@ -27,7 +27,6 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; import javax.jms.Connection; import javax.jms.Session; -import javax.naming.Context; /** @@ -35,9 +34,7 @@ import javax.naming.Context; */ public class SessionCreateTest extends QpidBrokerTestCase { - private static final Logger _logger = LoggerFactory.getLogger(MessageListenerTest.class); - - private Context _context; + private static final Logger LOGGER = LoggerFactory.getLogger(SessionCreateTest.class); private Connection _clientConnection; protected int maxSessions = 65555; @@ -54,7 +51,7 @@ public class SessionCreateTest extends QpidBrokerTestCase Session sess = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); assertNotNull(sess); sess.close(); - System.out.println("created session: " + i); + LOGGER.debug("created session: " + i); } _clientConnection.close(); diff --git a/java/systests/src/main/java/org/apache/qpid/client/SynchReceiveTest.java b/java/systests/src/main/java/org/apache/qpid/client/SynchReceiveTest.java new file mode 100644 index 0000000000..bf147197e4 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/SynchReceiveTest.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ +package org.apache.qpid.client; + +import javax.jms.Connection; +import javax.jms.MessageConsumer; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class SynchReceiveTest extends QpidBrokerTestCase +{ + private static final long AWAIT_MESSAGE_TIMEOUT = 2000; + private static final long AWAIT_MESSAGE_TIMEOUT_NEGATIVE = 250; + private static final int MSG_COUNT = 10; + private final String _testQueueName = getTestQueueName(); + private Connection _consumerConnection; + private Session _consumerSession; + private MessageConsumer _consumer; + private Queue _queue; + + protected void setUp() throws Exception + { + super.setUp(); + + _consumerConnection = getConnection(); + _consumerConnection.start(); + _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _queue = _consumerSession.createQueue(_testQueueName); + _consumer = _consumerSession.createConsumer(_queue); + + // Populate queue + Connection producerConnection = getConnection(); + Session producerSession = producerConnection.createSession(true, Session.SESSION_TRANSACTED); + sendMessage(producerSession, _queue, MSG_COUNT); + producerConnection.close(); + } + + public void testReceiveWithTimeout() throws Exception + { + for (int msg = 0; msg < MSG_COUNT; msg++) + { + assertNotNull("Expected message number " + msg, _consumer.receive(AWAIT_MESSAGE_TIMEOUT)); + } + + assertNull("Received too many messages", _consumer.receive(500)); + } + + public void testReceiveNoWait() throws Exception + { + for (int msg = 0; msg < MSG_COUNT; msg++) + { + assertNotNull("Expected message number " + msg, _consumer.receiveNoWait()); + } + + assertNull("Received too many messages", _consumer.receive(500)); + } + + public void testTwoConsumersInterleaved() throws Exception + { + //create a new connection with prefetch set to 1 + _consumerConnection.close(); + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); + + _consumerConnection = getConnection(); + _consumerConnection.start(); + Session consumerSession1 = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumer1 = consumerSession1.createConsumer(_queue); + + Session consumerSession2 = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumer2 = consumerSession2.createConsumer(_queue); + + final int maxLoops = MSG_COUNT * 2; + int msg = 0; + int loops = 0; + while(msg < MSG_COUNT && loops < maxLoops) + { + if (consumer1.receive(AWAIT_MESSAGE_TIMEOUT) != null) + { + msg++; + } + + if (consumer2.receive(AWAIT_MESSAGE_TIMEOUT) != null) + { + msg++; + } + + loops++; + } + + assertEquals("Not all messages received.", MSG_COUNT, msg); + assertNull("Received too many messages", consumer1.receive(AWAIT_MESSAGE_TIMEOUT_NEGATIVE)); + assertNull("Received too many messages", consumer2.receive(AWAIT_MESSAGE_TIMEOUT_NEGATIVE)); + } + + public void testIdleSecondConsumer() throws Exception + { + Session idleSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + @SuppressWarnings("unused") + MessageConsumer idleConsumerOnSameQueue = idleSession.createConsumer(_queue); + + // Since we don't call receive on the idle consumer, all messages will flow to other + + for (int msg = 0; msg < MSG_COUNT; msg++) + { + assertNotNull("Expected message number " + msg, _consumer.receive(AWAIT_MESSAGE_TIMEOUT)); + } + + assertNull("Received too many messages", _consumer.receive(AWAIT_MESSAGE_TIMEOUT_NEGATIVE)); + } + + +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/redelivered/RedeliveredMessageTest.java b/java/systests/src/main/java/org/apache/qpid/client/redelivered/RedeliveredMessageTest.java index cd74691035..0f12c8c7e6 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/redelivered/RedeliveredMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/redelivered/RedeliveredMessageTest.java @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.client.redelivered; import org.apache.qpid.test.utils.QpidBrokerTestCase; diff --git a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java index f337908134..ac29b72620 100644 --- a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java +++ b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java @@ -43,7 +43,7 @@ public class XAResourceTest extends QpidBrokerTestCase public void testIsSameRMSingleCF() throws Exception { XAConnectionFactory factory = getConnectionFactory(FACTORY_NAME); - XAConnection conn = factory.createXAConnection(); + XAConnection conn = factory.createXAConnection("guest","guest"); XASession session = conn.createXASession(); XAResource xaResource1 = session.getXAResource(); XAResource xaResource2 = session.getXAResource(); @@ -68,9 +68,9 @@ public class XAResourceTest extends QpidBrokerTestCase XAConnectionFactory factory2 = new AMQConnectionFactory(url); XAConnectionFactory factory3 = getConnectionFactory(ALT_FACTORY_NAME); - XAConnection conn = factory.createXAConnection(); - XAConnection conn2 = factory2.createXAConnection(); - XAConnection conn3 = factory3.createXAConnection(); + XAConnection conn = factory.createXAConnection("guest","guest"); + XAConnection conn2 = factory2.createXAConnection("guest","guest"); + XAConnection conn3 = factory3.createXAConnection("guest","guest"); XASession session = conn.createXASession(); XASession session2 = conn2.createXASession(); @@ -89,15 +89,6 @@ public class XAResourceTest extends QpidBrokerTestCase conn3.close(); } - @Override - public void stopBroker(int port) throws Exception - { - if (isBrokerPresent(port)) - { - super.stopBroker(port); - } - } - @Override public void tearDown() throws Exception { diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java index 0604955290..244e547e02 100644 --- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java @@ -20,6 +20,9 @@ package org.apache.qpid.management.jmx; import org.apache.commons.lang.time.FastDateFormat; +import org.apache.log4j.Logger; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.server.queue.AMQQueueMBean; import org.apache.qpid.test.utils.JMXTestUtils; @@ -27,15 +30,25 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; import javax.jms.Connection; import javax.jms.Destination; +import javax.jms.JMSException; import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; import javax.jms.Session; -import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.CompositeData; import javax.management.openmbean.TabularData; + +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /** * Tests the JMX API for the Managed Queue. @@ -43,17 +56,41 @@ import java.util.Map; */ public class ManagedQueueMBeanTest extends QpidBrokerTestCase { - /** - * JMX helper. - */ + protected static final Logger LOGGER = Logger.getLogger(ManagedQueueMBeanTest.class); + private JMXTestUtils _jmxUtils; + private Connection _connection; + private Session _session; + + private String _sourceQueueName; + private String _destinationQueueName; + private Destination _sourceQueue; + private Destination _destinationQueue; + private ManagedQueue _managedSourceQueue; + private ManagedQueue _managedDestinationQueue; public void setUp() throws Exception { _jmxUtils = new JMXTestUtils(this); _jmxUtils.setUp(); + super.setUp(); + _sourceQueueName = getTestQueueName() + "_src"; + _destinationQueueName = getTestQueueName() + "_dest"; + + _connection = getConnection(); + _connection.start(); + + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + _sourceQueue = _session.createQueue(_sourceQueueName); + _destinationQueue = _session.createQueue(_destinationQueueName); + createQueueOnBroker(_sourceQueue); + createQueueOnBroker(_destinationQueue); + _jmxUtils.open(); + + _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName); + _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName); } public void tearDown() throws Exception @@ -70,28 +107,18 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase */ public void testViewSingleMessage() throws Exception { - final String queueName = getTestQueueName(); - - // Create queue and send numMessages messages to it. - final Connection con = getConnection(); - final Session session = con.createSession(true, Session.SESSION_TRANSACTED); - final Destination dest = session.createQueue(queueName); - session.createConsumer(dest).close(); // Create a consumer only to cause queue creation - - final List sentMessages = sendMessage(session, dest, 1); + final List sentMessages = sendMessage(_session, _sourceQueue, 1); + syncSession(_session); final Message sentMessage = sentMessages.get(0); - // Obtain the management interface. - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNotNull("ManagedQueue expected to be available", managedQueue); - assertEquals("Unexpected queue depth", 1, managedQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue()); // Check the contents of the message - final TabularData tab = managedQueue.viewMessages(1l, 1l); + final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l); assertEquals("Unexpected number of rows in table", 1, tab.size()); - final Iterator rowItr = (Iterator) tab.values().iterator(); + final Iterator rowItr = (Iterator) tab.values().iterator(); - final CompositeDataSupport row1 = rowItr.next(); + final CompositeData row1 = rowItr.next(); assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID)); assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS)); assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED)); @@ -108,6 +135,184 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp")); } + /** + * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface. + */ + public void testMoveMessagesBetweenQueues() throws Exception + { + final int numberOfMessagesToSend = 10; + + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + // Move first three messages to destination + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(2); + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + + assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue()); + + // Now move a further two messages to destination + fromMessageId = amqMessagesIds.get(7); + toMessageId = amqMessagesIds.get(8); + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue()); + + assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); + } + + /** + * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface. + */ + public void testCopyMessagesBetweenQueues() throws Exception + { + final int numberOfMessagesToSend = 10; + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + // Copy first three messages to destination + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(2); + _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); + + assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + // Now copy a further two messages to destination + fromMessageId = amqMessagesIds.get(7); + toMessageId = amqMessagesIds.get(8); + _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); + assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); + } + + public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception + { + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); + Connection asyncConnection = getConnection(); + asyncConnection.start(); + + final int numberOfMessagesToSend = 50; + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); + + CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2); + AtomicInteger totalConsumed = new AtomicInteger(0); + startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed); + + boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS); + assertTrue("Did not read half of messages within time allowed", halfwayPointReached); + + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + + asyncConnection.stop(); + + // The exact number of messages moved will be non deterministic, as the number of messages processed + // by the consumer cannot be predicited. There is also the possibility that a message can remain + // on the source queue. This situation will arise if a message has been acquired by the consumer, but not + // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs. + // + // The number of messages moved + the number consumed + any messages remaining on source should + // *always* be equal to the number we originally sent. + + int numberOfMessagesReadByConsumer = totalConsumed.intValue(); + int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue(); + int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue(); + + LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer + + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue + + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue); + assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue); + } + + public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception + { + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); + Connection asyncConnection = getConnection(); + asyncConnection.start(); + + final int numberOfMessagesToSend = 50; + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); + + AtomicInteger totalConsumed = new AtomicInteger(0); + CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend); + startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed); + + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + + allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS); + assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue()); + } + + private void startAsyncConsumerOn(Destination queue, Connection asyncConnection, + final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception + { + Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumer = session.createConsumer(queue); + consumer.setMessageListener(new MessageListener() + { + + @Override + public void onMessage(Message arg0) + { + totalConsumed.incrementAndGet(); + requiredNumberOfMessagesRead.countDown(); + } + }); + } + + private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception + { + MessageConsumer consumer = _session.createConsumer(queue); + + for (int i : expectedIndices) + { + Message message = consumer.receive(1000); + assertNotNull("Expected message with index " + i, message); + assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX)); + } + + assertNull("Unexpected message encountered", consumer.receive(1000)); + } + + private List getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception + { + final SortedSet messageIds = new TreeSet(); + + final TabularData tab = managedQueue.viewMessages(startIndex, endIndex); + final Iterator rowItr = (Iterator) tab.values().iterator(); + while(rowItr.hasNext()) + { + final CompositeData row = rowItr.next(); + long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID); + messageIds.add(amqMessageId); + } + + return new ArrayList(messageIds); + } + /** * * Utility method to convert array of Strings in the form x = y into a @@ -126,4 +331,15 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase } return headerMap; } + + private void createQueueOnBroker(Destination destination) throws JMSException + { + _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation + } + + private void syncSession(Session session) throws Exception + { + ((AMQSession)session).sync(); + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/ra/QpidRAConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/ra/QpidRAConnectionTest.java new file mode 100644 index 0000000000..0ca90ac2ea --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/ra/QpidRAConnectionTest.java @@ -0,0 +1,89 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.ra; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.Message; +import javax.jms.Session; + +import org.apache.qpid.ra.QpidRAConnectionFactoryImpl; +import org.apache.qpid.ra.QpidRAManagedConnectionFactory; +import org.apache.qpid.ra.QpidResourceAdapter; + +public class QpidRAConnectionTest extends QpidBrokerTestCase +{ + private static final String BROKER_PORT = "15672"; + + private static final String URL = "amqp://guest:guest@client/test?brokerlist='tcp://localhost:" + BROKER_PORT + "?sasl_mechs='PLAIN''"; + + public void testSessionCommitOnClosedConnectionThrowsException() throws Exception + { + QpidResourceAdapter ra = new QpidResourceAdapter(); + QpidRAManagedConnectionFactory mcf = new QpidRAManagedConnectionFactory(); + mcf.setConnectionURL(URL); + mcf.setResourceAdapter(ra); + ConnectionFactory cf = new QpidRAConnectionFactoryImpl(mcf, null); + Connection c = cf.createConnection(); + Session s = c.createSession(true, Session.SESSION_TRANSACTED); + c.close(); + + try + { + s.commit(); + fail("Exception should be thrown"); + } + catch(Exception e) + { + e.printStackTrace(); + assertTrue(e instanceof javax.jms.IllegalStateException); + } + + } + + public void testMessageAck() throws Exception + { + QpidResourceAdapter ra = new QpidResourceAdapter(); + QpidRAManagedConnectionFactory mcf = new QpidRAManagedConnectionFactory(); + mcf.setConnectionURL(URL); + mcf.setResourceAdapter(ra); + ConnectionFactory cf = new QpidRAConnectionFactoryImpl(mcf, null); + Connection c = cf.createConnection(); + Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE); + Message m = s.createTextMessage(); + + try + { + m.acknowledge(); + } + catch(Exception e) + { + fail("Acknowledge should not throw an exception"); + } + finally + { + s.close(); + c.close(); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java b/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java index c42bb3b1fa..0e3a658e32 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java @@ -77,6 +77,7 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase public void testDisabling010() throws Exception { //disable 0-10 support + setConfigurationProperty("connector.amqp10enabled", "false"); setConfigurationProperty("connector.amqp010enabled", "false"); super.setUp(); @@ -92,6 +93,7 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase public void testDisabling091and010() throws Exception { //disable 0-91 and 0-10 support + setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false"); @@ -111,6 +113,7 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP09ENABLED, "false"); setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false"); setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); + setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); super.setUp(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java deleted file mode 100644 index 4a92f04b30..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.exchange; - -import org.apache.qpid.jms.Session; -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -/** - * MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology, - * and test parameters for running a messaging test over that topology. A Properties object holding some of these - * properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour. - * - *

A complete list of the parameters, default values and comments on their usage is provided here: - * - *

- *
Parameters
Parameter Default Comments - *
messageSize 0 Message size in bytes. Not including any headers. - *
destinationName ping The root name to use to generate destination names to ping. - *
persistent false Determines whether peristent delivery is used. - *
transacted false Determines whether messages are sent/received in transactions. - *
broker tcp://localhost:5672 Determines the broker to connect to. - *
virtualHost test Determines the virtual host to send all ping over. - *
rate 0 The maximum rate (in hertz) to send messages at. 0 means no limit. - *
verbose false The verbose flag for debugging. Prints to console on every message. - *
pubsub false Whether to ping topics or queues. Uses p2p by default. - *
username guest The username to access the broker with. - *
password guest The password to access the broker with. - *
selector null Not used. Defines a message selector to filter pings with. - *
destinationCount 1 The number of receivers listening to the pings. - *
timeout 30000 In milliseconds. The timeout to stop waiting for replies. - *
commitBatchSize 1 The number of messages per transaction in transactional mode. - *
uniqueDests true Whether each receiver only listens to one ping destination or all. - *
durableDests false Whether or not durable destinations are used. - *
ackMode AUTO_ACK The message acknowledgement mode. Possible values are: - * 0 - SESSION_TRANSACTED - * 1 - AUTO_ACKNOWLEDGE - * 2 - CLIENT_ACKNOWLEDGE - * 3 - DUPS_OK_ACKNOWLEDGE - * 257 - NO_ACKNOWLEDGE - * 258 - PRE_ACKNOWLEDGE - *
maxPending 0 The maximum size in bytes, of messages sent but not yet received. - * Limits the volume of messages currently buffered on the client - * or broker. Can help scale test clients by limiting amount of buffered - * data to avoid out of memory errors. - *
- * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide the names and defaults of all test parameters. - *
- */ -public class MessagingTestConfigProperties -{ - // ====================== Connection Properties ================================== - - /** Holds the name of the default connection configuration. */ - public static final String CONNECTION_NAME = "broker"; - - /** Holds the name of the property to get the initial context factory name from. */ - public static final String INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial"; - - /** Defines the class to use as the initial context factory by default. */ - public static final String INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"; - - /** Holds the name of the default connection factory configuration property. */ - public static final String CONNECTION_PROPNAME = "connectionfactory.broker"; - - /** Holds the name of the property to get the test broker url from. */ - public static final String BROKER_PROPNAME = "qpid.test.broker"; - - /** Holds the name of the property to get the test broker virtual path. */ - public static final String VIRTUAL_HOST_PROPNAME = "virtualHost"; - - /** Holds the default virtual path for the test. */ - public static final String VIRTUAL_HOST_DEFAULT = ""; - - /** Holds the name of the property to get the broker access username from. */ - public static final String USERNAME_PROPNAME = "username"; - - /** Holds the default broker log on username. */ - public static final String USERNAME_DEFAULT = "guest"; - - /** Holds the name of the property to get the broker access password from. */ - public static final String PASSWORD_PROPNAME = "password"; - - /** Holds the default broker log on password. */ - public static final String PASSWORD_DEFAULT = "guest"; - - // ====================== Messaging Topology Properties ========================== - - /** Holds the name of the property to get the bind publisher procuder flag from. */ - public static final String PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind"; - - /** Holds the default value of the publisher producer flag. */ - public static final boolean PUBLISHER_PRODUCER_BIND_DEFAULT = true; - - /** Holds the name of the property to get the bind publisher procuder flag from. */ - public static final String PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind"; - - /** Holds the default value of the publisher consumer flag. */ - public static final boolean PUBLISHER_CONSUMER_BIND_DEFAULT = false; - - /** Holds the name of the property to get the bind receiver procuder flag from. */ - public static final String RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind"; - - /** Holds the default value of the receiver producer flag. */ - public static final boolean RECEIVER_PRODUCER_BIND_DEFAULT = false; - - /** Holds the name of the property to get the bind receiver procuder flag from. */ - public static final String RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind"; - - /** Holds the default value of the receiver consumer flag. */ - public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true; - - /** Holds the name of the property to get the destination name root from. */ - public static final String SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot"; - - /** Holds the root of the name of the default destination to send to. */ - public static final String SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo"; - - /** Holds the name of the property to get the destination name root from. */ - public static final String RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot"; - - /** Holds the root of the name of the default destination to send to. */ - public static final String RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom"; - - /** Holds the name of the proeprty to get the destination count from. */ - public static final String DESTINATION_COUNT_PROPNAME = "destinationCount"; - - /** Defines the default number of destinations to ping. */ - public static final int DESTINATION_COUNT_DEFAULT = 1; - - /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */ - public static final String PUBSUB_PROPNAME = "pubsub"; - - /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */ - public static final boolean PUBSUB_DEFAULT = false; - - // ====================== JMS Options and Flags ================================= - - /** Holds the name of the property to get the test delivery mode from. */ - public static final String PERSISTENT_MODE_PROPNAME = "persistent"; - - /** Holds the message delivery mode to use for the test. */ - public static final boolean PERSISTENT_MODE_DEFAULT = false; - - /** Holds the name of the property to get the test transactional mode from. */ - public static final String TRANSACTED_PROPNAME = "transacted"; - - /** Holds the transactional mode to use for the test. */ - public static final boolean TRANSACTED_DEFAULT = false; - - /** Holds the name of the property to set the no local flag from. */ - public static final String NO_LOCAL_PROPNAME = "noLocal"; - - /** Defines the default value of the no local flag to use when consuming messages. */ - public static final boolean NO_LOCAL_DEFAULT = false; - - /** Holds the name of the property to get the message acknowledgement mode from. */ - public static final String ACK_MODE_PROPNAME = "ackMode"; - - /** Defines the default message acknowledgement mode. */ - public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE; - - /** Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. */ - public static final String DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription"; - - /** Defines the default value of the durable subscriptions flag. */ - public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false; - - // ====================== Qpid Options and Flags ================================ - - /** Holds the name of the property to set the exclusive flag from. */ - public static final String EXCLUSIVE_PROPNAME = "exclusive"; - - /** Defines the default value of the exclusive flag to use when consuming messages. */ - public static final boolean EXCLUSIVE_DEFAULT = false; - - /** Holds the name of the property to set the immediate flag from. */ - public static final String IMMEDIATE_PROPNAME = "immediate"; - - /** Defines the default value of the immediate flag to use when sending messages. */ - public static final boolean IMMEDIATE_DEFAULT = false; - - /** Holds the name of the property to set the mandatory flag from. */ - public static final String MANDATORY_PROPNAME = "mandatory"; - - /** Defines the default value of the mandatory flag to use when sending messages. */ - public static final boolean MANDATORY_DEFAULT = false; - - /** Holds the name of the property to get the durable destinations flag from. */ - public static final String DURABLE_DESTS_PROPNAME = "durableDests"; - - /** Default value for the durable destinations flag. */ - public static final boolean DURABLE_DESTS_DEFAULT = false; - - /** Holds the name of the proeprty to set the prefetch size from. */ - public static final String PREFECTH_PROPNAME = "prefetch"; - - /** Defines the default prefetch size to use when consuming messages. */ - public static final int PREFETCH_DEFAULT = 100; - - // ====================== Common Test Parameters ================================ - - /** Holds the name of the property to get the test message size from. */ - public static final String MESSAGE_SIZE_PROPNAME = "messageSize"; - - /** Used to set up a default message size. */ - public static final int MESSAGE_SIZE_DEAFULT = 0; - - /** Holds the name of the property to get the message rate from. */ - public static final String RATE_PROPNAME = "rate"; - - /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */ - public static final int RATE_DEFAULT = 0; - - /** Holds the name of the proeprty to get the. */ - public static final String SELECTOR_PROPNAME = "selector"; - - /** Holds the default message selector. */ - public static final String SELECTOR_DEFAULT = ""; - - /** Holds the name of the property to get the waiting timeout for response messages. */ - public static final String TIMEOUT_PROPNAME = "timeout"; - - /** Default time to wait before assuming that a ping has timed out. */ - public static final long TIMEOUT_DEFAULT = 30000; - - /** Holds the name of the property to get the commit batch size from. */ - public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize"; - - /** Defines the default number of pings to send in each transaction when running transactionally. */ - public static final int TX_BATCH_SIZE_DEFAULT = 1; - - /** Holds the name of the property to set the maximum amount of pending message data for a producer to hold. */ - public static final String MAX_PENDING_PROPNAME = "maxPending"; - - /** Defines the default maximum quantity of pending message data to allow producers to hold. */ - public static final int MAX_PENDING_DEFAULT = 0; - - /** Holds the name of the property to get the verbose mode proeprty from. */ - public static final String VERBOSE_PROPNAME = "verbose"; - - /** Holds the default verbose mode. */ - public static final boolean VERBOSE_DEFAULT = false; - - /** Holds the default configuration properties. */ - public static ParsedProperties defaults = new ParsedProperties(); - - static - { - defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT); - defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT); - defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT); - defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT); - defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT); - defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT); - defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT); - defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT); - defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT); - defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT); - defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT); - defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT); - defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT); - defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT); - defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT); - defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT); - defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT); - defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT); - defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT); - defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT); - defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT); - defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT); - defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT); - defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT); - defaults.setPropertyIfNull(PREFECTH_PROPNAME, PREFETCH_DEFAULT); - defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT); - defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT); - defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT); - defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java index 2a1895d6c8..3d116f1b1b 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java @@ -241,7 +241,7 @@ public class ReturnUnroutableMandatoryMessageTest extends QpidBrokerTestCase imp con2.start(); MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_topic, false, false); - MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic); + MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic, false, true); // First test - should be routed _logger.info("Sending non-mandatory message"); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java deleted file mode 100644 index e32edff692..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.logging; - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; - -import javax.jms.Connection; -import javax.jms.Queue; -import javax.jms.Session; -import java.io.File; -import java.util.List; - -/** - * The MessageStore test suite validates that the follow log messages as - * specified in the Functional Specification. - * - * This suite of tests validate that the MessageStore messages occur correctly - * and according to the following format: - * - * MST-1001 : Created : - * MST-1003 : Closed - * - * NOTE: Only for Persistent Stores - * MST-1002 : Store location : - * MST-1004 : Recovery Start [: ] - * MST-1005 : Recovered messages for queue - * MST-1006 : Recovery Complete [: ] - */ -public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest -{ - - @Override - public void setUp() throws Exception - { - super.setUp(); - // MemoryMessageStoreLoggingTest setUp itself does not call super.setUp - //We call super.setUp but this will not start the broker as that is - //part of the test case. - - // Load the default configuration file to get the list of defined vhosts - ServerConfiguration configuration = new ServerConfiguration(new File(_configFile.getParent() + "/config.xml")); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - // Make them all persistent i.e. Use DerbyMessageStore and - // test that it logs correctly. - for (String vhost : vhosts) - { - makeVirtualHostPersistent(vhost); - } - } - - /** - * Description: - * Persistent MessageStores will require space on disk to persist the data. - * This value will be logged on startup after the MessageStore has been - * created. - * Input: - * Default configuration - * Output: - * - * MST-1002 : Store location : - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. This must occur after MST-1001 - */ - public void testMessageStoreStoreLocation() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - startBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1002"); - - assertEquals("Each vhost did not close its store.", vhosts.size(), results.size()); - - for (int index = 0; index < results.size(); index++) - { - String result = getLogMessage(results, index);; - - // getSlize will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // To get the store class used in the configuration we need to know - // the virtualhost name, found above. AND - // the index that the virtualhost is within the configuration. - // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertTrue("MST-1002 does not contain a store path" + getMessageString(result), - getMessageString(result).length() > 0); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - } - } - - /** - * Description: - * Persistent message stores may have state on disk that they must recover - * during startup. As the MessageStore starts up it will report that it is - * about to start the recovery process by logging MST-1004. This message - * will always be logged for persistent MessageStores. If there is no data - * to recover then there will be no subsequent recovery messages. - * Input: - * Default persistent configuration - * Output: - * MST-1004 : Recovery Start - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. The MessageStore must have first logged a creation event. - */ - public void testMessageStoreRecoveryStart() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - startBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1004"); - - assertTrue("Each vhost did not close its store.", vhosts.size() <= results.size()); - - for (int index = 0; index < results.size(); index++) - { - String result = getLogMessage(results, index);; - - if (getMessageString(result).contains("Recovery Start :")) - { - //Don't test queue start recoveries - continue; - } - - // getSlize will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // To get the store class used in the configuration we need to know - // the virtualhost name, found above. AND - // the index that the virtualhost is within the configuration. - // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertEquals("MST-1004 does have expected message", "Recovery Start", - getMessageString(result)); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - } - } - - /** - * Description: - * Once all persistent queues have been recovered and the MessageStore has completed all recovery it must logged that the recovery process has completed. - * Input: - * Default persistent configuration - * Output: - * - * MST-1006 : Recovery Complete - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. This is the last message from the MessageStore during startup. - * 3. This must be proceeded by a MST-1006 Recovery Start. - */ - public void testMessageStoreRecoveryComplete() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - startBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1006"); - - assertTrue("Each vhost did not close its store.", vhosts.size() <= results.size()); - - for (int index = 0; index < results.size(); index++) - { - String result = getLogMessage(results, index); - - if (getMessageString(result).contains("Recovery Complete :")) - { - //Don't test queue start recoveries - continue; - } - - // getSlize will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // To get the store class used in the configuration we need to know - // the virtualhost name, found above. AND - // the index that the virtualhost is within the configuration. - // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertEquals("MST-1006 does have expected message", "Recovery Complete", - getMessageString(result)); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - } - } - - /** - * Description: - * A persistent MessageStore may have data to recover from disk. The message store will use MST-1004 to report the start of recovery for a specific queue that it has previously persisted. - * Input: - * Default persistent configuration - * Output: - * - * MST-1004 : Recovery Start : - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. This must occur after the recovery start MST-1004 has been logged. - */ - public void testMessageStoreQueueRecoveryStart() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - startBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1004 : Recovery Start :"); - - // We are only looking for the default queue defined in local host being - // recovered. If other tests have made queues in test then we want to - // exclude them here. - results = filterResultsByVirtualHost(results, "/localhost"); - - assertEquals("Recovered test queue not found.", 1, results.size()); - - String result = getLogMessage(results, 0); - - // getSlize will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // To get the store class used in the configuration we need to know - // the virtualhost name, found above. AND - // the index that the virtualhost is within the configuration. - // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertTrue("MST-1006 does end with queue 'test-queue':" + getMessageString(result), - getMessageString(result).endsWith("test-queue")); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - - } - - /** - * Description: - * After the queue has been recovered the store will log that recovery has been completed. The MessageStore must not report further status about the recovery of this queue after this message. In addition every MST-1004 queue recovery start message must be matched with a MST-1006 recovery complete. - * Input: - * Default persistent configuration - * Output: - * - * MST-1006 : Recovery Complete : - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. This must occur after the queue recovery start MST-1004 has been logged. - * 3. The queue.name is non-empty - * 4. The queue.name correlates with a previous recovery start - */ - public void testMessageStoreQueueRecoveryComplete() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - startBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1006 : Recovery Complete :"); - - // We are only looking for the default queue defined in local host being - // recovered. If other tests have made queues in test then we want to - // exclude them here. - results = filterResultsByVirtualHost(results, "/localhost"); - - assertEquals("Recovered test queue not found.", 1, results.size()); - - String result = getLogMessage(results, 0); - - // getSlize will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // To get the store class used in the configuration we need to know - // the virtualhost name, found above. AND - // the index that the virtualhost is within the configuration. - // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertTrue("MST-1006 does end with queue 'test-queue':" + getMessageString(result), - getMessageString(result).endsWith("test-queue")); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - - results = findMatches("MST-1004 : Recovery Start : test-queue"); - - assertEquals("MST-1004 for test-queue not found", 1, results.size()); - } - - /** - * Description: - * A persistent queue must be persisted so that on recovery it can be restored independently of any messages that may be stored on it. This test verifies that the MessageStore will log that it has recovered 0 messages for persistent queues that do not have any messages. - * Input: - * - * 1. Default persistent configuration - * 2. Persistent queue with no messages enqueued - * Output: - * - * MST-1005 : Recovered 0 messages for queue - * - * Validation Steps: - * 3. The MST ID is correct - * 4. This must occur after the queue recovery start MST-1004 has been logged. - * 5. The count is 0 - * 6. 'messages' is correctly printed - * 7. The queue.name is non-empty - */ - public void testMessageStoreQueueRecoveryCountEmpty() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - String queueName = getTestQueueName(); - - startBroker(); - Connection connetion = getConnection(); - Session session = connetion.createSession(false, Session.AUTO_ACKNOWLEDGE); - Queue queue = session.createQueue("direct://amq.direct/" + queueName + "/" + queueName + "?durable='true'"); - - session.createConsumer(queue).close(); - - // Stop the broker so that we can test recovery - stopBroker(); - - int COUNT = 0; - testDurableRecoveryCount(COUNT, queueName); - } - - /** - * Description: - * On recovery all the persistent messages that are stored on disk must be returned to the queue. MST-1005 will report the number of messages that have been recovered from disk. - * Input: - * - * 1. Default persistent configuration - * 2. Persistent queue with multiple messages enqueued - * Output: - * - * MST-1005 : Recovered messages for queue - * - * Validation Steps: - * 3. The MST ID is correct - * 4. This must occur after the queue recovery start MST-1004 has been logged. - * 5. The count is > 1 - * 6. 'messages' is correctly printed - * 7. The queue.name is non-empty - */ - public void testMessageStoreQueueRecoveryCountPlural() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - String queueName = getTestQueueName(); - - int COUNT = 10; - - testDurableRecoveryCount(COUNT, queueName); - } - - /** - * Send a set number of messages to a new durable queue, as specified. Then - * restart the broker and validate that they are restored. - * - * @param COUNT - the count to send - * @param queueName - the new queue name - * @throws Exception - if a problem occured. - */ - private void testDurableRecoveryCount(int COUNT, String queueName) throws Exception - { - startBroker(); - Connection connetion = getConnection(); - Session session = connetion.createSession(false, Session.AUTO_ACKNOWLEDGE); - Queue queue = session.createQueue("direct://amq.direct/" + queueName + "/" + queueName + "?durable='true'"); - - session.createConsumer(queue).close(); - - sendMessage(session, queue, COUNT); - try - { - connetion.close(); - - stopBroker(); - - // Clear our monitor - _monitor.markDiscardPoint(); - - startBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1004 : Recovery Start : " + queueName); - - assertEquals("Recovered test queue not found.", 1, results.size()); - - String result = getLogMessage(results, 0); - - validateMessageID("MST-1004", result); - - assertTrue("MST-1004 does end with queue '" + queueName + "':" + getMessageString(result), - getMessageString(result).endsWith(queueName)); - - results = waitAndFindMatches("MST-1005"); - - assertTrue("Insufficient MST-1005 logged.", results.size()>0); - - result = null; - - // If the first message is not our queue the second one will be - for(String resultEntry : results) - { - // Look for first match and set that to result - if (resultEntry.contains(queueName)) - { - result = getLog(resultEntry); - break; - } - } - - assertNotNull("MST-1005 entry for queue:" + queueName + ". Not found", result); - - // getSlize will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // To get the store class used in the configuration we need to know - // the virtualhost name, found above. AND - // the index that the virtualhost is within the configuration. - // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertTrue("MST-1005 does end with queue 'test-queue':" + getMessageString(result), - getMessageString(result).endsWith(queueName)); - - assertTrue("MST-1005 does end show correct count:" + getMessageString(result), - getMessageString(result).contains("Recovered " + COUNT + " messages")); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - } - finally - { - //Ensure we attempt to drain the queue. - assertEquals("Unable to drain queue", COUNT, drainQueue(queue)); - } - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java deleted file mode 100644 index e6e1196cc6..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* -* -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -* -*/ -package org.apache.qpid.server.logging; - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; -import org.apache.qpid.util.LogMonitor; - -import java.util.Arrays; -import java.util.List; - -/** - * The MessageStore test suite validates that the follow log messages as - * specified in the Functional Specification. - * - * This suite of tests validate that the MessageStore messages occur correctly - * and according to the following format: - * - * MST-1001 : Created : - * MST-1003 : Closed - * - * NOTE: Only for Persistent Stores - * MST-1002 : Store location : - * MST-1004 : Recovery Start [: ] - * MST-1005 : Recovered messages for queue - * MST-1006 : Recovery Complete [: ] - */ -public class MemoryMessageStoreLoggingTest extends AbstractTestLogging -{ - protected static final String MESSAGES_STORE_PREFIX = "MST-"; - - public void setUp() throws Exception - { - //We explicitly do not call super.setUp as starting up the broker is - //part of the test case. - // So we have to make the new Log Monitor here - - _monitor = new LogMonitor(_outputFile); - } - - /** - * Description: - * During Virtualhost startup a MessageStore will be created. The first MST - * message that must be logged is the MST-1001 MessageStore creation. - * Input: - * Default configuration - * Output: - * MST-1001 : Created : - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. The is the correct MessageStore type as specified in the Default configuration - * - * @throws Exception caused by broker startup - */ - public void testMessageStoreCreation() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - super.setUp(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - String log = getLogMessage(results, 0); - //1 - assertEquals("MST-1001 is not the first MST message", "MST-1001", getMessageID(fromMessage(log))); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1001"); - - // Load VirtualHost list from file. - List vhosts = Arrays.asList(getServerConfig().getVirtualHosts()); - - assertEquals("Each vhost did not create a store.", vhosts.size(), results.size()); - - for (int index = 0; index < results.size(); index++) - { - String result = getLogMessage(results, index); - - // getSlice will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // Get the store class used in the configuration for the virtualhost. - String fullStoreName = getServerConfig().getVirtualHostConfig(vhostName).getMessageStoreClass(); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertTrue("MST-1001 does not contains correct store name:" - + storeName + ":" + result, getMessageString(result).endsWith(storeName)); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - } - } - - /** - * Description: - * During shutdown the MessageStore will also cleanly close. When this has - * completed a MST-1003 closed message will be logged. No further messages - * from this MessageStore will be logged after this message. - * - * Input: - * Default configuration - * Output: - * MST-1003 : Closed - * - * Validation Steps: - * - * 1. The MST ID is correct - * 2. This is teh last log message from this MessageStore - * - * @throws Exception caused by broker startup - */ - public void testMessageStoreClose() throws Exception - { - assertLoggingNotYetOccured(MESSAGES_STORE_PREFIX); - - super.setUp(); - - //Stop the broker so we get the close messages. - stopBroker(); - - List results = waitAndFindMatches(MESSAGES_STORE_PREFIX); - - // Validation - - assertTrue("MST messages not logged", results.size() > 0); - - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List vhosts = Arrays.asList(configuration.getVirtualHosts()); - - //Validate each vhost logs a creation - results = waitAndFindMatches("MST-1003"); - - assertEquals("Each vhost did not close its store.", vhosts.size(), results.size()); - - for (int index = 0; index < results.size(); index++) - { - String result = getLogMessage(results, index); - - // getSlice will return extract the vhost from vh(/test) -> '/test' - // so remove the '/' to get the name - String vhostName = AbstractTestLogSubject.getSlice("vh", result).substring(1); - - // Get the store class used in the configuration for the virtualhost. - String fullStoreName = configuration.getVirtualHostConfig(vhostName).getMessageStoreClass(); - - // Get the Simple class name from the expected class name of o.a.q.s.s.MMS - String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); - - assertEquals("MST-1003 does not close:", - "Closed", getMessageString(result)); - - assertEquals("The store name does not match expected value", - storeName, AbstractTestLogSubject.getSlice("ms", fromSubject(result))); - } - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java index ddcb96b4db..236202f323 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.logging; +import javax.jms.QueueBrowser; import junit.framework.AssertionFailedError; import org.apache.qpid.client.AMQConnection; @@ -166,8 +167,10 @@ public class SubscriptionLoggingTest extends AbstractTestLogging */ public void testSubscriptionCreateQueueBrowser() throws JMSException, IOException { - _session.createBrowser(_queue); + _connection.start(); + QueueBrowser browser = _session.createBrowser(_queue); + browser.getEnumeration(); //Validate //Ensure that we wait for the SUB log message waitAndFindMatches("SUB-1001"); diff --git a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java index 2e259191aa..bcad59a1fa 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java @@ -42,7 +42,7 @@ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase protected final String MY_TOPIC_SUBSCRIPTION_NAME = this.getName(); protected static final int SEND_COUNT = 10; - public void test() throws Exception + public void testNoLocalNotQueued() throws Exception { if(!isBrokerStorePersistent()) { @@ -66,6 +66,8 @@ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase // Check messages can be received as expected. connection.start(); + //As the no-local subscriber was on the same connection the messages were + //published on, tit will receive no messages as they will be discarded on the broker List received = receiveMessage(noLocalSubscriber, SEND_COUNT); assertEquals("No Local Subscriber Received messages", 0, received.size()); @@ -73,10 +75,12 @@ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase assertEquals("Normal Subscriber Received no messages", SEND_COUNT, received.size()); session.commit(); + + normalSubscriber.close(); connection.close(); - //We didn't receive the messages on the durable queue for the no-local subscriber - //so they are still on the broker. Restart the broker, prompting their recovery. + //Ensure the no-local subscribers messages were discarded by restarting the broker + //and reconnecting to the subscription to ensure they were not recovered. restartBroker(); Connection connection2 = getConnection(); @@ -89,12 +93,72 @@ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase createDurableSubscriber(topic2, MY_TOPIC_SUBSCRIPTION_NAME + "-NoLocal", null, true); - // The NO-local subscriber should now get ALL the messages - // as they are being consumed on a different connection to - // the one that they were published on. + // The NO-local subscriber should not get any messages + received = receiveMessage(noLocalSubscriber2, SEND_COUNT); + session2.commit(); + assertEquals("No Local Subscriber Received messages", 0, received.size()); + + noLocalSubscriber2.close(); + + + } + + + public void testNonNoLocalQueued() throws Exception + { + if(!isBrokerStorePersistent()) + { + fail("This test requires a broker with a persistent store"); + } + + Connection connection = getConnection(); + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + Topic topic = session.createTopic(MY_TOPIC_SUBSCRIPTION_NAME); + + TopicSubscriber noLocalSubscriber = + session.createDurableSubscriber(topic, MY_TOPIC_SUBSCRIPTION_NAME + "-NoLocal", null, true); + + + sendMessage(session, topic, SEND_COUNT); + + // Check messages can be received as expected. + connection.start(); + + List received = receiveMessage(noLocalSubscriber, SEND_COUNT); + assertEquals("No Local Subscriber Received messages", 0, received.size()); + + + + session.commit(); + + Connection connection3 = getConnection(); + Session session3 = connection3.createSession(true, Session.SESSION_TRANSACTED); + sendMessage(session3, topic, SEND_COUNT); + + + connection.close(); + + //We didn't receive the messages on the durable queue for the no-local subscriber + //so they are still on the broker. Restart the broker, prompting their recovery. + restartBroker(); + + Connection connection2 = getConnection(); + connection2.start(); + + Session session2 = connection2.createSession(true, Session.SESSION_TRANSACTED); + Topic topic2 = session2.createTopic(MY_TOPIC_SUBSCRIPTION_NAME); + + TopicSubscriber noLocalSubscriber2 = + session2.createDurableSubscriber(topic2, MY_TOPIC_SUBSCRIPTION_NAME + "-NoLocal",null, true); + + // The NO-local subscriber should receive messages sent from connection3 received = receiveMessage(noLocalSubscriber2, SEND_COUNT); session2.commit(); - assertEquals("No Local Subscriber Received messages", SEND_COUNT, received.size()); + assertEquals("No Local Subscriber did not receive expected messages", SEND_COUNT, received.size()); + + noLocalSubscriber2.close(); + + } protected List receiveMessage(MessageConsumer messageConsumer, diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityQueueTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityQueueTest.java index 7cb58ff1ed..a6c9885568 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityQueueTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityQueueTest.java @@ -21,8 +21,10 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; +import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -30,12 +32,15 @@ import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; +import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.naming.NamingException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class PriorityQueueTest extends QpidBrokerTestCase { @@ -197,4 +202,99 @@ public class PriorityQueueTest extends QpidBrokerTestCase return send; } + + /** + * Test that after sending an initial message with priority 0, it is able to be repeatedly reflected back to the queue using + * default priority and then consumed again, with separate transacted sessions with prefetch 1 for producer and consumer. + * + * Highlighted defect with PriorityQueues resolved in QPID-3927. + */ + public void testMessageReflectionWithPriorityIncreaseOnTransactedSessionsWithPrefetch1() throws Exception + { + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, "1"); + Connection conn = getConnection(); + conn.start(); + assertEquals("Prefetch not reset", 1, ((AMQConnection) conn).getMaxPrefetch()); + + final Session producerSess = conn.createSession(true, Session.SESSION_TRANSACTED); + final Session consumerSess = conn.createSession(true, Session.SESSION_TRANSACTED); + + //declare a priority queue with 10 priorities + final Map arguments = new HashMap(); + arguments.put("x-qpid-priorities",10); + ((AMQSession) producerSess).createQueue(new AMQShortString(getTestQueueName()), false, true, false, arguments); + + Queue queue = producerSess.createQueue(getTestQueueName()); + + //create the consumer, producer, add message listener + CountDownLatch latch = new CountDownLatch(5); + MessageConsumer cons = producerSess.createConsumer(queue); + MessageProducer producer = producerSess.createProducer(queue); + + ReflectingMessageListener listener = new ReflectingMessageListener(producerSess,producer,consumerSess,latch); + cons.setMessageListener(listener); + + //Send low priority 0 message to kick start the asynchronous reflection process + producer.setPriority(0); + producer.send(nextMessage(1, true, producerSess, producer)); + producerSess.commit(); + + //wait for the reflection process to complete + assertTrue("Test process failed to complete in allowed time", latch.await(10, TimeUnit.SECONDS)); + assertNull("Unexpected throwable encountered", listener.getThrown()); + } + + private static class ReflectingMessageListener implements MessageListener + { + private Session _prodSess; + private Session _consSess; + private CountDownLatch _latch; + private MessageProducer _prod; + private long _origCount; + private Throwable _lastThrown; + + public ReflectingMessageListener(final Session prodSess, final MessageProducer prod, + final Session consSess, final CountDownLatch latch) + { + _latch = latch; + _origCount = _latch.getCount(); + _prodSess = prodSess; + _consSess = consSess; + _prod = prod; + } + + @Override + public void onMessage(final Message message) + { + try + { + _latch.countDown(); + long msgNum = _origCount - _latch.getCount(); + System.out.println("Received message " + msgNum + " with ID: " + message.getIntProperty("msg")); + + if(_latch.getCount() > 0) + { + //reflect the message, updating its ID and using default priority + message.clearProperties(); + message.setIntProperty("msg", (int) msgNum + 1); + _prod.setPriority(Message.DEFAULT_PRIORITY); + _prod.send(message); + _prodSess.commit(); + } + + //commit the consumer session to consume the message + _consSess.commit(); + } + catch(Throwable t) + { + t.printStackTrace(); + _lastThrown = t; + } + } + + public Throwable getThrown() + { + return _lastThrown; + } + } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java index ad8c856a74..13053d02df 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java @@ -357,13 +357,45 @@ public class ProducerFlowControlTest extends AbstractTestLogging consumer.receive(); } + public void testQueueDeleteWithBlockedFlow() throws Exception + { + String queueName = getTestQueueName(); + createAndBindQueueWithFlowControlEnabled(producerSession, queueName, 1000, 800, true, false); + + producer = producerSession.createProducer(queue); + + // try to send 5 messages (should block after 4) + sendMessagesAsync(producer, producerSession, 5, 50L); + + Thread.sleep(5000); + + assertEquals("Incorrect number of message sent before blocking", 4, _sentMessages.get()); + + // close blocked producer session and connection + producerConnection.close(); + + // delete queue with a consumer session + ((AMQSession) consumerSession).sendQueueDelete(new AMQShortString(queueName)); + + consumer = consumerSession.createConsumer(queue); + consumerConnection.start(); + + Message message = consumer.receive(1000l); + assertNull("Unexpected message", message); + } + private void createAndBindQueueWithFlowControlEnabled(Session session, String queueName, int capacity, int resumeCapacity) throws Exception + { + createAndBindQueueWithFlowControlEnabled(session, queueName, capacity, resumeCapacity, false, true); + } + + private void createAndBindQueueWithFlowControlEnabled(Session session, String queueName, int capacity, int resumeCapacity, boolean durable, boolean autoDelete) throws Exception { final Map arguments = new HashMap(); arguments.put("x-qpid-capacity",capacity); arguments.put("x-qpid-flow-resume-capacity",resumeCapacity); - ((AMQSession) session).createQueue(new AMQShortString(queueName), true, false, false, arguments); - queue = session.createQueue("direct://amq.direct/"+queueName+"/"+queueName+"?durable='false'&autodelete='true'"); + ((AMQSession) session).createQueue(new AMQShortString(queueName), autoDelete, durable, false, arguments); + queue = session.createQueue("direct://amq.direct/"+queueName+"/"+queueName+"?durable='" + durable + "'&autodelete='" + autoDelete + "'"); ((AMQSession) session).declareAndBind((AMQDestination)queue); } diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java index 54abb76b6d..f2d4a513be 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java +++ b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java @@ -26,10 +26,10 @@ import org.apache.log4j.Logger; import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.federation.Bridge; import org.apache.qpid.server.federation.BrokerLink; -import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; @@ -38,7 +38,7 @@ import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Iterator; -public class SlowMessageStore implements MessageStore, DurableConfigurationStore +public class SlowMessageStore implements MessageStore { private static final Logger _logger = Logger.getLogger(SlowMessageStore.class); private static final String DELAYS = "delays"; @@ -55,11 +55,8 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore public void configureConfigStore(String name, ConfigurationRecoveryHandler recoveryHandler, - Configuration config, - LogSubject logSubject) throws Exception + Configuration config) throws Exception { - //To change body of implemented methods use File | Settings | File Templates. - _logger.info("Starting SlowMessageStore on Virtualhost:" + name); Configuration delays = config.subset(DELAYS); @@ -74,7 +71,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore if (messageStoreClass != null) { - Class clazz = Class.forName(messageStoreClass); + Class clazz = Class.forName(messageStoreClass); Object o = clazz.newInstance(); @@ -89,13 +86,14 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore _durableConfigurationStore = (DurableConfigurationStore)o; } } - _durableConfigurationStore.configureConfigStore(name, recoveryHandler, config, logSubject); + _durableConfigurationStore.configureConfigStore(name, recoveryHandler, config); } private void configureDelays(Configuration config) { - Iterator delays = config.getKeys(); + @SuppressWarnings("unchecked") + Iterator delays = config.getKeys(); while (delays.hasNext()) { @@ -160,11 +158,11 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore public void configureMessageStore(String name, - MessageStoreRecoveryHandler recoveryHandler, - Configuration config, - LogSubject logSubject) throws Exception + MessageStoreRecoveryHandler messageRecoveryHandler, + TransactionLogRecoveryHandler tlogRecoveryHandler, + Configuration config) throws Exception { - _realStore.configureMessageStore(name, recoveryHandler, config, logSubject); + _realStore.configureMessageStore(name, messageRecoveryHandler, tlogRecoveryHandler, config); } public void close() throws Exception @@ -194,17 +192,17 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("removeExchange"); } - public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException + public void bindQueue(Binding binding) throws AMQStoreException { doPreDelay("bindQueue"); - _durableConfigurationStore.bindQueue(exchange, routingKey, queue, args); + _durableConfigurationStore.bindQueue(binding); doPostDelay("bindQueue"); } - public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException + public void unbindQueue(Binding binding) throws AMQStoreException { doPreDelay("unbindQueue"); - _durableConfigurationStore.unbindQueue(exchange, routingKey, queue, args); + _durableConfigurationStore.unbindQueue(binding); doPostDelay("unbindQueue"); } @@ -227,14 +225,6 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("removeQueue"); } - public void configureTransactionLog(String name, - TransactionLogRecoveryHandler recoveryHandler, - Configuration storeConfiguration, LogSubject logSubject) - throws Exception - { - _realStore.configureTransactionLog(name, recoveryHandler, storeConfiguration, logSubject); - } - public Transaction newTransaction() { doPreDelay("beginTran"); @@ -313,6 +303,17 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore _underlying.abortTran(); doPostDelay("abortTran"); } + + public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException + { + _underlying.removeXid(format, globalId, branchId); + } + + public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues) + throws AMQStoreException + { + _underlying.recordXid(format, globalId, branchId, enqueues, dequeues); + } } public void updateQueue(AMQQueue queue) throws AMQStoreException @@ -350,4 +351,23 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore _durableConfigurationStore.deleteBridge(bridge); doPostDelay("deleteBridge"); } + + @Override + public void activate() throws Exception + { + _realStore.activate(); + } + + @Override + public void addEventListener(EventListener eventListener, Event... events) + { + _realStore.addEventListener(eventListener, events); + } + + @Override + public String getStoreLocation() + { + return _realStore.getStoreLocation(); + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java new file mode 100644 index 0000000000..6497a640d2 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +public class SlowMessageStoreFactory implements MessageStoreFactory +{ + + @Override + public MessageStore createMessageStore() + { + return new SlowMessageStore(); + } + + @Override + public String getStoreClassName() + { + return SlowMessageStore.class.getSimpleName(); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java deleted file mode 100644 index d95ad51e05..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.test.client; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.QueueBrowser; -import javax.jms.Session; -import java.util.Enumeration; - -public class CancelTest extends QpidBrokerTestCase -{ - private static final Logger _logger = Logger.getLogger(CancelTest.class); - - private Connection _clientConnection; - private Session _clientSession; - private Queue _queue; - - public void setUp() throws Exception - { - - super.setUp(); - - _queue = (Queue) getInitialContext().lookup("queue"); - - //Create Client - _clientConnection = getConnection(); - - _clientConnection.start(); - - _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - //Ensure _queue is created - _clientSession.createConsumer(_queue).close(); - } - - /** - * Simply - * This test originally did not assert anything but was just checking - * that a message could be browsed and consumed without throwing an exception. - * It now checks that at least a message is browsed and that a message is received. - */ - public void test() throws Exception - { - Connection producerConnection = getConnection(); - - producerConnection.start(); - - Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - MessageProducer producer = producerSession.createProducer(_queue); - producer.send(producerSession.createTextMessage()); - producerConnection.close(); - - - QueueBrowser browser = _clientSession.createBrowser(_queue); - Enumeration e = browser.getEnumeration(); - - assertTrue(e.hasMoreElements()); - - int i = 0; - while (e.hasMoreElements()) - { - e.nextElement(); - if(++i > 1) - { - fail("Two many elemnts to browse!"); - } - } - - browser.close(); - - MessageConsumer consumer = _clientSession.createConsumer(_queue); - assertNotNull( consumer.receive(2000l) ); - consumer.close(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java index 484146b690..b746a5b09e 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java @@ -18,11 +18,9 @@ */ package org.apache.qpid.test.client; -import org.apache.qpid.client.AMQNoConsumersException; -import org.apache.qpid.client.AMQNoRouteException; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; import javax.jms.Connection; import javax.jms.Destination; import javax.jms.ExceptionListener; @@ -32,9 +30,10 @@ import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.Topic; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; +import org.apache.qpid.client.AMQNoConsumersException; +import org.apache.qpid.client.AMQNoRouteException; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.test.utils.QpidBrokerTestCase; public class ImmediateAndMandatoryPublishingTest extends QpidBrokerTestCase implements ExceptionListener { @@ -202,7 +201,88 @@ public class ImmediateAndMandatoryPublishingTest extends QpidBrokerTestCase impl return message; } - @Override + public void testMandatoryAndImmediateDefaults() throws JMSException, InterruptedException + { + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // publish to non-existent queue - should get mandatory failure + MessageProducer producer = session.createProducer(session.createQueue(getTestQueueName())); + Message message = session.createMessage(); + producer.send(message); + + JMSException exception = _exceptions.poll(10, TimeUnit.SECONDS); + assertNotNull("JMSException is expected", exception); + AMQNoRouteException noRouteException = (AMQNoRouteException) exception.getLinkedException(); + assertNotNull("AMQNoRouteException should be linked to JMSEXception", noRouteException); + Message bounceMessage = (Message) noRouteException.getUndeliveredMessage(); + assertNotNull("Bounced Message is expected", bounceMessage); + assertEquals("Unexpected message is bounced", message.getJMSMessageID(), bounceMessage.getJMSMessageID()); + + producer = session.createProducer(null); + message = session.createMessage(); + producer.send(session.createQueue(getTestQueueName()), message); + + exception = _exceptions.poll(10, TimeUnit.SECONDS); + assertNotNull("JMSException is expected", exception); + noRouteException = (AMQNoRouteException) exception.getLinkedException(); + assertNotNull("AMQNoRouteException should be linked to JMSEXception", noRouteException); + bounceMessage = (Message) noRouteException.getUndeliveredMessage(); + assertNotNull("Bounced Message is expected", bounceMessage); + assertEquals("Unexpected message is bounced", message.getJMSMessageID(), bounceMessage.getJMSMessageID()); + + + // publish to non-existent topic - should get no failure + producer = session.createProducer(session.createTopic(getTestQueueName())); + message = session.createMessage(); + producer.send(message); + + exception = _exceptions.poll(1, TimeUnit.SECONDS); + assertNull("Unexpected JMSException", exception); + + producer = session.createProducer(null); + message = session.createMessage(); + producer.send(session.createTopic(getTestQueueName()), message); + + exception = _exceptions.poll(1, TimeUnit.SECONDS); + assertNull("Unexpected JMSException", exception); + + session.close(); + } + + public void testMandatoryAndImmediateSystemProperties() throws JMSException, InterruptedException + { + setTestClientSystemProperty("qpid.default_mandatory","true"); + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // publish to non-existent topic - should get mandatory failure + + MessageProducer producer = session.createProducer(session.createTopic(getTestQueueName())); + Message message = session.createMessage(); + producer.send(message); + + JMSException exception = _exceptions.poll(10, TimeUnit.SECONDS); + assertNotNull("JMSException is expected", exception); + AMQNoRouteException noRouteException = (AMQNoRouteException) exception.getLinkedException(); + assertNotNull("AMQNoRouteException should be linked to JMSEXception", noRouteException); + Message bounceMessage = (Message) noRouteException.getUndeliveredMessage(); + assertNotNull("Bounced Message is expected", bounceMessage); + assertEquals("Unexpected message is bounced", message.getJMSMessageID(), bounceMessage.getJMSMessageID()); + + // now set topic specific system property to false - should no longer get mandatory failure on new producer + setTestClientSystemProperty("qpid.default_mandatory_topic","false"); + producer = session.createProducer(null); + message = session.createMessage(); + producer.send(session.createTopic(getTestQueueName()), message); + + exception = _exceptions.poll(1, TimeUnit.SECONDS); + if(exception != null) + { + exception.printStackTrace(); + } + assertNull("Unexpected JMSException", exception); + + } + public void onException(JMSException exception) { _exceptions.add(exception); diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java index 7a4a45a2c8..6b6b4a7b3c 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java @@ -20,11 +20,7 @@ */ package org.apache.qpid.test.client; -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - +import java.util.Enumeration; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; @@ -35,7 +31,10 @@ import javax.jms.QueueBrowser; import javax.jms.Session; import javax.jms.TextMessage; import javax.naming.NamingException; -import java.util.Enumeration; +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.test.utils.QpidBrokerTestCase; public class QueueBrowserAutoAckTest extends QpidBrokerTestCase { @@ -421,4 +420,21 @@ public class QueueBrowserAutoAckTest extends QpidBrokerTestCase validate(messages); } + public void testBrowsingWhileStopped() throws JMSException + { + _clientConnection.stop(); + + try + { + QueueBrowser browser = _clientSession.createBrowser(getTestQueue()); + Enumeration messages = browser.getEnumeration(); + fail("Expected exception when attempting to browse on a stopped connection did not occur"); + } + catch(javax.jms.IllegalStateException e) + { + // pass + } + + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java index ee81e7c372..91f5cb7770 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java @@ -54,7 +54,7 @@ public class SyncWaitDelayTest extends QpidBrokerTestCase public void setUp() throws Exception { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.factoryclass", "org.apache.qpid.server.store.SlowMessageStoreFactory"); setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY)); setConfigurationProperty("management.enabled", "false"); diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java b/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java deleted file mode 100644 index 13465741bd..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -/** - * An AMQPPublisher represents the status of the publishing side of a test circuit that exposes AMQP specific features. - * Its provides additional assertions not available through the plain JMS {@link Publisher} interface. - * - *

- *
CRC Card
Responsibilities - *
Provide assertion that the publishers received a no consumers error code on every message. - *
Provide assertion that the publishers received a no route error code on every message. - *
- */ -public interface AMQPPublisher extends Publisher -{ - /** - * Provides an assertion that the publisher got a no consumers exception on every message. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the publisher got a no consumers exception on every message. - */ - Assertion noConsumersAssertion(ParsedProperties testProps); - - /** - * Provides an assertion that the publisher got a no rout exception on every message. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the publisher got a no rout exception on every message. - */ - Assertion noRouteAssertion(ParsedProperties testProps); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Assertion.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Assertion.java deleted file mode 100644 index 60d54f1f6f..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/Assertion.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - * Assertion models an assertion on a test {@link Circuit}. - * - *

- *
CRC Card
Responsibilities - *
Indicate whether or not the assertion passes when applied. - *
- */ -public interface Assertion -{ - /** - * Applies the assertion. - * - * @return true if the assertion passes, false if it fails. - */ - public boolean apply(); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/AssertionBase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/AssertionBase.java deleted file mode 100644 index 0bb4911d4c..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/AssertionBase.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import java.util.LinkedList; -import java.util.List; - -/** - * AssertionBase is a base class for implenmenting assertions. It provides a mechanism to store error messages, and - * report all error messages when its {@link #toString()} method is called. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Collect error messages. - *
- */ -public abstract class AssertionBase implements Assertion -{ - /** Holds the error messages. */ - List errors = new LinkedList(); - - /** - * Adds an error message to the assertion. - * - * @param error An error message to add to the assertion. - */ - public void addError(String error) - { - errors.add(error); - } - - /** - * Prints all of the error messages in the assertion into a string. - * - * @return All of the error messages in the assertion as a string. - */ - public String toString() - { - String result = ""; - - for (String error : errors) - { - result += error; - } - - return result; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java b/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java deleted file mode 100644 index 41614f92fc..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - * BrokerLifecycleAware is an awareness interface implemented by test cases that can run control the life-cycle of - * the brokers on which they run. Its purpose is to expose additional instrumentation of brokers during testing, that - * enables tests to use an automated failure mechanism to simulate broker failures, and to re-start failed brokers. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Indicate whether or not a test case is using an in-vm broker. - *
Track which in-vm broker is currently in use. - *
Accept setting of a failure mechanism. {@link CauseFailure}. - *
- * - * @todo Need to think about how to present the brokers through this interface. Thinking numbering the available - * brokers from 1 will do. Then can kill 1 and assume failing onto 2. Restart 1 and kill 2 and fail back onto - * 1 again? - */ -public interface BrokerLifecycleAware -{ - public void setInVmBrokers(); - - /** - * Indicates whether or not a test case is using in-vm brokers. - * - * @return true if the test is using in-vm brokers, false otherwise. - */ - public boolean usingInVmBroker(); - - /** - * Sets the currently live in-vm broker. - * - * @param i The currently live in-vm broker. - */ - public void setLiveBroker(int i); - - /** - * Reports the currently live in-vm broker. - * - * @return The currently live in-vm broker. - */ - public int getLiveBroker(); - - /** - * Accepts a failure mechanism. - * - * @param failureMechanism The failure mechanism. - */ - public void setFailureMechanism(CauseFailure failureMechanism); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java deleted file mode 100644 index 9bdd5a72c5..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - * CauseFailure provides a method to cause a failure in a messaging broker, usually used in conjunction with fail-over - * or other failure mode testing. In some cases failures may be automated, for example by shutting down an in-vm broker, - * or by sending a special control signal to a broker over a network connection. In other cases, it may be preferable - * to ask a user interactively to cause a failure scenario, in which case an implementation may display a prompt or - * dialog box asking for notification once the failure has been caused. The purpose of this interface is to abstract - * the exact cause and nature of a failure out of failure test cases. - * - *

- *
CRC Card
Responsibilities - *
Cause messaging broker failure. - *
- */ -public interface CauseFailure -{ - /** - * Causes the active message broker to fail. - */ - void causeFailure(); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java deleted file mode 100644 index 118ddff48b..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import java.io.IOException; - -/** - * Causes a message broker failure by interactively prompting the user to cause it. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Cause messaging broker failure. - *
- */ -public class CauseFailureUserPrompt implements CauseFailure -{ - /** - * Causes the active message broker to fail. - */ - public void causeFailure() - { - waitForUser("Cause a broker failure now, then press Return."); - } - - /** - * Outputs a prompt to the console and waits for the user to press return. - * - * @param prompt The prompt to display on the console. - */ - private void waitForUser(String prompt) - { - System.out.println(prompt); - - try - { - System.in.read(); - } - catch (IOException e) - { - // Ignored. - } - - System.out.println("Continuing."); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java deleted file mode 100644 index 4f9ab1a273..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import java.util.List; - -/** - * A Circuit is the basic test unit against which test cases are to be written. A circuit consists of two 'ends', an - * instigating 'publisher' end and a more passive 'receivers' end. - * - *

Once created, the life-cycle of a circuit may be controlled by {@link #start()}ing it, or {@link #close()}ing it. - * Once started, the circuit is ready to send messages over. Once closed the circuit can no longer be used. - * - *

The state of the circuit may be taken with the {@link #check()} method, and asserted against by the - * {@link #applyAssertions(java.util.List)} method. - * - *

There is a default test procedure which may be performed against the circuit. The outline of this procedure is: - * - *

- * Start the circuit.
- * Send test messages.
- * Request a status report.
- * Assert conditions on the publishing end of the circuit.
- * Assert conditions on the receiving end of the circuit.
- * Close the circuit.
- * Pass with no failed assertions or fail with a list of failed assertions.
- * 
- * - *

- *
CRC Card
Responsibilities - *
Supply the publishing and receiving ends of a test messaging circuit. - *
Start the circuit running. - *
Close the circuit down. - *
Take a reading of the circuits state. - *
Apply assertions against the circuits state. - *
Send test messages over the circuit. - *
Perform the default test procedue on the circuit. - *
- */ -public interface Circuit -{ - /** - * Gets the interface on the publishing end of the circuit. - * - * @return The publishing end of the circuit. - */ - public Publisher getPublisher(); - - /** - * Gets the interface on the receiving end of the circuit. - * - * @return The receiving end of the circuit. - */ - public Receiver getReceiver(); - - /** - * Connects and starts the circuit. After this method is called the circuit is ready to send messages. - */ - public void start(); - - /** - * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit, - * into a report, against which assertions may be checked. - */ - public void check(); - - /** - * Closes the circuit. All associated resources are closed. - */ - public void close(); - - /** - * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing - * this, to ensure that the circuit has gathered its state into a report to assert against. - * - * @param assertions The list of assertions to apply to the circuit. - * - * @return Any assertions that failed. - */ - public List applyAssertions(List assertions); - - /** - * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. - * - * @param numMessages The number of messages to send using the default test procedure. - * @param assertions The list of assertions to apply. - * - * @return Any assertions that failed. - */ - public List test(int numMessages, List assertions); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java deleted file mode 100644 index ffde385cfc..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * A CircuitEnd is a pair consisting of one message producer and one message consumer, that represents one end of a - * test circuit. It is a standard unit of connectivity allowing a full-duplex conversation to be held, provided both - * the consumer and producer are instantiated and configured. - * - *

- *
CRC Card
Responsibilities - *
Provide a message producer for sending messages. - *
Provide a message consumer for receiving messages. - *
- * - * @todo Update the {@link org.apache.qpid.test.utils.ConversationFactory} so that it accepts these as the basic conversation - * connection units. - */ -public interface CircuitEnd -{ - /** - * Gets the message producer at this circuit end point. - * - * @return The message producer at with this circuit end point. - */ - public MessageProducer getProducer(); - - /** - * Gets the message consumer at this circuit end point. - * - * @return The message consumer at this circuit end point. - */ - public MessageConsumer getConsumer(); - - /** - * Send the specified message over the producer at this end point. - * - * @param message The message to send. - * - * @throws JMSException Any JMS exception occuring during the send is allowed to fall through. - */ - public void send(Message message) throws JMSException; - - /** - * Gets the JMS Session associated with this circuit end point. - * - * @return The JMS Session associated with this circuit end point. - */ - public Session getSession(); - - /** - * Closes the message producers and consumers and the sessions, associated with this circuit end point. - * - * @throws JMSException Any JMSExceptions occurring during the close are allowed to fall through. - */ - public void close() throws JMSException; - - /** - * Returns the message monitor for reporting on received messages on this circuit end. - * - * @return The message monitor for this circuit end. - */ - public MessageMonitor getMessageMonitor(); - - /** - * Returns the exception monitor for reporting on exceptions received on this circuit end. - * - * @return The exception monitor for this circuit end. - */ - public ExceptionMonitor getExceptionMonitor(); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java deleted file mode 100644 index 5730752eae..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * A CircuitEndBase is a pair consisting of one message producer and one message consumer, that represents one end of a - * test circuit. It is a standard unit of connectivity allowing a full-duplex conversation to be held, provided both - * the consumer and producer are instantiated and configured. - * - *

- *
CRC Card
Responsibilities - *
Provide a message producer for sending messages. - *
Provide a message consumer for receiving messages. - *
- */ -public class CircuitEndBase implements CircuitEnd -{ - /** Holds the single message producer. */ - MessageProducer producer; - - /** Holds the single message consumer. */ - MessageConsumer consumer; - - /** Holds the controlSession for the circuit end. */ - Session session; - - /** Holds the message monitor for the circuit end. */ - MessageMonitor messageMonitor; - - /** Holds the exception monitor for the circuit end. */ - ExceptionMonitor exceptionMonitor; - - /** - * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured - * for messages and exceptions received by the circuit end. - * - * @param producer The message producer for the circuit end point. - * @param consumer The message consumer for the circuit end point. - * @param session The controlSession for the circuit end point. - * @param messageMonitor The monitor to notify of all messages received by the circuit end. - * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end. - */ - public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session, MessageMonitor messageMonitor, - ExceptionMonitor exceptionMonitor) - { - this.producer = producer; - this.consumer = consumer; - this.session = session; - - this.messageMonitor = messageMonitor; - this.exceptionMonitor = exceptionMonitor; - } - - /** - * Gets the message producer at this circuit end point. - * - * @return The message producer at with this circuit end point. - */ - public MessageProducer getProducer() - { - return producer; - } - - /** - * Gets the message consumer at this circuit end point. - * - * @return The message consumer at this circuit end point. - */ - public MessageConsumer getConsumer() - { - return consumer; - } - - /** - * Send the specified message over the producer at this end point. - * - * @param message The message to send. - * @throws javax.jms.JMSException Any JMS exception occuring during the send is allowed to fall through. - */ - public void send(Message message) throws JMSException - { - producer.send(message); - } - - /** - * Gets the JMS Session associated with this circuit end point. - * - * @return The JMS Session associated with this circuit end point. - */ - public Session getSession() - { - return session; - } - - /** - * Closes the message producers and consumers and the sessions, associated with this circuit end point. - * - * @throws javax.jms.JMSException Any JMSExceptions occurring during the close are allowed to fall through. - */ - public void close() throws JMSException - { - if (producer != null) - { - producer.close(); - } - - if (consumer != null) - { - consumer.close(); - } - } - - /** - * Returns the message monitor for reporting on received messages on this circuit end. - * - * @return The message monitor for this circuit end. - */ - public MessageMonitor getMessageMonitor() - { - return messageMonitor; - } - - /** - * Returns the exception monitor for reporting on exceptions received on this circuit end. - * - * @return The exception monitor for this circuit end. - */ - public ExceptionMonitor getExceptionMonitor() - { - return exceptionMonitor; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/DropInTest.java b/java/systests/src/main/java/org/apache/qpid/test/framework/DropInTest.java deleted file mode 100644 index 78b5a72c1f..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/DropInTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import javax.jms.JMSException; -import javax.jms.Message; - -/** - * A DropIn test is a test case that can accept late joining test clients into a running test. This can be usefull, - * for interactive experimentation. - * - *

- *
CRC Card
Responsibilities - *
Accept late joining test clients. - *
- */ -public interface DropInTest -{ - /** - * Should accept a late joining client into a running test case. The client will be enlisted with a control message - * with the 'CONTROL_TYPE' field set to the value 'LATEJOIN'. It should also provide values for the fields: - * - *

- *
CLIENT_NAME A unique name for the new client. - *
CLIENT_PRIVATE_CONTROL_KEY The key for the route on which the client receives its control messages. - *
- * - * @param message The late joiners join message. - * - * @throws JMSException Any JMS Exception are allowed to fall through, indicating that the join failed. - */ - public void lateJoin(Message message) throws JMSException; -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java b/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java deleted file mode 100644 index afb7b5bc5b..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; - -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * An exception monitor, listens for JMS exception on a connection or consumer. It record all exceptions that it receives - * and provides methods to test the number and type of exceptions received. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Record all exceptions received. - *
- */ -public class ExceptionMonitor implements ExceptionListener -{ - /** Used for debugging. */ - private final Logger log = Logger.getLogger(ExceptionMonitor.class); - - /** Holds the received exceptions. */ - private List exceptions = new ArrayList(); - - /** - * Receives incoming exceptions. - * - * @param e The exception to record. - */ - public synchronized void onException(JMSException e) - { - log.debug("public void onException(JMSException e): called", e); - - exceptions.add(e); - } - - /** - * Checks that no exceptions have been received. - * - * @return true if no exceptions have been received, false otherwise. - */ - public synchronized boolean assertNoExceptions() - { - return exceptions.isEmpty(); - } - - /** - * Checks that exactly one exception has been received. - * - * @return true if exactly one exception been received, false otherwise. - */ - public synchronized boolean assertOneJMSException() - { - return exceptions.size() == 1; - } - - /** - * Checks that exactly one exception, with a linked cause of the specified type, has been received. - * - * @param aClass The type of the linked cause. - * - * @return true if exactly one exception, with a linked cause of the specified type, been received, - * false otherwise. - */ - public synchronized boolean assertOneJMSExceptionWithLinkedCause(Class aClass) - { - if (exceptions.size() == 1) - { - Exception e = exceptions.get(0); - - if (e instanceof JMSException) - { - JMSException jmse = (JMSException) e; - - Exception linkedCause = jmse.getLinkedException(); - - if ((linkedCause != null) && aClass.isInstance(linkedCause)) - { - return true; - } - } - } - - return false; - } - - /** - * Checks that at least one exception of the the specified type, has been received. - * - * @param exceptionClass The type of the exception. - * - * @return true if at least one exception of the specified type has been received, false otherwise. - */ - public synchronized boolean assertExceptionOfType(Class exceptionClass) - { - // Start by assuming that the exception has no been received. - boolean passed = false; - - // Scan all the exceptions for a match. - for (Exception e : exceptions) - { - if (exceptionClass.isInstance(e)) - { - passed = true; - - break; - } - } - - return passed; - } - - /** - * Reports the number of exceptions held by this monitor. - * - * @return The number of exceptions held by this monitor. - */ - public synchronized int size() - { - return exceptions.size(); - } - - /** - * Clears the record of received exceptions. - */ - public synchronized void reset() - { - exceptions = new ArrayList(); - } - - /** - * Provides a dump of the stack traces of all exceptions that this exception monitor was notified of. Mainly - * use for debugging/test failure reporting purposes. - * - * @return A string containing a dump of the stack traces of all exceptions. - */ - public synchronized String toString() - { - String result = "ExceptionMonitor: holds " + exceptions.size() + " exceptions.\n\n"; - - for (Exception ex : exceptions) - { - result += getStackTrace(ex) + "\n"; - } - - return result; - } - - /** - * Prints an exception stack trace into a string. - * - * @param t The throwable to get the stack trace from. - * - * @return A string containing the throwables stack trace. - */ - public static String getStackTrace(Throwable t) - { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw, true); - t.printStackTrace(pw); - pw.flush(); - sw.flush(); - - return sw.toString(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java deleted file mode 100644 index ecbb710a6b..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import org.apache.qpid.junit.extensions.SetupTaskAware; -import org.apache.qpid.junit.extensions.SetupTaskHandler; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.junit.extensions.util.TestContextProperties; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import java.util.ArrayList; -import java.util.List; - -/** - * FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is - * to provide some convenience methods for testing. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Create and clean up in-vm brokers on every test case. - *
Produce lists of assertions from assertion creation calls. - *
Produce JUnit failures from assertion failures. - *
Convert failed assertions to error messages. - *
- */ -public class FrameworkBaseCase extends QpidBrokerTestCase implements FrameworkTestContext, SetupTaskAware, - BrokerLifecycleAware -{ - /** Used for debugging purposes. */ - private static final Logger log = Logger.getLogger(FrameworkBaseCase.class); - - private CircuitFactory circuitFactory = new LocalAMQPCircuitFactory(); - - private ParsedProperties testProps; - - private SetupTaskHandler taskHandler = new SetupTaskHandler(); - - private boolean isUsingInVM; - - private CauseFailure failureMechanism = new CauseFailureUserPrompt(); - - /** - * Creates a new test case with the specified name. - * - * @param name The test case name. - */ - public FrameworkBaseCase(String name) - { - super(name); - } - - /** Holds the test sequencer to create and run test circuits with. */ /** - * Returns the test case sequencer that provides test circuit, and test sequence implementations. The sequencer - * that this base case returns by default is suitable for running a test circuit with both circuit ends colocated - * on the same JVM. - * - * @return The test case sequencer. - */ - protected CircuitFactory getCircuitFactory() - { - return circuitFactory; - } - - /** - * Overrides the default test circuit factory. Test decorators can use this to supply distributed test sequencers or - * other test circuit factory specializations. - * - * @param circuitFactory The new test circuit factory. - */ - public void setCircuitFactory(CircuitFactory circuitFactory) - { - this.circuitFactory = circuitFactory; - } - - /** - * Reports the current test case name. - * - * @return The current test case name. - */ - public TestCaseVector getTestCaseVector() - { - return new TestCaseVector(this.getName(), 0); - } - - /** - * Reports the current test case parameters. - * - * @return The current test case parameters. - */ - public MessagingTestConfigProperties getTestParameters() - { - return new MessagingTestConfigProperties(testProps); - } - - /** - * Creates a list of assertions. - * - * @param asserts The assertions to compile in a list. - * - * @return A list of assertions. - */ - protected List assertionList(Assertion... asserts) - { - List result = new ArrayList(); - - for (Assertion assertion : asserts) - { - result.add(assertion); - } - - return result; - } - - /** - * Generates a JUnit assertion exception (failure) if any assertions are passed into this method, also concatenating - * all of the error messages in the assertions together to form an error message to diagnose the test failure with. - * - * @param asserts The list of failed assertions. - */ - protected static void assertNoFailures(List asserts) - { - log.debug("protected void assertNoFailures(List asserts = " + asserts + "): called"); - - // Check if there are no assertion failures, and return without doing anything if so. - if ((asserts == null) || asserts.isEmpty()) - { - return; - } - - // Compile all of the assertion failure messages together. - String errorMessage = assertionsToString(asserts); - - // Fail with the error message from all of the assertions. - fail(errorMessage); - } - - /** - * Converts a list of failed assertions into an error message. - * - * @param asserts The failed assertions. - * - * @return The error message. - */ - protected static String assertionsToString(List asserts) - { - String errorMessage = ""; - - for (Assertion assertion : asserts) - { - errorMessage += assertion.toString() + "\n"; - } - - return errorMessage; - } - - /** - * Ensures that the in-vm broker is created and initialized. - * - * @throws Exception Any exceptions allowed to fall through and fail the test. - */ - protected void setUp() throws Exception - { - super.setUp(); - NDC.push(getName()); - - testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); - } - - /** - * Ensures that the in-vm broker is cleaned up after each test run. - */ - protected void tearDown() - { - NDC.pop(); - - // Process all optional tear down tasks. This may include in-vm broker clean up, if a decorator has added it. - taskHandler.runTearDownTasks(); - } - - /** - * Adds the specified task to the tests setup. - * - * @param task The task to add to the tests setup. - */ - public void chainSetupTask(Runnable task) - { - taskHandler.chainSetupTask(task); - } - - /** - * Adds the specified task to the tests tear down. - * - * @param task The task to add to the tests tear down. - */ - public void chainTearDownTask(Runnable task) - { - taskHandler.chainTearDownTask(task); - } - - /** - * Should provide a translation from the junit method name of a test to its test case name as known to the test - * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test - * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case - * name "TC2_BasicP2P". - * - * @param methodName The name of the JUnit test method. - * - * @return The name of the corresponding interop test case. - */ - public String getTestCaseNameForTestMethod(String methodName) - { - return methodName; - } - - public void setInVmBrokers() - { - isUsingInVM = true; - } - - /** - * Indicates whether or not a test case is using in-vm brokers. - * - * @return true if the test is using in-vm brokers, false otherwise. - */ - public boolean usingInVmBroker() - { - return isUsingInVM; - } - - /** - * Sets the currently live in-vm broker. - * - * @param i The currently live in-vm broker. - */ - public void setLiveBroker(int i) - { } - - /** - * Reports the currently live in-vm broker. - * - * @return The currently live in-vm broker. - */ - public int getLiveBroker() - { - return 0; - } - - /** - * Accepts a failure mechanism. - * - * @param failureMechanism The failure mechanism. - */ - public void setFailureMechanism(CauseFailure failureMechanism) - { - this.failureMechanism = failureMechanism; - } - - protected ParsedProperties getTestProps() - { - return testProps; - } - - protected void setTestProps(ParsedProperties testProps) - { - this.testProps = testProps; - } - - protected SetupTaskHandler getTaskHandler() - { - return taskHandler; - } - - protected CauseFailure getFailureMechanism() - { - return failureMechanism; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java deleted file mode 100644 index 9a4668e86f..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - * A FrameworkTestContext provides context information to test code about the current test case being run; its name, its - * parameters. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide the name of the current test case. - *
Provide the test parameters. - *
- */ -public interface FrameworkTestContext -{ - /** - * Reports the current test case name. - * - * @return The current test case name. - */ - TestCaseVector getTestCaseVector(); - - /** - * Reports the current test case parameters. - * - * @return The current test case parameters. - */ - MessagingTestConfigProperties getTestParameters(); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java deleted file mode 100644 index 899a808bdd..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.localcircuit.LocalAMQPPublisherImpl; -import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.Topic; - -/** - * LocalAMQPCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted - * on the same JVM, allowing AMQP/Qpid specific options to be applied to the circuit. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a standard test procedure over a test circuit. - *
Construct test circuits appropriate to a tests context. - *
Construct test circuits the support AMQP specific options. - *
- */ -public class LocalAMQPCircuitFactory extends LocalCircuitFactory -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(LocalAMQPCircuitFactory.class); - - /** - * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters. - * - * @param connection The connection to build the circuit end on. - * @param testProps The test parameters to configure the circuit end construction. - * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique. - * - * @return A circuit end suitable for the publishing side of a test circuit. - * - * @throws javax.jms.JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation. - */ - public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId) - throws JMSException - { - log.debug( - "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = " - + uniqueId + "): called"); - - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps); - - Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode()); - - Destination destination = - props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId) - : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId); - - MessageProducer producer = - props.getPublisherProducerBind() - ? ((props.getImmediate() || props.getMandatory()) - ? ((AMQSession) session).createProducer(destination, props.getMandatory(), props.getImmediate()) - : session.createProducer(destination)) : null; - - MessageConsumer consumer = - props.getPublisherConsumerBind() - ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null; - - MessageMonitor messageMonitor = new MessageMonitor(); - - if (consumer != null) - { - consumer.setMessageListener(messageMonitor); - } - - ExceptionMonitor exceptionMonitor = new ExceptionMonitor(); - connection.setExceptionListener(exceptionMonitor); - - if (!props.getPublisherConsumerActive() && (consumer != null)) - { - consumer.close(); - } - - return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor); - } - - /** - * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters. - * - * @param connection The connection to build the circuit end on. - * @param testProps The test parameters to configure the circuit end construction. - * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique. - * - * @return A circuit end suitable for the receiving side of a test circuit. - * - * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation. - */ - public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId) - throws JMSException - { - log.debug( - "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = " - + uniqueId + "): called"); - - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps); - - Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode()); - - MessageProducer producer = - props.getReceiverProducerBind() - ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null; - - Destination destination = - props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId) - : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId); - - MessageConsumer consumer = - props.getReceiverConsumerBind() - ? ((props.getDurableSubscription() && props.getPubsub()) - ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination)) - : null; - - MessageMonitor messageMonitor = new MessageMonitor(); - - if (consumer != null) - { - consumer.setMessageListener(messageMonitor); - } - - if (!props.getReceiverConsumerActive() && (consumer != null)) - { - consumer.close(); - } - - return new CircuitEndBase(producer, consumer, session, messageMonitor, null); - } - - /** - * Creates a local {@link Publisher} from a {@link CircuitEnd}. The publisher implementation provides AMQP - * specific assertion methods, for testing beyond JMS. - * - * @param publisherEnd The publishing circuit end. - * - * @return A {@link Receiver}. - */ - protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd) - { - return new LocalAMQPPublisherImpl(publisherEnd); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java deleted file mode 100644 index b8fd4cc7e7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl; -import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl; -import org.apache.qpid.test.framework.localcircuit.LocalReceiverImpl; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.Topic; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicLong; - -/** - * LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted - * on the same JVM. The ends of the circuit are presented as {@link Publisher} and {@link Receiver} interfaces, which - * in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation - * of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that - * use messaging features not available in JMS can be written. This provides an extension point for writing tests - * against proprietary features of JMS implementations. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a standard test procedure over a test circuit. - *
Construct test circuits appropriate to a tests context. - *
- */ -public class LocalCircuitFactory implements CircuitFactory -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(LocalCircuitFactory.class); - - /** Used to create unique destination names for each test. */ - protected static AtomicLong uniqueDestsId = new AtomicLong(); - - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test and gathering the test reports from the participants. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) - { - if (testCircuit != null) - { - FrameworkBaseCase.assertNoFailures(testCircuit.test(1, assertions)); - } - } - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * - * @return A test circuit. - */ - public Circuit createCircuit(Connection connection, ParsedProperties testProperties) - { - Circuit result; - - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties); - - // Create a standard publisher/receivers test client pair on a shared connection, individual sessions. - try - { - // Get a unique offset to append to destination names to make them unique to the connection. - long uniqueId = uniqueDestsId.incrementAndGet(); - - // Add the connection exception listener to assert on exception conditions with. - // ExceptionMonitor exceptionMonitor = new ExceptionMonitor(); - // connection.setExceptionListener(exceptionMonitor); - - // Set up the publisher. - CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId); - - // Set up the receiver. - CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId); - - // Start listening for incoming messages. - connection.start(); - - // Package everything up. - LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd); - LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd); - - result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor()); - } - catch (JMSException e) - { - throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e); - } - - return result; - } - - /** - * Creates a local {@link Receiver} from a {@link CircuitEnd}. Sub-classes may override this to provide more - * specialized receivers if necessary. - * - * @param receiverEnd The receiving circuit end. - * - * @return A {@link Receiver}. - */ - protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd) - { - return new LocalReceiverImpl(receiverEnd); - } - - /** - * Creates a local {@link Publisher} from a {@link CircuitEnd}. Sub-classes may override this to provide more - * specialized receivers if necessary. - * - * @param publisherEnd The publishing circuit end. - * - * @return A {@link Receiver}. - */ - protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd) - { - return new LocalPublisherImpl(publisherEnd); - } - - /** - * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters. - * - * @param connection The connection to build the circuit end on. - * @param testProps The test parameters to configure the circuit end construction. - * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique. - * - * @return A circuit end suitable for the publishing side of a test circuit. - * - * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation. - */ - public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId) - throws JMSException - { - log.debug( - "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = " - + uniqueId + "): called"); - - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps); - - // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do. - if (props.getImmediate() || props.getMandatory()) - { - throw new RuntimeException( - "Cannot create a pure JMS circuit as the test properties require AMQP specific options."); - } - - Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode()); - - Destination destination = - props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId) - : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId); - - MessageProducer producer = props.getPublisherProducerBind() ? session.createProducer(destination) : null; - - MessageConsumer consumer = - props.getPublisherConsumerBind() - ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null; - - MessageMonitor messageMonitor = new MessageMonitor(); - - if (consumer != null) - { - consumer.setMessageListener(messageMonitor); - } - - ExceptionMonitor exceptionMonitor = new ExceptionMonitor(); - connection.setExceptionListener(exceptionMonitor); - - if (!props.getPublisherConsumerActive() && (consumer != null)) - { - consumer.close(); - } - - return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor); - } - - /** - * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters. - * - * @param connection The connection to build the circuit end on. - * @param testProps The test parameters to configure the circuit end construction. - * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique. - * - * @return A circuit end suitable for the receiving side of a test circuit. - * - * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation. - */ - public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId) - throws JMSException - { - log.debug( - "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = " - + uniqueId + "): called"); - - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps); - - // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do. - if (props.getImmediate() || props.getMandatory()) - { - throw new RuntimeException( - "Cannot create a pure JMS circuit as the test properties require AMQP specific options."); - } - - Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode()); - - MessageProducer producer = - props.getReceiverProducerBind() - ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null; - - Destination destination = - props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId) - : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId); - - MessageConsumer consumer = - props.getReceiverConsumerBind() - ? ((props.getDurableSubscription() && props.getPubsub()) - ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination)) - : null; - - MessageMonitor messageMonitor = new MessageMonitor(); - - if (consumer != null) - { - consumer.setMessageListener(messageMonitor); - } - - if (!props.getReceiverConsumerActive() && (consumer != null)) - { - consumer.close(); - } - - return new CircuitEndBase(producer, consumer, session, messageMonitor, null); - } - - /** - * Sets the sender test client to coordinate the test with. - * - * @param sender The contact details of the sending client in the test. - */ - public void setSender(TestClientDetails sender) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Sets the receiving test client to coordinate the test with. - * - * @param receiver The contact details of the sending client in the test. - */ - public void setReceiver(TestClientDetails receiver) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Supplies the sending test client. - * - * @return The sending test client. - */ - public TestClientDetails getSender() - { - throw new RuntimeException("Not implemented."); - } - - /** - * Supplies the receiving test client. - * - * @return The receiving test client. - */ - public List getReceivers() - { - throw new RuntimeException("Not implemented."); - } - - /** - * Accepts the conversation factory over which to hold the test coordinating conversation. - * - * @param conversationFactory The conversation factory to coordinate the test over. - */ - public void setConversationFactory(ConversationFactory conversationFactory) - { - throw new RuntimeException("Not implemented."); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java b/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java deleted file mode 100644 index 397c4e9fbd..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - * MessageIdentityVector provides a message identification scheme, that matches individual messages with test cases. - * Test messages are being sent by a number of test clients, sending messages over a set of routes, and being received - * by another set of test clients. Each test is itself, being run within a test cycle, of which there could be many. It - * is the job of the test coordinator to request and receive reports from the available test clients, on what has been - * sent, what has been received, and what errors may have occurred, and to reconcile this information against the - * assertions being applied by the test case. In order to be able to figure out which messages belong to which test, - * there needs to be an identification scheme, that the coordinator can use to correlate messages in senders and - * receiver reports. Every message sent in a test can be associated with this information. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Identify a test case, a handling client id, a circuit end within the client, and a test cycle number. - *
- */ -public class MessageIdentityVector -{ - /** Holds the test case vector component of the message identity vector. */ - private TestCaseVector testCaseVector; - - /** The unique client id. */ - private String clientId; - - /** The unique circuit end number within the client id. */ - private int circuitEndId; - - /** - * Creates a new identity vector for test messages. - * - * @param testCase The name of the test case generating the messages. - * @param clientId The unique id of the client implementing a circuit end that is handling the messages. - * @param circuitEndId The unique id number of the circuit end within the client. - * @param testCycleNumber The cycle iteration number of the test case. - */ - public MessageIdentityVector(String testCase, String clientId, int circuitEndId, int testCycleNumber) - { - this.testCaseVector = new TestCaseVector(testCase, testCycleNumber); - this.clientId = clientId; - this.circuitEndId = circuitEndId; - } - - /** - * Reports the test case vector component of the message identity vector. - * - * @return The test case vector component of the message identity vector. - */ - public TestCaseVector getTestCaseVector() - { - return testCaseVector; - } - - /** - * Reports the name of the test case. - * - * @return The name of the test case. - */ - public String getTestCase() - { - return testCaseVector.getTestCase(); - } - - /** - * Reports the test iteration cycle number within the test case. - * - * @return The test iteration cycle number within the test case. - */ - public int getTestCycleNumber() - { - return testCaseVector.getTestCycleNumber(); - } - - /** - * Resports the client id. - * - * @return The client id. - */ - public String getClientId() - { - return clientId; - } - - /** - * Reports the circuit end number within the test client. - * - * @return The circuit end number within the test client. - */ - public int getCircuitEndId() - { - return circuitEndId; - } - - /** - * Compares this identity vector with another for equality. All fields must match. - * - * @param o The identity vector to compare with. - * - * @return true if the identity vector is identical to this one by all fields, false otherwise. - */ - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - - if ((o == null) || (getClass() != o.getClass())) - { - return false; - } - - MessageIdentityVector that = (MessageIdentityVector) o; - - if (circuitEndId != that.circuitEndId) - { - return false; - } - - if ((clientId != null) ? (!clientId.equals(that.clientId)) : (that.clientId != null)) - { - return false; - } - - if ((testCaseVector != null) ? (!testCaseVector.equals(that.testCaseVector)) : (that.testCaseVector != null)) - { - return false; - } - - return true; - } - - /** - * Computes a hash code for this identity vector based on all fields. - * - * @return A hash code for this identity vector based on all fields. - */ - public int hashCode() - { - int result; - result = ((testCaseVector != null) ? testCaseVector.hashCode() : 0); - result = (31 * result) + ((clientId != null) ? clientId.hashCode() : 0); - result = (31 * result) + circuitEndId; - - return result; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java b/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java deleted file mode 100644 index 5265c0416f..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; - -import javax.jms.Message; -import javax.jms.MessageListener; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * MessageMonitor is used to record information about messages received. This will provide methods to check various - * properties, such as the type, number and content of messages received in order to verify the correct behaviour of - * tests. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Count incoming messages. - *
Record time ellapsed since the arrival of the first message. - *
Reset all counts and timings. - *
- */ -public class MessageMonitor implements MessageListener -{ - /** Used for debugging. */ - private final Logger log = Logger.getLogger(MessageMonitor.class); - - /** Holds the count of messages received since the last query. */ - protected AtomicInteger numMessages = new AtomicInteger(); - - /** Holds the time of arrival of the first message. */ - protected Long firstMessageTime = null; - - /** - * Handles received messages. Does Nothing. - * - * @param message The message. Ignored. - */ - public void onMessage(Message message) - { - // log.debug("public void onMessage(Message message): called"); - - numMessages.getAndIncrement(); - } - - /** - * Gets the count of messages. - * - * @return The count of messages. - */ - public int getNumMessage() - { - if (firstMessageTime == null) - { - firstMessageTime = System.nanoTime(); - } - - return numMessages.get(); - } - - /** - * Gets the time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet. - * - * @return The time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet. - */ - public long getTime() - { - if (firstMessageTime != null) - { - return System.nanoTime() - firstMessageTime; - } - else - { - return 0L; - } - } - - /** - * Resets the message count and timer to zero. - */ - public void reset() - { - numMessages.set(0); - firstMessageTime = null; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java b/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java deleted file mode 100644 index ceece2dae2..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java +++ /dev/null @@ -1,684 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -import javax.jms.Session; -import java.util.Properties; - -/** - * MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology, - * and test parameters for running a messaging test over that topology. A Properties object holding some of these - * properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour. - * - *

A complete list of the parameters, default values and comments on their usage is provided here: - * - *

- *
Parameters
Parameter Default Comments - *
messageSize 0 Message size in bytes. Not including any headers. - *
destinationName ping The root name to use to generate destination names to ping. - *
persistent false Determines whether peristent delivery is used. - *
transacted false Determines whether messages are sent/received in transactions. - *
broker tcp://localhost:5672 Determines the broker to connect to. - *
virtualHost test Determines the virtual host to send all ping over. - *
rate 0 The maximum rate (in hertz) to send messages at. 0 means no limit. - *
verbose false The verbose flag for debugging. Prints to console on every message. - *
pubsub false Whether to ping topics or queues. Uses p2p by default. - *
username guest The username to access the broker with. - *
password guest The password to access the broker with. - *
selector null Not used. Defines a message selector to filter pings with. - *
destinationCount 1 The number of receivers listening to the pings. - *
timeout 30000 In milliseconds. The timeout to stop waiting for replies. - *
commitBatchSize 1 The number of messages per transaction in transactional mode. - *
uniqueDests true Whether each receivers only listens to one ping destination or all. - *
durableDests false Whether or not durable destinations are used. - *
ackMode AUTO_ACK The message acknowledgement mode. Possible values are: - * 0 - SESSION_TRANSACTED - * 1 - AUTO_ACKNOWLEDGE - * 2 - CLIENT_ACKNOWLEDGE - * 3 - DUPS_OK_ACKNOWLEDGE - * 257 - NO_ACKNOWLEDGE - * 258 - PRE_ACKNOWLEDGE - *
maxPending 0 The maximum size in bytes, of messages sent but not yet received. - * Limits the volume of messages currently buffered on the client - * or broker. Can help scale test clients by limiting amount of buffered - * data to avoid out of memory errors. - *
- * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide the names and defaults of all test parameters. - *
- * - * @todo Put a type-safe wrapper around these properties, but continue to store the parameters as properties. This is - * simply to ensure that it is a simple matter to serialize/deserialize string/string pairs onto messages. - */ -public class MessagingTestConfigProperties extends ParsedProperties -{ - // ====================== Connection Properties ================================== - - /** Holds the name of the default connection configuration. */ - public static final String CONNECTION_NAME = "broker"; - - /** Holds the name of the property to get the initial context factory name from. */ - public static final String INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial"; - - /** Defines the class to use as the initial context factory by default. */ - public static final String INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"; - - /** Holds the name of the property to get the test broker url from. */ - public static final String BROKER_PROPNAME = "qpid.test.broker"; - - /** Holds the default broker url for the test. */ - public static final String BROKER_DEFAULT = "vm://:1"; - - /** Holds the name of the property to get the test broker virtual path. */ - public static final String VIRTUAL_HOST_PROPNAME = "virtualHost"; - - /** Holds the default virtual path for the test. */ - public static final String VIRTUAL_HOST_DEFAULT = "test"; - - /** Holds the name of the property to get the broker access username from. */ - public static final String USERNAME_PROPNAME = "username"; - - /** Holds the default broker log on username. */ - public static final String USERNAME_DEFAULT = "guest"; - - /** Holds the name of the property to get the broker access password from. */ - public static final String PASSWORD_PROPNAME = "password"; - - /** Holds the default broker log on password. */ - public static final String PASSWORD_DEFAULT = "guest"; - - // ====================== Messaging Topology Properties ========================== - - /** Holds the name of the property to get the bind publisher procuder flag from. */ - public static final String PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind"; - - /** Holds the default value of the publisher producer flag. */ - public static final boolean PUBLISHER_PRODUCER_BIND_DEFAULT = true; - - /** Holds the name of the property to get the bind publisher procuder flag from. */ - public static final String PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind"; - - /** Holds the default value of the publisher consumer flag. */ - public static final boolean PUBLISHER_CONSUMER_BIND_DEFAULT = false; - - /** Holds the name of the property to get the bind receivers procuder flag from. */ - public static final String RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind"; - - /** Holds the default value of the receivers producer flag. */ - public static final boolean RECEIVER_PRODUCER_BIND_DEFAULT = false; - - /** Holds the name of the property to get the bind receivers procuder flag from. */ - public static final String RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind"; - - /** Holds the default value of the receivers consumer flag. */ - public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true; - - /** Holds the name of the property to get the publishers consumer active flag from. */ - public static final String PUBLISHER_CONSUMER_ACTIVE_PROPNAME = "publisherConsumerActive"; - - /** Holds the default value of the publishers consumer active flag. */ - public static final boolean PUBLISHER_CONSUMER_ACTIVE_DEFAULT = true; - - /** Holds the name of the property to get the receivers consumer active flag from. */ - public static final String RECEIVER_CONSUMER_ACTIVE_PROPNAME = "receiverConsumerActive"; - - /** Holds the default value of the receivers consumer active flag. */ - public static final boolean RECEIVER_CONSUMER_ACTIVE_DEFAULT = true; - - /** Holds the name of the property to get the destination name root from. */ - public static final String SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot"; - - /** Holds the root of the name of the default destination to send to. */ - public static final String SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo"; - - /** Holds the name of the property to get the destination name root from. */ - public static final String RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot"; - - /** Holds the root of the name of the default destination to send to. */ - public static final String RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom"; - - /** Holds the name of the proeprty to get the destination count from. */ - public static final String DESTINATION_COUNT_PROPNAME = "destinationCount"; - - /** Defines the default number of destinations to ping. */ - public static final int DESTINATION_COUNT_DEFAULT = 1; - - /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */ - public static final String PUBSUB_PROPNAME = "pubsub"; - - /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */ - public static final boolean PUBSUB_DEFAULT = false; - - // ====================== JMS Options and Flags ================================= - - /** Holds the name of the property to get the test delivery mode from. */ - public static final String PERSISTENT_MODE_PROPNAME = "persistent"; - - /** Holds the message delivery mode to use for the test. */ - public static final boolean PERSISTENT_MODE_DEFAULT = false; - - /** Holds the name of the property to get the test transactional mode from. */ - public static final String TRANSACTED_PUBLISHER_PROPNAME = "transactedPublisher"; - - /** Holds the transactional mode to use for the test. */ - public static final boolean TRANSACTED_PUBLISHER_DEFAULT = false; - - /** Holds the name of the property to get the test transactional mode from. */ - public static final String TRANSACTED_RECEIVER_PROPNAME = "transactedReceiver"; - - /** Holds the transactional mode to use for the test. */ - public static final boolean TRANSACTED_RECEIVER_DEFAULT = false; - - /** Holds the name of the property to set the no local flag from. */ - public static final String NO_LOCAL_PROPNAME = "noLocal"; - - /** Defines the default value of the no local flag to use when consuming messages. */ - public static final boolean NO_LOCAL_DEFAULT = false; - - /** Holds the name of the property to get the message acknowledgement mode from. */ - public static final String ACK_MODE_PROPNAME = "ackMode"; - - /** Defines the default message acknowledgement mode. */ - public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE; - - /** Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. */ - public static final String DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription"; - - /** Defines the default value of the durable subscriptions flag. */ - public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false; - - // ====================== Qpid/AMQP Options and Flags ================================ - - /** Holds the name of the property to set the exclusive flag from. */ - public static final String EXCLUSIVE_PROPNAME = "exclusive"; - - /** Defines the default value of the exclusive flag to use when consuming messages. */ - public static final boolean EXCLUSIVE_DEFAULT = false; - - /** Holds the name of the property to set the immediate flag from. */ - public static final String IMMEDIATE_PROPNAME = "immediate"; - - /** Defines the default value of the immediate flag to use when sending messages. */ - public static final boolean IMMEDIATE_DEFAULT = false; - - /** Holds the name of the property to set the mandatory flag from. */ - public static final String MANDATORY_PROPNAME = "mandatory"; - - /** Defines the default value of the mandatory flag to use when sending messages. */ - public static final boolean MANDATORY_DEFAULT = false; - - /** Holds the name of the property to get the durable destinations flag from. */ - public static final String DURABLE_DESTS_PROPNAME = "durableDests"; - - /** Default value for the durable destinations flag. */ - public static final boolean DURABLE_DESTS_DEFAULT = false; - - /** Holds the name of the property to set the prefetch size from. */ - public static final String PREFETCH_PROPNAME = "prefetch"; - - /** Defines the default prefetch size to use when consuming messages. */ - public static final int PREFETCH_DEFAULT = 100; - - // ====================== Common Test Parameters ================================ - - /** Holds the name of the property to get the test message size from. */ - public static final String MESSAGE_SIZE_PROPNAME = "messageSize"; - - /** Used to set up a default message size. */ - public static final int MESSAGE_SIZE_DEAFULT = 0; - - /** Holds the name of the property to get the message rate from. */ - public static final String RATE_PROPNAME = "rate"; - - /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */ - public static final int RATE_DEFAULT = 0; - - /** Holds the name of the proeprty to get the. */ - public static final String SELECTOR_PROPNAME = "selector"; - - /** Holds the default message selector. */ - public static final String SELECTOR_DEFAULT = ""; - - /** Holds the name of the property to get the waiting timeout for response messages. */ - public static final String TIMEOUT_PROPNAME = "timeout"; - - /** Default time to wait before assuming that a ping has timed out. */ - public static final long TIMEOUT_DEFAULT = 30000; - - /** Holds the name of the property to get the commit batch size from. */ - public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize"; - - /** Defines the default number of pings to send in each transaction when running transactionally. */ - public static final int TX_BATCH_SIZE_DEFAULT = 1; - - /** Holds the name of the property to set the maximum amount of pending message data for a producer to hold. */ - public static final String MAX_PENDING_PROPNAME = "maxPending"; - - /** Defines the default maximum quantity of pending message data to allow producers to hold. */ - public static final int MAX_PENDING_DEFAULT = 0; - - /** Holds the name of the property to get the publisher rollback flag from. */ - public static final String ROLLBACK_PUBLISHER_PROPNAME = "rollbackPublisher"; - - /** Holds the default publisher roll back setting. */ - public static final boolean ROLLBACK_PUBLISHER_DEFAULT = false; - - /** Holds the name of the property to get the publisher rollback flag from. */ - public static final String ROLLBACK_RECEIVER_PROPNAME = "rollbackReceiver"; - - /** Holds the default publisher roll back setting. */ - public static final boolean ROLLBACK_RECEIVER_DEFAULT = false; - - // ====================== Options that control the bahviour of the test framework. ========================= - - /** Holds the name of the property to get the behavioural mode of not applicable assertions. */ - public static final String NOT_APPLICABLE_ASSERTION_PROPNAME = "notApplicableAssertion"; - - /** Holds the default behavioral mode of not applicable assertions, which is logging them as a warning. */ - public static final String NOT_APPLICABLE_ASSERTION_DEFAULT = "warn"; - - /** Holds the name of the property to get the verbose mode proeprty from. */ - public static final String VERBOSE_PROPNAME = "verbose"; - - /** Holds the default verbose mode. */ - public static final boolean VERBOSE_DEFAULT = false; - - /** Holds the default configuration properties. */ - public static ParsedProperties defaults = new ParsedProperties(); - - static - { - defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT); - defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT); - defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT); - defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT); - defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT); - - defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT); - defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT); - defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT); - defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT); - defaults.setPropertyIfNull(PUBLISHER_CONSUMER_ACTIVE_PROPNAME, PUBLISHER_CONSUMER_ACTIVE_DEFAULT); - defaults.setPropertyIfNull(RECEIVER_CONSUMER_ACTIVE_PROPNAME, RECEIVER_CONSUMER_ACTIVE_DEFAULT); - defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT); - defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT); - defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT); - defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT); - - defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT); - defaults.setPropertyIfNull(TRANSACTED_PUBLISHER_PROPNAME, TRANSACTED_PUBLISHER_DEFAULT); - defaults.setPropertyIfNull(TRANSACTED_RECEIVER_PROPNAME, TRANSACTED_RECEIVER_DEFAULT); - defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT); - defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT); - defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT); - - defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT); - defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT); - defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT); - defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT); - defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT); - - defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT); - defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT); - defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT); - defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT); - defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT); - defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT); - defaults.setPropertyIfNull(ROLLBACK_PUBLISHER_PROPNAME, ROLLBACK_PUBLISHER_DEFAULT); - defaults.setPropertyIfNull(ROLLBACK_RECEIVER_PROPNAME, ROLLBACK_RECEIVER_DEFAULT); - - defaults.setPropertyIfNull(NOT_APPLICABLE_ASSERTION_PROPNAME, NOT_APPLICABLE_ASSERTION_DEFAULT); - defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT); - } - - /** - * Creates a test configuration based on the defaults. - */ - public MessagingTestConfigProperties() - { - super(defaults); - } - - /** - * Creates a test configuration based on the supplied properties. - * - * @param properties The test configuration. - */ - public MessagingTestConfigProperties(Properties properties) - { - super(properties); - } - - /** - * The size of test messages to send. - * - * @return The size of test messages to send. - */ - public int getMessageSize() - { - return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME); - } - - /** - * Flag to indicate that the publishing producer should be set up to publish to a destination. - * - * @return Flag to indicate that the publishing producer should be set up to publish to a destination. - */ - public boolean getPublisherProducerBind() - { - return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME); - } - - /** - * Flag to indicate that the publishing consumer should be set up to receive from a destination. - * - * @return Flag to indicate that the publishing consumer should be set up to receive from a destination. - */ - public boolean getPublisherConsumerBind() - { - return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME); - } - - /** - * Flag to indicate that the receiving producer should be set up to publish to a destination. - * - * @return Flag to indicate that the receiving producer should be set up to publish to a destination. - */ - public boolean getReceiverProducerBind() - { - return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME); - } - - /** - * Flag to indicate that the receiving consumer should be set up to receive from a destination. - * - * @return Flag to indicate that the receiving consumer should be set up to receive from a destination. - */ - public boolean getReceiverConsumerBind() - { - return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME); - } - - /** - * Flag to indicate that the publishing consumer should be created and actively listening. - * - * @return Flag to indicate that the publishing consumer should be created. - */ - public boolean getPublisherConsumerActive() - { - return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME); - } - - /** - * Flag to indicate that the receiving consumers should be created and actively listening. - * - * @return Flag to indicate that the receiving consumers should be created and actively listening. - */ - public boolean getReceiverConsumerActive() - { - return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME); - } - - /** - * A root to create all test destination names from. - * - * @return A root to create all test destination names from. - */ - public String getSendDestinationNameRoot() - { - return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME); - } - - /** - * A root to create all receiving destination names from. - * - * @return A root to create all receiving destination names from. - */ - public String getReceiveDestinationNameRoot() - { - return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME); - } - - /** - * Flag to indicate that persistent messages should be used. - * - * @return Flag to indicate that persistent messages should be used. - */ - public boolean getPersistentMode() - { - return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME); - } - - /** - * Flag to indicate that transactional messages should be sent by the publisher. - * - * @return Flag to indicate that transactional messages should be sent by the publisher. - */ - public boolean getPublisherTransacted() - { - return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME); - } - - /** - * Flag to indicate that transactional receives should be used by the receiver. - * - * @return Flag to indicate that transactional receives should be used by the receiver. - */ - public boolean getReceiverTransacted() - { - return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME); - } - - /** - * The name of the virtual host to run all tests over. - * - * @return The name of the virtual host to run all tests over. - */ - public String getVirtualHost() - { - return getProperty(VIRTUAL_HOST_PROPNAME); - } - - /** - * Limiting rate for each sender in messages per second, or zero for unlimited. - * - * @return Limiting rate for each sender in messages per second, or zero for unlimited. - */ - public String getRate() - { - return getProperty(RATE_PROPNAME); - } - - /** - * Flag to indicate that test messages should be received publish/subscribe style by all receivers. - * - * @return Flag to indicate that test messages should be received publish/subscribe style by all receivers. - */ - public boolean getPubsub() - { - return getPropertyAsBoolean(PUBSUB_PROPNAME); - } - - /** - * The username credentials to run tests with. - * - * @return The username credentials to run tests with. - */ - public String getUsername() - { - return getProperty(USERNAME_PROPNAME); - } - - /** - * The password credentials to run tests with. - * - * @return The password credentials to run tests with. - */ - public String getPassword() - { - return getProperty(PASSWORD_PROPNAME); - } - - /** - * The timeout duration to fail tests on, should they receive no messages within it. - * - * @return The timeout duration to fail tests on, should they receive no messages within it. - */ - public long getTimeout() - { - return getPropertyAsLong(TIMEOUT_PROPNAME); - } - - /** - * The number of messages to batch into each transaction in transational tests. - * - * @return The number of messages to batch into each transaction in transational tests. - */ - public int getTxBatchSize() - { - return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME); - } - - /** - * Flag to indicate that tests should use durable destinations. - * - * @return Flag to indicate that tests should use durable destinations. - */ - public boolean getDurableDests() - { - return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME); - } - - /** - * The ack mode for message receivers to use. - * - * @return The ack mode for message receivers to use. - */ - public int getAckMode() - { - return getPropertyAsInteger(ACK_MODE_PROPNAME); - } - - /** - * Flag to indicate that tests should use durable subscriptions. - * - * @return Flag to indicate that tests should use durable subscriptions. - */ - public boolean getDurableSubscription() - { - return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME); - } - - /** - * The maximum amount of in-flight data, in bytes, that tests should send at any time. - * - * @return The maximum amount of in-flight data, in bytes, that tests should send at any time. - */ - public int getMaxPending() - { - return getPropertyAsInteger(MAX_PENDING_PROPNAME); - } - - /** - * The size of the prefetch queue to use. - * - * @return The size of the prefetch queue to use. - */ - public int getPrefetch() - { - return getPropertyAsInteger(PREFETCH_PROPNAME); - } - - /** - * Flag to indicate that subscriptions should be no-local. - * - * @return Flag to indicate that subscriptions should be no-local. - */ - public boolean getNoLocal() - { - return getPropertyAsBoolean(NO_LOCAL_PROPNAME); - } - - /** - * Flag to indicate that subscriptions should be exclusive. - * - * @return Flag to indicate that subscriptions should be exclusive. - */ - public boolean getExclusive() - { - return getPropertyAsBoolean(EXCLUSIVE_PROPNAME); - } - - /** - * Flag to indicate that messages must be delivered immediately. - * - * @return Flag to indicate that messages must be delivered immediately. - */ - public boolean getImmediate() - { - return getPropertyAsBoolean(IMMEDIATE_PROPNAME); - } - - /** - * Flag to indicate that messages must be routable. - * - * @return Flag to indicate that messages must be routable. - */ - public boolean getMandatory() - { - return getPropertyAsBoolean(MANDATORY_PROPNAME); - } - - /** - * Gets the value of a flag to indicate that the publisher should rollback all messages sent. - * - * @return A flag to indicate that the publisher should rollback all messages sent. - */ - public boolean getRollbackPublisher() - { - return getPropertyAsBoolean(ROLLBACK_PUBLISHER_PROPNAME); - } - - /** - * Gets the value of a flag to indicate that the receiver should rollback all messages received, then receive them - * again. - * - * @return A flag to indicate that the publisher should rollback all messages received. - */ - public boolean getRollbackReceiver() - { - return getPropertyAsBoolean(ROLLBACK_RECEIVER_PROPNAME); - } - - /** - * Gets the behavioural mode of not applicable assertions. Should be one of 'quiet', 'warn' or 'fail'. - * - * @return The behavioural mode of not applicable assertions. - */ - public String getNotApplicableAssertionMode() - { - return getProperty(NOT_APPLICABLE_ASSERTION_PROPNAME); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java b/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java deleted file mode 100644 index 2a20be12d6..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -/** - * NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not - * applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be - * being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this - * instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them - * as warnings to the console, or raise them as test failures. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Quitely pass. - *
Log a warning. - *
Raise a test failure. - *
- */ -public class NotApplicableAssertion implements Assertion -{ - /** Used for logging to the console. */ - private static final Logger console = Logger.getLogger("CONSOLE." + NotApplicableAssertion.class.getName()); - - /** The possible behavioural modes of this assertion. */ - private enum Mode - { - /** Quietly ignore the assertion by passing. */ - Quiet, - - /** Ignore the assertion by passing but log a warning about it. */ - Warn, - - /** Fail the assertion. */ - Fail; - } - - /** The behavioural mode of the assertion. */ - private Mode mode; - - /** - * Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test - * configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically - * read as 'fail'. - * - * @param testProperties The test configuration properties. - */ - public NotApplicableAssertion(ParsedProperties testProperties) - { - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties); - - String modeName = props.getNotApplicableAssertionMode(); - - if ("quiet".equals(modeName)) - { - mode = Mode.Quiet; - } - else if ("warn".equals(modeName)) - { - mode = Mode.Warn; - } - else - { - mode = Mode.Fail; - } - } - - /** - * Applies the assertion. - * - * @return true if the assertion passes, false if it fails. - */ - public boolean apply() - { - switch (mode) - { - case Quiet: - return true; - - case Warn: - console.warn("Warning: Not applicable assertion being ignored."); - - return true; - - case Fail: - default: - return false; - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java deleted file mode 100644 index 2c8be4f787..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -/** - * A Publisher represents the status of the publishing side of a test circuit. Its main purpose is to provide assertions - * that can be applied to test the behaviour of the publishers. - * - *

- *
CRC Card
Responsibilities - *
Provide assertion that the publishers received no exceptions. - *
- * - * @todo There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a - * warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes. - * I am tempted to go with the dropping/warning/error approach, that would imply that it makes sense to pull - * the assertions back from AMQPPublisher to here. - */ -public interface Publisher -{ - // Assertions that are meaningfull to AMQP and to JMS. - - /** - * Provides an assertion that the publisher encountered no exceptions. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the publisher encountered no exceptions. - */ - public Assertion noExceptionsAssertion(ParsedProperties testProps); - - // Assertions that are meaningfull only to AMQP. - - /** - * Provides an assertion that the AMQP channel was forcibly closed by an error condition. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the AMQP channel was forcibly closed by an error condition. - */ - public Assertion channelClosedAssertion(ParsedProperties testProps); - - // Assertions that are meaningfull only to Java/JMS. - - /** - * Provides an assertion that the publisher got a given exception during the test. - * - * @param testProps The test configuration properties. - * @param exceptionClass The exception class to check for. - * - * @return An assertion that the publisher got a given exception during the test. - */ - public Assertion exceptionAssertion(ParsedProperties testProps, Class exceptionClass); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java deleted file mode 100644 index 19dc4d90e7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -/** - * A Receiver is a {@link CircuitEnd} that represents the status of the receiving side of a test circuit. Its main - * purpose is to provide assertions that can be applied to check the behaviour of the receivers. - * - *

- *
CRC Card
Responsibilities - *
Provide assertion that the receivers received no exceptions. - *
Provide assertion that the receivers received all test messages sent to it. - *
- * - * @todo There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a - * warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes. - * I am tempted to go with the dropping/warning/error approach. - */ -public interface Receiver -{ - // Assertions that are meaningfull to AMQP and to JMS. - - /** - * Provides an assertion that the receivers encountered no exceptions. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the receivers encountered no exceptions. - */ - public Assertion noExceptionsAssertion(ParsedProperties testProps); - - /** - * Provides an assertion that the receivers got all messages that were sent to it. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the receivers got all messages that were sent to it. - */ - public Assertion allMessagesReceivedAssertion(ParsedProperties testProps); - - /** - * Provides an assertion that the receivers got none of the messages that were sent to it. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the receivers got none of the messages that were sent to it. - */ - public Assertion noMessagesReceivedAssertion(ParsedProperties testProps); - - // Assertions that are meaningfull only to AMQP. - - /** - * Provides an assertion that the AMQP channel was forcibly closed by an error condition. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the AMQP channel was forcibly closed by an error condition. - */ - public Assertion channelClosedAssertion(ParsedProperties testProps); - - // Assertions that are meaningfull only to Java/JMS. - - /** - * Provides an assertion that the receiver got a given exception during the test. - * - * @param testProps The test configuration properties. - * @param exceptionClass The exception class to check for. - * - * @return An assertion that the receiver got a given exception during the test. - */ - public Assertion exceptionAssertion(ParsedProperties testProps, Class exceptionClass); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java b/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java deleted file mode 100644 index ad1e70f6f7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - *

- *
CRC Card
Responsibilities Collaborations - *
- *
- */ -public class TestCaseVector -{ - /** The test case name. */ - private String testCase; - - /** The test cycle number within the test case. */ - private int testCycleNumber; - - public TestCaseVector(String testCase, int testCycleNumber) - { - this.testCase = testCase; - this.testCycleNumber = testCycleNumber; - } - - public String getTestCase() - { - return testCase; - } - - public int getTestCycleNumber() - { - return testCycleNumber; - } - - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - - if ((o == null) || (getClass() != o.getClass())) - { - return false; - } - - TestCaseVector that = (TestCaseVector) o; - - if (testCycleNumber != that.testCycleNumber) - { - return false; - } - - if ((testCase != null) ? (!testCase.equals(that.testCase)) : (that.testCase != null)) - { - return false; - } - - return true; - } - - public int hashCode() - { - int result; - result = ((testCase != null) ? testCase.hashCode() : 0); - result = (31 * result) + testCycleNumber; - - return result; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/TestClientDetails.java b/java/systests/src/main/java/org/apache/qpid/test/framework/TestClientDetails.java deleted file mode 100644 index 7498f2b6b5..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/TestClientDetails.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -/** - * TestClientDetails is used to encapsulate information about an interop test client. It pairs together the unique - * name of the client, and the route on which it listens to its control messages. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Record test clients control addresses together with their names. - *
- */ -public class TestClientDetails -{ - /** The test clients name. */ - public String clientName; - - /* The test clients unique sequence number. Not currently used. */ - - /** The routing key of the test clients control topic. */ - public String privateControlKey; - - /** - * Two TestClientDetails are considered to be equal, iff they have the same client name. - * - * @param o The object to compare to. - * - * @return If the object to compare to is a TestClientDetails equal to this one, false otherwise. - */ - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - - if (!(o instanceof TestClientDetails)) - { - return false; - } - - final TestClientDetails testClientDetails = (TestClientDetails) o; - - return !((clientName != null) ? (!clientName.equals(testClientDetails.clientName)) - : (testClientDetails.clientName != null)); - } - - /** - * Computes a hash code compatible with the equals method; based on the client name alone. - * - * @return A hash code for this. - */ - public int hashCode() - { - return ((clientName != null) ? clientName.hashCode() : 0); - } - - /** - * Outputs the client name and address details. Mostly used for debugging purposes. - * - * @return The client name and address. - */ - public String toString() - { - return "TestClientDetails: [ clientName = " + clientName + ", privateControlKey = " + privateControlKey + " ]"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java deleted file mode 100644 index 919faa4754..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.BROKER_PROPNAME; -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.CONNECTION_NAME; -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.PASSWORD_PROPNAME; -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.USERNAME_PROPNAME; -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.VIRTUAL_HOST_PROPNAME; - -import javax.jms.BytesMessage; -import javax.jms.Connection; -import javax.jms.ConnectionFactory; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import java.util.Map; - -/** - * TestUtils provides static helper methods that are usefull for writing tests against QPid. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Create connections from test properties. {@link MessagingTestConfigProperties} - *
Create test messages. - *
Inject a short pause in a test. - *
Serialize properties into a message. - *
- */ -public class TestUtils -{ - /** Used for debugging. */ - private static Logger log = Logger.getLogger(TestUtils.class); - - /** Some dummy data to stuff all test messages with. */ - private static final byte[] MESSAGE_DATA_BYTES = - "Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- " - .getBytes(); - - /** - * Establishes a JMS connection using a set of properties and qpids built in JNDI implementation. This is a simple - * convenience method for code that does not anticipate handling connection failures. All exceptions that indicate - * that the connection has failed, are wrapped as rutime exceptions, presumably handled by a top level failure - * handler. - * - *

This utility makes use of the following test parameters from {@link MessagingTestConfigProperties} to control - * the connection creation: - * - *

- * + + + + + #doc- + + + + + + #- + + + + + + + + + + + + +

section-

+
+ +
+
+ + + + + + +

doc-

+
+ +
+ + +

doc-

+
+
+ +
+
+
+
+ + + + + pre + + + + + + + + + + + #section- + + + + #type- + + + + #doc- + + + .xml + + + + + + + + + + + + + +

type-

+ + signature +
+ + + Encodings: + composite + + + + + + + + +

type-

+ + + composite fields + +
+ + + + + + + + +

type-

+ + + compositepossible values + +
+ + + + + + + +
{@link MessagingTestConfigProperties#USERNAME_PROPNAME} The username. - *
{@link MessagingTestConfigProperties#PASSWORD_PROPNAME} The password. - *
{@link MessagingTestConfigProperties#VIRTUAL_HOST_PROPNAME} The virtual host name. - *
{@link MessagingTestConfigProperties#BROKER_PROPNAME} The broker URL. - *
{@link MessagingTestConfigProperties#CONNECTION_NAME} The broker name in the initial context. - * - * @param messagingProps Connection properties as defined in {@link MessagingTestConfigProperties}. - * - * @return A JMS conneciton. - */ - public static Connection createConnection(ParsedProperties messagingProps) - { - log.debug("public static Connection createConnection(ParsedProperties messagingProps = " + messagingProps - + "): called"); - - try - { - // Extract the configured connection properties from the test configuration. - String conUsername = messagingProps.getProperty(USERNAME_PROPNAME); - String conPassword = messagingProps.getProperty(PASSWORD_PROPNAME); - String virtualHost = messagingProps.getProperty(VIRTUAL_HOST_PROPNAME); - String brokerUrl = messagingProps.getProperty(BROKER_PROPNAME); - - // Create the broker connection url. - String connectionString = - "amqp://" + conUsername + ":" + conPassword + "@clientid/" + ((virtualHost != null) ? virtualHost : "") - + "?brokerlist='" + brokerUrl + "'"; - - // Create properties to create the initial context from, and inject the connection factory configuration - // for the defined connection name into it. - messagingProps.setProperty("connectionfactory." + CONNECTION_NAME, connectionString); - - Context ctx = new InitialContext(messagingProps); - - ConnectionFactory cf = (ConnectionFactory) ctx.lookup(CONNECTION_NAME); - - return cf.createConnection(); - } - catch (NamingException e) - { - throw new RuntimeException("Got JNDI NamingException whilst looking up the connection factory.", e); - } - catch (JMSException e) - { - throw new RuntimeException("Could not establish connection due to JMSException.", e); - } - } - - /** - * Creates a test message of the specified size, on the given JMS session. - * - * @param session The JMS session. - * @param size The size of the message in bytes. - * - * @return A bytes message, of the specified size, filled with dummy data. - * - * @throws JMSException Any underlying JMSExceptions are allowed to fall through. - */ - public static Message createTestMessageOfSize(Session session, int size) throws JMSException - { - BytesMessage message = session.createBytesMessage(); - - if (size > 0) - { - int div = size / MESSAGE_DATA_BYTES.length; - int mod = size % MESSAGE_DATA_BYTES.length; - - for (int i = 0; i < div; i++) - { - message.writeBytes(MESSAGE_DATA_BYTES); - } - - if (mod != 0) - { - message.writeBytes(MESSAGE_DATA_BYTES, 0, mod); - } - } - - return message; - } - - /** - * Pauses for the specified length of time. In the event of failing to pause for at least that length of time - * due to interuption of the thread, a RutimeException is raised to indicate the failure. The interupted status - * of the thread is restores in that case. This method should only be used when it is expected that the pause - * will be succesfull, for example in test code that relies on inejecting a pause. - * - * @param t The minimum time to pause for in milliseconds. - */ - public static void pause(long t) - { - try - { - Thread.sleep(t); - } - catch (InterruptedException e) - { - // Restore the interrupted status - Thread.currentThread().interrupt(); - - throw new RuntimeException("Failed to generate the requested pause length.", e); - } - } - - /** - * Sets properties of different types on a JMS Message. - * - * @param message The message to set properties on. - * @param properties The property name/value pairs to set. - * - * @throws javax.jms.JMSException All underlying JMSExceptions are allowed to fall through. - * - * @todo Move this helper method somewhere else. For example, TestUtils. - */ - public static void setPropertiesOnMessage(Message message, Map properties) throws JMSException - { - for (Map.Entry entry : properties.entrySet()) - { - String name = entry.getKey().toString(); - Object value = entry.getValue(); - - message.setObjectProperty(name, value); - } - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java deleted file mode 100644 index 00cc2d8966..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.clocksynch; - -/** - * ClockSynchFailureException represents failure of a {@link ClockSynchronizer} to achieve synchronization. For example, - * this could be because a reference signal is not available, or because a desired accurracy cannot be attained. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Represent failure to achieve synchronization. - *
- */ -public class ClockSynchFailureException extends Exception -{ - /** - * Creates a clock synch failure exception. - * - * @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method). - * @param cause The cause (which is saved for later retrieval by the {@link #getCause()} method). (A null - * value is permitted, and indicates that the cause is nonexistent or unknown.) - */ - public ClockSynchFailureException(String message, Throwable cause) - { - super(message, cause); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchThread.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchThread.java deleted file mode 100644 index 3d4c4f7d12..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchThread.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.clocksynch; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.ShutdownHookable; -import org.apache.qpid.junit.extensions.Throttle; - -/** - * ClockSynchThread is a convenient utility for running a thread that periodically synchronizes the clock against - * a reference. Supply it with a {@link ClockSynchronizer} and a {@link Throttle} and it will continually keep the - * clock up-to-date at a rate determined by the throttle. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Continually sychronize the clock at a throttled rate. - *
- */ -public class ClockSynchThread extends Thread implements ShutdownHookable -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(ClockSynchThread.class); - - /** Holds the clock syncher for the synch thread. */ - private ClockSynchronizer clockSyncher; - - /** Holds the throttle to limit the synch rate. */ - private Throttle throttle; - - /** Flag to indicate that the periodic clock syncher should keep running. */ - boolean doSynch = true; - - /** - * Creates a clock synchronizer thread from a clock synchronizer and a throttle. - * - * @param syncher The clock synchronizer. - * @param throttle The throttle. - */ - public ClockSynchThread(ClockSynchronizer syncher, Throttle throttle) - { - this.clockSyncher = syncher; - this.throttle = throttle; - } - - /** - * Terminates the synchronization thread. - */ - public void terminate() - { - doSynch = false; - } - - /** - * Continually updates the clock, until {@link #terminate()} is called. - */ - public void run() - { - while (doSynch) - { - // Perform a clock clockSynch. - try - { - // Wait controlled by the throttle before doing the next synch. - throttle.throttle(); - - clockSyncher.synch(); - log.debug("Clock synched, delta = " + clockSyncher.getDelta() + ", epsilon = " + clockSyncher.getEpsilon() - + "."); - } - // Terminate the synch thread if the synchronization cannot be achieved. - catch (ClockSynchFailureException e) - { - log.debug("Cannot synchronize the clock (reference service may be down). Terminating the synch thread."); - doSynch = false; - } - } - } - - /** - * Gets the clock synchronizer that is kept continually up to date. - * - * @return The clock synchronizer that is kept continually up to date. - */ - public ClockSynchronizer getClockSyncher() - { - return clockSyncher; - } - - /** - * Supplies a shutdown hook, that terminates the synching thread. - * - * @return The shut down hook. - */ - public Thread getShutdownHook() - { - return new Thread(new Runnable() - { - public void run() - { - doSynch = false; - } - }); - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java deleted file mode 100644 index a92c551bc2..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.clocksynch; - -/** - * ClockSynchronizer provides an interface through which two nodes may synchronize their clocks. It is expected that one - * node will act as the reference clock, to which no delta need be applied, and the other node will act as the slave, - * and which must apply a delta to its local clock to get a clock synchronized with the reference. - * - *

The slave side will initiate the computation of a clock delta by calling the {@link #synch} method. This method - * will not return until the delta has been computed, at which point there is a method to return its value, as well as - * an estimate of the likely error (usually one standard deviation), in the synchronization. For convenience there is a - * {@link #nanoTime} method to return the value of System.nanoTime() with the delta added in. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Trigger a clock synchronization. - *
Compute a clock delta to apply to the local clock. - *
Estimate the error in the synchronzation. - *
- */ -public interface ClockSynchronizer -{ - /** - * The slave side should call this to copute a clock delta with the reference. - * - * @throws ClockSynchFailureException If synchronization cannot be achieved. - */ - public void synch() throws ClockSynchFailureException; - - /** - * Gets the clock delta in nano seconds. - * - * @return The clock delta in nano seconds. - */ - public long getDelta(); - - /** - * Gets an estimate of the clock error in nan seconds. - * - * @return An estimate of the clock error in nan seconds. - */ - public long getEpsilon(); - - /** - * Gets the local clock time with any computed delta added in. - * - * @return The local clock time with any computed delta added in. - */ - public long nanoTime(); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/LocalClockSynchronizer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/LocalClockSynchronizer.java deleted file mode 100644 index f448d5f23c..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/LocalClockSynchronizer.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.clocksynch; - -/** - * LocalClockSynchronizer is a fake {@link ClockSynchronizer} that simply calls System.nanoTime(). It exists so that - * the same tests can be run distributed or locally, taking timings against the ClockSynchronizer interface without - * being aware of how they are being run. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Supply the local clock with no delta. - *
- */ -public class LocalClockSynchronizer implements ClockSynchronizer -{ - /** - * The slave side should call this to copute a clock delta with the reference. - * - * @throws org.apache.qpid.test.framework.clocksynch.ClockSynchFailureException - * If synchronization cannot be achieved. - */ - public void synch() throws ClockSynchFailureException - { } - - /** - * Gets the clock delta in nano seconds. - * - * @return The clock delta in nano seconds. - */ - public long getDelta() - { - return 0L; - } - - /** - * Gets an estimate of the clock error in nan seconds. - * - * @return An estimate of the clock error in nan seconds. - */ - public long getEpsilon() - { - return 0L; - } - - /** - * Gets the local clock time with any computed delta added in. - * - * @return The local clock time with any computed delta added in. - */ - public long nanoTime() - { - return System.nanoTime(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockReference.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockReference.java deleted file mode 100644 index 8ee8d82636..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockReference.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.clocksynch; - -import org.apache.qpid.junit.extensions.ShutdownHookable; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.nio.ByteBuffer; - -/** - * UDPClockReference supplies a refernce clock signal (generated from System.nanoTime()). - * - *

- *
CRC Card
Responsibilities Collaborations - *
Supply a reference clock signal. - *
- * - * @todo Port hard coded. Make configurable. - * - * @todo Errors rethrown as runtimes, or silently terminate the service. Could add better error handling if needed. - */ -public class UDPClockReference implements Runnable, ShutdownHookable -{ - /** Used for debugging. */ - // private static final Logger log = Logger.getLogger(UDPClockReference.class); - - /** Defines the timeout to use when polling the socket for time requests. */ - private static final int TIMEOUT = 200; - - /** Defines the port to run the clock reference on. */ - public static final int REFERENCE_PORT = 4444; - - /** Holds the socket to receive clock reference requests on. */ - protected DatagramSocket socket = null; - - /** Flag used to indicate that the time server should keep running. Set to false to terminate. */ - protected boolean publish = true; - - /** - * Creates a clock reference service on the standard port. - */ - public UDPClockReference() - { - try - { - socket = new DatagramSocket(REFERENCE_PORT); - socket.setSoTimeout(TIMEOUT); - } - catch (SocketException e) - { - throw new RuntimeException(e); - } - } - - /** - * Implements the run loop for this reference time server. This waits for incoming time requests, and replies to - * any, with a message with the local time stamp in it. Periodically (controlled by {@link #TIMEOUT}), the run - * loop will check if the {@link #publish} flag has been cleared, and terminate the reference time service if so. - */ - public void run() - { - byte[] buf = new byte[256]; - ByteBuffer bbuf = ByteBuffer.wrap(buf); - - while (publish) - { - try - { - // Wait for a reference time request. - DatagramPacket packet = new DatagramPacket(buf, buf.length); - boolean timedOut = false; - - try - { - socket.receive(packet); - } - catch (SocketTimeoutException e) - { - timedOut = true; - } - - if (!timedOut) - { - // Work out from the received packet, where to reply to. - InetAddress address = packet.getAddress(); - int port = packet.getPort(); - - // Respond to the time request by sending back the local clock as the reference time. - bbuf.putLong(System.nanoTime()); - bbuf.flip(); - packet = new DatagramPacket(bbuf.array(), bbuf.capacity(), address, port); - - socket.send(packet); - } - } - catch (IOException e) - { - publish = false; - } - } - - socket.close(); - } - - /** - * Supplies a shutdown hook. - * - * @return The shut down hook. - */ - public Thread getShutdownHook() - { - return new Thread(new Runnable() - { - public void run() - { - publish = false; - } - }); - } - - /** - * For testing purposes. Runs a reference clock on the default port. - * - * @param args None. - */ - public static void main(String[] args) - { - try - { - // Create the clock reference service. - UDPClockReference clock = new UDPClockReference(); - - // Set up a shutdown hook for it. - Runtime.getRuntime().addShutdownHook(clock.getShutdownHook()); - - // Start the service. - clock.run(); - } - catch (Exception e) - { - e.printStackTrace(); - System.exit(1); - } - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockSynchronizer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockSynchronizer.java deleted file mode 100644 index 226c84611d..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/UDPClockSynchronizer.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.clocksynch; - -import org.apache.qpid.junit.extensions.util.CommandLineParser; -import org.apache.qpid.junit.extensions.util.ParsedProperties; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * UDPClockSynchronizer is a {@link ClockSynchronizer} that sends pings as UDP datagrams, and uses the following simple - * algorithm to perform clock synchronization: - * - *

    - *
  1. Slave initiates synchronization with a Reference clock.
  2. - *
  3. Slave stamps current local time on a "time request" message and sends to the Reference.
  4. - *
  5. Upon receipt by Reference, Reference stamps Reference-time and returns.
  6. - *
  7. Upon receipt by Slave, Slave subtracts current time from sent time and divides by two to compute latency. It - * subtracts current time from Reference time to determine Slave-Reference time delta and adds in the - * half-latency to get the correct clock delta.
  8. - *
  9. The first result is immediately used to update the clock since it will get the local clock into at least - * the right ballpark.
  10. - *
  11. The Slave repeats steps 2 through 4, 15 more times.
  12. - *
  13. The results of the packet receipts are accumulated and sorted in lowest-latency to highest-latency order. The - * median latency is determined by picking the mid-point sample from this ordered list.
  14. - *
  15. All samples outside 1 standard-deviation from the median are discarded and the remaining samples - * are averaged using an arithmetic mean.
  16. - *
- * - *

The use of UDP datagrams, instead of TCP based communication eliminates the hidden delays that TCP can introduce, - * as it can transparently re-order or re-send packets, or introduce delays as packets are naggled. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Trigger a clock synchronziation. - *
Compute a clock delta to apply to the local clock. - *
Estimate the error in the synchronzation. - *
- */ -public class UDPClockSynchronizer implements ClockSynchronizer -{ - /** Used for debugging. */ - // private static final Logger log = Logger.getLogger(UDPClockSynchronizer.class); - - /** Defines the timeout to use when waiting for responses to time requests. */ - private static final int TIMEOUT = 50; - - /** The clock delta. */ - private long delta = 0L; - - /** Holds an estimate of the clock error relative to the reference clock. */ - private long epsilon = 0L; - - /** Holds the address of the reference clock. */ - private InetAddress referenceAddress; - - /** Holds the socket to communicate with the reference service over. */ - private DatagramSocket socket; - - /** Used to control the shutdown in the main test loop. */ - private static boolean doSynch = true; - - /** - * Creates a clock synchronizer against the specified address for the reference. - * - * @param address The address of the reference service. - */ - public UDPClockSynchronizer(String address) - { - try - { - referenceAddress = InetAddress.getByName(address); - } - catch (UnknownHostException e) - { - throw new RuntimeException(e); - } - } - - /** - * The slave side should call this to compute a clock delta with the reference. - * - * @throws ClockSynchFailureException If synchronization cannot be achieved, due to unavailability of the reference - * time service. - */ - public void synch() throws ClockSynchFailureException - { - try - { - socket = new DatagramSocket(); - socket.setSoTimeout(TIMEOUT); - - // Synchronize on a single ping, to get the clock into the right ball-park. - synch(1); - - // Synchronize on 15 pings. - synch(15); - - // And again, for greater accuracy, on 31. - synch(31); - - socket.close(); - } - catch (SocketException e) - { - throw new RuntimeException(e); - } - } - - /** - * Updates the synchronization delta by performing the specified number of reference clock requests. - * - * @param n The number of reference clock request cycles to perform. - * - * @throws ClockSynchFailureException If synchronization cannot be achieved, due to unavailability of the reference - * time service. - */ - protected void synch(int n) throws ClockSynchFailureException - { - // log.debug("protected void synch(int n = " + n + "): called"); - - // Create an array of deltas by performing n reference pings. - long[] delta = new long[n]; - - for (int i = 0; i < n; i++) - { - delta[i] = ping(); - } - - // Reject any deltas that are larger than 1 s.d. above the median. - long median = median(delta); - long sd = standardDeviation(delta); - - // log.debug("median = " + median); - // log.debug("sd = " + sd); - - long[] tempDeltas = new long[n]; - int count = 0; - - for (int i = 0; i < n; i++) - { - if ((delta[i] <= (median + sd)) && (delta[i] >= (median - sd))) - { - tempDeltas[count] = delta[i]; - count++; - } - else - { - // log.debug("Rejected: " + delta[i]); - } - } - - System.arraycopy(tempDeltas, 0, delta, 0, count); - - // Estimate the delta as the mean of the remaining deltas. - this.delta += mean(delta); - - // Estimate the error as the standard deviation of the remaining deltas. - this.epsilon = standardDeviation(delta); - - // log.debug("this.delta = " + this.delta); - // log.debug("this.epsilon = " + this.epsilon); - } - - /** - * Performs a single reference clock request cycle and returns the estimated delta relative to the local clock. - * This is computed as the half-latency of the requst cycle, plus the reference clock, minus the local clock. - * - * @return The estimated clock delta. - * - * @throws ClockSynchFailureException If the reference service is not responding. - */ - protected long ping() throws ClockSynchFailureException - { - // log.debug("protected long ping(): called"); - - try - { - byte[] buf = new byte[256]; - - boolean timedOut = false; - long start = 0L; - long refTime = 0L; - long localTime = 0L; - long latency = 0L; - int failCount = 0; - - // Keep trying the ping until it gets a response, or 10 tries in a row all time out. - do - { - // Start timing the request latency. - start = nanoTime(); - - // Get the reference time. - DatagramPacket packet = - new DatagramPacket(buf, buf.length, referenceAddress, UDPClockReference.REFERENCE_PORT); - socket.send(packet); - packet = new DatagramPacket(buf, buf.length); - - timedOut = false; - - try - { - socket.receive(packet); - } - catch (SocketTimeoutException e) - { - timedOut = true; - failCount++; - - continue; - } - - ByteBuffer bbuf = ByteBuffer.wrap(packet.getData()); - refTime = bbuf.getLong(); - - // Stop timing the request latency. - localTime = nanoTime(); - latency = localTime - start; - - // log.debug("refTime = " + refTime); - // log.debug("localTime = " + localTime); - // log.debug("start = " + start); - // log.debug("latency = " + latency); - // log.debug("delta = " + ((latency / 2) + (refTime - localTime))); - - } - while (timedOut && (failCount < 10)); - - // Fail completely if the fail count is too high. - if (failCount >= 10) - { - throw new ClockSynchFailureException("Clock reference not responding.", null); - } - - // Estimate delta as (ref clock + half-latency) - local clock. - return (latency / 2) + (refTime - localTime); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - /** - * Gets the clock delta in nano seconds. - * - * @return The clock delta in nano seconds. - */ - public long getDelta() - { - return delta; - } - - /** - * Gets an estimate of the clock error in nan seconds. - * - * @return An estimate of the clock error in nan seconds. - */ - public long getEpsilon() - { - return epsilon; - } - - /** - * Gets the local clock time with any computed delta added in. - * - * @return The local clock time with any computed delta added in. - */ - public long nanoTime() - { - return System.nanoTime() + delta; - } - - /** - * Computes the median of a series of values. - * - * @param values The values. - * - * @return The median. - */ - public static long median(long[] values) - { - // log.debug("public static long median(long[] values = " + Arrays.toString(values) + "): called"); - - long median; - - // Order the list of values. - long[] orderedValues = new long[values.length]; - System.arraycopy(values, 0, orderedValues, 0, values.length); - Arrays.sort(orderedValues); - - // Check if the median is computed from a pair of middle value. - if ((orderedValues.length % 2) == 0) - { - int middle = orderedValues.length / 2; - - median = (orderedValues[middle] + orderedValues[middle - 1]) / 2; - } - // The median is computed from a single middle value. - else - { - median = orderedValues[orderedValues.length / 2]; - } - - // log.debug("median = " + median); - - return median; - } - - /** - * Computes the mean of a series of values. - * - * @param values The values. - * - * @return The mean. - */ - public static long mean(long[] values) - { - // log.debug("public static long mean(long[] values = " + Arrays.toString(values) + "): called"); - - long total = 0L; - - for (long value : values) - { - total += value; - } - - long mean = total / values.length; - - // log.debug("mean = " + mean); - - return mean; - } - - /** - * Computes the variance of series of values. - * - * @param values The values. - * - * @return The variance of the values. - */ - public static long variance(long[] values) - { - // log.debug("public static long variance(long[] values = " + Arrays.toString(values) + "): called"); - - long mean = mean(values); - - long totalVariance = 0; - - for (long value : values) - { - long diff = (value - mean); - totalVariance += diff * diff; - } - - long variance = totalVariance / values.length; - - // log.debug("variance = " + variance); - - return variance; - } - - /** - * Computes the standard deviation of a series of values. - * - * @param values The values. - * - * @return The standard deviation. - */ - public static long standardDeviation(long[] values) - { - // log.debug("public static long standardDeviation(long[] values = " + Arrays.toString(values) + "): called"); - - long sd = Double.valueOf(Math.sqrt(variance(values))).longValue(); - - // log.debug("sd = " + sd); - - return sd; - } - - /** - * For testing purposes. Supply address of reference clock as arg 1. - * - * @param args Address of reference clock as arg 1. - */ - public static void main(String[] args) - { - ParsedProperties options = - new ParsedProperties(CommandLineParser.processCommandLine(args, - new CommandLineParser( - new String[][] - { - { "1", "Address of clock reference service.", "address", "true" } - }), System.getProperties())); - - String address = options.getProperty("1"); - - // Create a clock synchronizer. - UDPClockSynchronizer clockSyncher = new UDPClockSynchronizer(address); - - // Set up a shutdown hook for it. - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() - { - public void run() - { - doSynch = false; - } - })); - - // Repeat the clock synching until the user kills the progam. - while (doSynch) - { - // Perform a clock clockSynch. - try - { - clockSyncher.synch(); - - // Print out the clock delta and estimate of the error. - System.out.println("Delta = " + clockSyncher.getDelta()); - System.out.println("Epsilon = " + clockSyncher.getEpsilon()); - - try - { - Thread.sleep(250); - } - catch (InterruptedException e) - { - // Restore the interrupted status and terminate the loop. - Thread.currentThread().interrupt(); - doSynch = false; - } - } - // Terminate if the reference time service is unavailable. - catch (ClockSynchFailureException e) - { - doSynch = false; - } - } - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java deleted file mode 100644 index 6c950fc307..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedcircuit; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.TimingController; -import org.apache.qpid.junit.extensions.TimingControllerAware; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.Publisher; -import org.apache.qpid.test.framework.Receiver; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; -import java.util.LinkedList; -import java.util.List; - -/** - * DistributedCircuitImpl is a distributed implementation of the test {@link Circuit}. Many publishers and receivers - * accross multiple machines may be combined to form a single test circuit. The test circuit extracts reports from - * all of its publishers and receivers, and applies its assertions to these reports. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Supply the publishing and receiving ends of a test messaging circuit. - *
Start the circuit running. - *
Close the circuit down. - *
Take a reading of the circuits state. - *
Apply assertions against the circuits state. - *
Send test messages over the circuit. - *
Perform the default test procedue on the circuit. - *
- * - * @todo There is a short pause after receiving sender reports before asking for receiver reports, because receivers may - * not have finished receiving all their test messages before the report request arrives. This is going to be a - * problem for taking test timings and needs to be eliminiated. Suggested solution: have receiver send back reports - * asynchronously, on test batch size boundaries, and do so automatically rather than having to have the report - * request sent to them. Number each test run, or otherwise uniquely identify it, when a receiver does not get - * any more messages on a test run for more than a timeout, it can assume the test is complete and send a final - * report. On the coordinator end a future will need to be created to wait for all final reports to come in, and - * to register results and timings for the test. This must work in such a way that a new test cycle can be started - * without waiting for the results of the old one to come in. - * - * @todo Add in setting of timing controller, from timing aware test cases. - */ -public class DistributedCircuitImpl implements Circuit, TimingControllerAware -{ - /** Used for debugging purposes. */ - private static final Logger log = Logger.getLogger(DistributedCircuitImpl.class); - - /** Holds the conversation factory over which to coordinate the test. */ - protected ConversationFactory conversationFactory; - - /** Holds the controlSession over which to hold the control conversation. */ - protected Session controlSession; - - /** Holds the sender nodes in the test circuit. */ - protected List senders; - - /** Holds the receiver nodes in the test circuit. */ - protected List receivers; - - /** Holds the sender control conversations. */ - protected ConversationFactory.Conversation[] senderConversation; - - /** Holds the receiver control conversations. */ - protected ConversationFactory.Conversation[] receiverConversation; - - /** Holds the control topics for the senders in the test circuit. */ - protected Destination[] senderControlTopic; - - /** Holds the control topics for the receivers in the test circuit. */ - protected Destination[] receiverControlTopic; - - /** Holds the number of messages to send per test run. */ - protected int numMessages; - - /** - * Holds the timing controller for the circuit. This is used to log test times asynchronously, when reciever nodes - * return their reports after senders have completed a test case. - */ - TimingController timingController; - - /** - * Creates a distributed test circuit on the specified senders and receivers. - * - * @param session The controlSession for all control conversations. - * @param senders The senders. - * @param receivers The receivers. - * @param senderConversation A control conversation with the senders. - * @param receiverConversation A control conversation with the receivers. - * @param senderControlTopic The senders control topic. - * @param receiverControlTopic The receivers control topic. - */ - protected DistributedCircuitImpl(Session session, List senders, List receivers, - ConversationFactory.Conversation[] senderConversation, ConversationFactory.Conversation[] receiverConversation, - Destination[] senderControlTopic, Destination[] receiverControlTopic) - { - this.controlSession = session; - this.senders = senders; - this.receivers = receivers; - this.senderConversation = senderConversation; - this.receiverConversation = receiverConversation; - this.senderControlTopic = senderControlTopic; - this.receiverControlTopic = receiverControlTopic; - } - - /** - * Creates a distributed test circuit from the specified test parameters, on the senders and receivers - * given. - * - * @param testProps The test parameters. - * @param senders The sender ends in the test circuit. - * @param receivers The receiver ends in the test circuit. - * @param conversationFactory A conversation factory for creating the control conversations with senders and receivers. - * - * @return A connected and ready to start, test circuit. - */ - public static Circuit createCircuit(ParsedProperties testProps, List senders, - List receivers, ConversationFactory conversationFactory) - { - log.debug("public static Circuit createCircuit(ParsedProperties testProps, List senders, " - + " List receivers, ConversationFactory conversationFactory)"); - - try - { - Session session = conversationFactory.getSession(); - - // Create control conversations with each of the senders. - ConversationFactory.Conversation[] senderConversation = new ConversationFactory.Conversation[senders.size()]; - Destination[] senderControlTopic = new Destination[senders.size()]; - - for (int i = 0; i < senders.size(); i++) - { - TestClientDetails sender = senders.get(i); - - senderControlTopic[i] = session.createTopic(sender.privateControlKey); - senderConversation[i] = conversationFactory.startConversation(); - } - - log.debug("Sender conversations created."); - - // Create control conversations with each of the receivers. - ConversationFactory.Conversation[] receiverConversation = new ConversationFactory.Conversation[receivers.size()]; - Destination[] receiverControlTopic = new Destination[receivers.size()]; - - for (int i = 0; i < receivers.size(); i++) - { - TestClientDetails receiver = receivers.get(i); - - receiverControlTopic[i] = session.createTopic(receiver.privateControlKey); - receiverConversation[i] = conversationFactory.startConversation(); - } - - log.debug("Receiver conversations created."); - - // Assign the sender role to each of the sending test clients. - for (int i = 0; i < senders.size(); i++) - { - TestClientDetails sender = senders.get(i); - - Message assignSender = conversationFactory.getSession().createMessage(); - TestUtils.setPropertiesOnMessage(assignSender, testProps); - assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignSender.setStringProperty("ROLE", "SENDER"); - - senderConversation[i].send(senderControlTopic[i], assignSender); - } - - log.debug("Sender role assignments sent."); - - // Assign the receivers role to each of the receiving test clients. - for (int i = 0; i < receivers.size(); i++) - { - TestClientDetails receiver = receivers.get(i); - - Message assignReceiver = session.createMessage(); - TestUtils.setPropertiesOnMessage(assignReceiver, testProps); - assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignReceiver.setStringProperty("ROLE", "RECEIVER"); - - receiverConversation[i].send(receiverControlTopic[i], assignReceiver); - } - - log.debug("Receiver role assignments sent."); - - // Wait for the senders and receivers to confirm their roles. - for (int i = 0; i < senders.size(); i++) - { - senderConversation[i].receive(); - } - - log.debug("Got all sender role confirmations"); - - for (int i = 0; i < receivers.size(); i++) - { - receiverConversation[i].receive(); - } - - log.debug("Got all receiver role confirmations"); - - // Package everything up as a circuit. - return new DistributedCircuitImpl(session, senders, receivers, senderConversation, receiverConversation, - senderControlTopic, receiverControlTopic); - } - catch (JMSException e) - { - throw new RuntimeException("JMSException not handled."); - } - } - - /** - * Used by tests cases that can supply a {@link org.apache.qpid.junit.extensions.TimingController} to set the - * controller on an aware test. - * - * @param controller The timing controller. - */ - public void setTimingController(TimingController controller) - { - this.timingController = controller; - } - - /** - * Gets the interface on the publishing end of the circuit. - * - * @return The publishing end of the circuit. - */ - public Publisher getPublisher() - { - throw new RuntimeException("Not Implemented."); - } - - /** - * Gets the interface on the receiving end of the circuit. - * - * @return The receiving end of the circuit. - */ - public Receiver getReceiver() - { - throw new RuntimeException("Not Implemented."); - } - - /** - * Connects and starts the circuit. After this method is called the circuit is ready to send messages. - */ - public void start() - { - log.debug("public void start(): called"); - - try - { - // Start the test on each of the senders. - Message start = controlSession.createMessage(); - start.setStringProperty("CONTROL_TYPE", "START"); - start.setIntProperty("MESSAGE_COUNT", numMessages); - - for (int i = 0; i < senders.size(); i++) - { - senderConversation[i].send(senderControlTopic[i], start); - } - - log.debug("All senders told to start their tests."); - } - catch (JMSException e) - { - throw new RuntimeException("Unhandled JMSException.", e); - } - } - - /** - * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit, - * into a report, against which assertions may be checked. - * - * @todo Replace the asynch receiver report thread with a choice of direct or asynch executor, so that asynch - * or synch logging of test timings is optional. Also need to provide an onMessage method that is capable - * of receiving timing reports that receivers will generate during an ongoing test, on the test sample - * size boundaries. The message timing logging code should be factored out as a common method that can - * be called in response to the final report responses, or the onMessage method. Another alternative is - * to abandon the final report request altogether and just use the onMessage method? I think the two - * differ though, as the final report is used to apply assertions, and the ongoing report is just for - * periodic timing results... In which case, maybe there needs to be a way for the onMessage method - * to process just some of the incoming messages, and forward the rest on to the conversion helper, as - * a sort of pre-conversation helper filter? Make conversation expose its onMessage method (it should - * already) and allow another delivery thread to filter the incoming messages to the conversation. - */ - public void check() - { - log.debug("public void check(): called"); - - try - { - // Wait for all the test senders to return their reports. - for (int i = 0; i < senders.size(); i++) - { - Message senderReport = senderConversation[i].receive(); - log.debug("Sender " + senderReport.getStringProperty("CLIENT_NAME") + " reports message count: " - + senderReport.getIntProperty("MESSAGE_COUNT")); - log.debug("Sender " + senderReport.getStringProperty("CLIENT_NAME") + " reports message time: " - + senderReport.getLongProperty("TEST_TIME")); - } - - log.debug("Got all sender test reports."); - - // Apply sender assertions to pass/fail the tests. - - // Inject a short pause to give the receivers time to finish receiving their test messages. - TestUtils.pause(500); - - // Ask the receivers for their reports. - Message statusRequest = controlSession.createMessage(); - statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); - - for (int i = 0; i < receivers.size(); i++) - { - receiverConversation[i].send(receiverControlTopic[i], statusRequest); - } - - log.debug("All receiver test reports requested."); - - // Wait for all receiver reports to come in, but do so asynchronously. - Runnable gatherAllReceiverReports = - new Runnable() - { - public void run() - { - try - { - // Wait for all the receivers to send their reports. - for (int i = 0; i < receivers.size(); i++) - { - Message receiverReport = receiverConversation[i].receive(); - - String clientName = receiverReport.getStringProperty("CLIENT_NAME"); - int messageCount = receiverReport.getIntProperty("MESSAGE_COUNT"); - long testTime = receiverReport.getLongProperty("TEST_TIME"); - - log.debug("Receiver " + clientName + " reports message count: " + messageCount); - log.debug("Receiver " + receiverReport.getStringProperty("CLIENT_NAME") - + " reports message time: " + testTime); - - // Apply receiver assertions to pass/fail the tests. - - // Log the test timings on the asynchronous test timing controller. - /*try - { - timingController.completeTest(true, messageCount, testTime); - } - // The timing controll can throw InterruptedException is the current test is to be - // interrupted. - catch (InterruptedException e) - { - e.printStackTrace(); - }*/ - } - - log.debug("All receiver test reports received."); - } - catch (JMSException e) - { - throw new RuntimeException(e); - } - } - }; - - Thread receiverReportsThread = new Thread(gatherAllReceiverReports); - receiverReportsThread.start(); - - // return new Message[] { senderReport, receiverReport }; - - } - catch (JMSException e) - { - throw new RuntimeException("Unhandled JMSException.", e); - } - } - - /** - * Closes the circuit. All associated resources are closed. - */ - public void close() - { - log.debug("public void close(): called"); - - // End the current test on all senders and receivers. - } - - /** - * Applies a list of assertions against the test circuit. The {@link #check()} method should be called before doing - * this, to ensure that the circuit has gathered its state into a report to assert against. - * - * @param assertions The list of assertions to apply. - * - * @return Any assertions that failed. - */ - public List applyAssertions(List assertions) - { - log.debug("public List applyAssertions(List assertions = " + assertions + "): called"); - - List failures = new LinkedList(); - - for (Assertion assertion : assertions) - { - if (!assertion.apply()) - { - failures.add(assertion); - } - } - - return failures; - } - - /** - * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. - * - * @param numMessages The number of messages to send using the default test procedure. - * @param assertions The list of assertions to apply. - * - * @return Any assertions that failed. - * - * @todo From check onwards needs to be handled as a future. The future must call back onto the test case to - * report results asynchronously. - */ - public List test(int numMessages, List assertions) - { - log.debug("public List test(int numMessages = " + numMessages + ", List assertions = " - + assertions + "): called"); - - // Keep the number of messages to send per test run, where the send method can reference it. - this.numMessages = numMessages; - - // Start the test running on all sender circuit ends. - start(); - - // Request status reports to be handed in. - check(); - - // Assert conditions on the publishing end of the circuit. - // Assert conditions on the receiving end of the circuit. - List failures = applyAssertions(assertions); - - // Close the circuit ending the current test case. - close(); - - // Pass with no failed assertions or fail with a list of failed assertions. - return failures; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java deleted file mode 100644 index 130e908b0e..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedcircuit; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Publisher; - -/** - * DistributedPublisherImpl represents the status of the publishing side of a test circuit. Its main purpose is to - * provide assertions that can be applied to verify the behaviour of a non-local publisher. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide assertion that the publishers received no exceptions. - *
Provide assertion that the publishers received a no consumers error code on every message. - *
Provide assertion that the publishers received a no route error code on every message. - *
- */ -public class DistributedPublisherImpl implements Publisher -{ - /** - * Provides an assertion that the publisher encountered no exceptions. - * - * @return An assertion that the publisher encountered no exceptions. - * @param testProps - */ - public Assertion noExceptionsAssertion(ParsedProperties testProps) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the publisher got a no consumers exception on every message. - * - * @return An assertion that the publisher got a no consumers exception on every message. - */ - public Assertion noConsumersAssertion() - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the publisher got a no rout exception on every message. - * - * @return An assertion that the publisher got a no rout exception on every message. - */ - public Assertion noRouteAssertion() - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the AMQP channel was forcibly closed by an error condition. - * - * @param testProps The test configuration properties. - * @return An assertion that the AMQP channel was forcibly closed by an error condition. - */ - public Assertion channelClosedAssertion(ParsedProperties testProps) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the publisher got a given exception during the test. - * - * @param testProps The test configuration properties. - * @param exceptionClass The exception class to check for. - * @return An assertion that the publisher got a given exception during the test. - */ - public Assertion exceptionAssertion(ParsedProperties testProps, Class exceptionClass) - { - throw new RuntimeException("Not implemented."); - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java deleted file mode 100644 index 4b801e7b66..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedcircuit; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Receiver; - -/** - * DistributedReceiverImpl represents the status of the receiving side of a test circuit. Its main purpose is to - * provide assertions that can be applied to verify the behaviour of a non-local receiver. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide assertion that the receivers received no exceptions. - *
Provide assertion that the receivers received all test messages sent to it. - *
- */ -public class DistributedReceiverImpl implements Receiver -{ - /** - * Provides an assertion that the receivers encountered no exceptions. - * - * @return An assertion that the receivers encountered no exceptions. - * @param testProps - */ - public Assertion noExceptionsAssertion(ParsedProperties testProps) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the receivers got all messages that were sent to it. - * - * @return An assertion that the receivers got all messages that were sent to it. - * @param testProps - */ - public Assertion allMessagesReceivedAssertion(ParsedProperties testProps) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the receivers got none of the messages that were sent to it. - * - * @return An assertion that the receivers got none of the messages that were sent to it. - * @param testProps - */ - public Assertion noMessagesReceivedAssertion(ParsedProperties testProps) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the AMQP channel was forcibly closed by an error condition. - * - * @param testProps The test configuration properties. - * @return An assertion that the AMQP channel was forcibly closed by an error condition. - */ - public Assertion channelClosedAssertion(ParsedProperties testProps) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Provides an assertion that the receiver got a given exception during the test. - * - * @param testProps - *@param exceptionClass The exception class to check for. @return An assertion that the receiver got a given exception during the test. - */ - public Assertion exceptionAssertion(ParsedProperties testProps, Class exceptionClass) - { - throw new RuntimeException("Not implemented."); - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java deleted file mode 100644 index 09bcf24da5..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedcircuit; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.junit.extensions.util.TestContextProperties; -import org.apache.qpid.test.framework.CircuitEnd; -import org.apache.qpid.test.framework.ExceptionMonitor; -import org.apache.qpid.test.framework.LocalCircuitFactory; -import org.apache.qpid.test.framework.MessageMonitor; -import org.apache.qpid.test.framework.MessagingTestConfigProperties; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * A TestClientCircuitEnd is a {@link CircuitEnd} that may be controlled from a - * {@link org.apache.qpid.test.framework.distributedtesting.TestClient}, and that forms a single publishing or - * receiving end point in a distributed test {@link org.apache.qpid.test.framework.Circuit}. - * - *

When operating in the SENDER role, this circuit end is capable of acting as part of the default circuit test - * procedure (described in the class comment for {@link org.apache.qpid.test.framework.Circuit}). That is, it will - * send the number of test messages required, using the test configuration parameters given in the test invite, and - * return a report on its activities to the circuit controller. - * - *

When operation in the RECEIVER role, this circuit end acts as part of the default circuit test procedure. It will - * receive test messages, on the setup specified in the test configuration parameters, and keep count of the messages - * received, and time taken to receive them. When requested by the circuit controller to provide a report, it will - * return this report of its activities. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a message producer for sending messages. - * {@link CircuitEnd}, {@link LocalCircuitFactory}, {@link TestUtils} - *
Provide a message consumer for receiving messages. - * {@link CircuitEnd}, {@link LocalCircuitFactory}, {@link TestUtils} - *
Supply the name of the test case that this implements. - *
Accept/Reject invites based on test parameters. {@link MessagingTestConfigProperties} - *
Adapt to assigned roles. {@link TestClientControlledTest.Roles} - *
Perform test case actions. {@link MessageMonitor} - *
Generate test reports. {@link MessageMonitor} - *
- */ -public class TestClientCircuitEnd implements CircuitEnd, TestClientControlledTest -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(TestClientCircuitEnd.class); - - /** Holds the test parameters. */ - ParsedProperties testProps; - - /** The number of test messages to send. */ - private int numMessages; - - /** The role to be played by the test. */ - private Roles role; - - /** The connection to send the test messages on. */ - private Connection connection; - - /** Holds the circuit end for this test. */ - CircuitEnd circuitEnd; - - /** - * Holds a message monitor for this circuit end, either the monitor on the consumer when in RECEIVER more, or - * a monitor updated on every message sent, when acting as a SENDER. - */ - MessageMonitor messageMonitor; - - /** - * Should provide the name of the test case that this class implements. The exact names are defined in the - * interop testing spec. - * - * @return The name of the test case that this implements. - */ - public String getName() - { - return "DEFAULT_CIRCUIT_TEST"; - } - - /** - * Determines whether the test invite that matched this test case is acceptable. - * - * @param inviteMessage The invitation to accept or reject. - * @return true to accept the invitation, false to reject it. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public boolean acceptInvite(Message inviteMessage) throws JMSException - { - log.debug("public boolean acceptInvite(Message inviteMessage): called"); - - // Populate the test parameters from the invitation. - testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); - - for (Object key : testProps.keySet()) - { - String propName = (String) key; - - // If the test parameters is overridden by the invitation, use it instead. - String inviteValue = inviteMessage.getStringProperty(propName); - - if (inviteValue != null) - { - testProps.setProperty(propName, inviteValue); - log.debug("Test invite supplied override to " + propName + " of " + inviteValue); - } - - } - - // Accept the invitation. - return true; - } - - /** - * Assigns the role to be played by this test case. The test parameters are fully specified in the - * assignment message. When this method return the test case will be ready to execute. - * - * @param role The role to be played; sender or receivers. - * @param assignRoleMessage The role assingment message, contains the full test parameters. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public void assignRole(Roles role, Message assignRoleMessage) throws JMSException - { - log.debug("public void assignRole(Roles role, Message assignRoleMessage): called"); - - // Take note of the role to be played. - this.role = role; - - // Extract and retain the test parameters. - numMessages = 1; // assignRoleMessage.getIntProperty("NUM_MESSAGES"); - - // Connect using the test parameters. - connection = TestUtils.createConnection(testProps); - - // Create a circuit end that matches the assigned role and test parameters. - LocalCircuitFactory circuitFactory = new LocalCircuitFactory(); - - switch (role) - { - // Check if the sender role is being assigned, and set up a message producer if so. - case SENDER: - - // Set up the publisher. - circuitEnd = circuitFactory.createPublisherCircuitEnd(connection, testProps, 0L); - - // Create a custom message monitor that will be updated on every message sent. - messageMonitor = new MessageMonitor(); - - break; - - // Otherwise the receivers role is being assigned, so set this up to listen for messages. - case RECEIVER: - - // Set up the receiver. - circuitEnd = circuitFactory.createReceiverCircuitEnd(connection, testProps, 0L); - - // Use the message monitor from the consumer for stats. - messageMonitor = getMessageMonitor(); - - break; - } - - // Reset all messaging stats for the report. - messageMonitor.reset(); - - connection.start(); - } - - /** - * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. - * - * @param numMessages The number of test messages to send. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - * - * @todo Add round robin on destinations where multiple destinations being used. - * - * @todo Add rate limiting when rate limit specified on publishers. - * - * @todo Add Max pending message size protection. The receiver will have to send back some acks once in a while, - * to notify the publisher that its messages are being consumed. This makes the safety valve harder to - * implement than in the single VM case. For example, if the limit is 1000 messages, might want to get back - * an ack every 500, to notify the publisher that it can keep sending. What about pub/sub tests? Will it be - * necessary to wait for an ack from every receiver? This will have the effect of rate limiting to slow - * consumers too. - * - * @todo Add commits on every commit batch size boundary. - */ - public void start(int numMessages) throws JMSException - { - log.debug("public void start(): called"); - - // If in the SENDER role, send the specified number of test messages to the circuit destinations. - if (role.equals(Roles.SENDER)) - { - Message testMessage = getSession().createMessage(); - - for (int i = 0; i < numMessages; i++) - { - getProducer().send(testMessage); - - // Increment the message count and timings. - messageMonitor.onMessage(testMessage); - } - } - } - - /** - * Gets a report on the actions performed by the test case in its assigned role. - * - * @param session The controlSession to create the report message in. - * @return The report message. - * - * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through. - */ - public Message getReport(Session session) throws JMSException - { - Message report = session.createMessage(); - report.setStringProperty("CONTROL_TYPE", "REPORT"); - - // Add the count of messages sent/received to the report. - report.setIntProperty("MESSAGE_COUNT", messageMonitor.getNumMessage()); - - // Add the time to send/receive messages to the report. - report.setLongProperty("TEST_TIME", messageMonitor.getTime()); - - // Add any exceptions detected to the report. - - return report; - } - - /** - * Gets the message producer at this circuit end point. - * - * @return The message producer at with this circuit end point. - */ - public MessageProducer getProducer() - { - return circuitEnd.getProducer(); - } - - /** - * Gets the message consumer at this circuit end point. - * - * @return The message consumer at this circuit end point. - */ - public MessageConsumer getConsumer() - { - return circuitEnd.getConsumer(); - } - - /** - * Send the specified message over the producer at this end point. - * - * @param message The message to send. - * - * @throws JMSException Any JMS exception occuring during the send is allowed to fall through. - */ - public void send(Message message) throws JMSException - { - // Send the message on the circuit ends producer. - circuitEnd.send(message); - } - - /** - * Gets the JMS Session associated with this circuit end point. - * - * @return The JMS Session associated with this circuit end point. - */ - public Session getSession() - { - return circuitEnd.getSession(); - } - - /** - * Closes the message producers and consumers and the sessions, associated with this circuit end point. - * - * @throws JMSException Any JMSExceptions occurring during the close are allowed to fall through. - */ - public void close() throws JMSException - { - // Close the producer and consumer. - circuitEnd.close(); - } - - /** - * Returns the message monitor for reporting on received messages on this circuit end. - * - * @return The message monitor for this circuit end. - */ - public MessageMonitor getMessageMonitor() - { - return circuitEnd.getMessageMonitor(); - } - - /** - * Returns the exception monitor for reporting on exceptions received on this circuit end. - * - * @return The exception monitor for this circuit end. - */ - public ExceptionMonitor getExceptionMonitor() - { - return circuitEnd.getExceptionMonitor(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java deleted file mode 100644 index e07b141cb5..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java +++ /dev/null @@ -1,546 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import junit.framework.Test; -import junit.framework.TestResult; -import junit.framework.TestSuite; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import org.apache.qpid.junit.extensions.TKTestRunner; -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; -import org.apache.qpid.junit.extensions.util.CommandLineParser; -import org.apache.qpid.junit.extensions.util.MathUtils; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.junit.extensions.util.TestContextProperties; -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.MessagingTestConfigProperties; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.framework.clocksynch.UDPClockReference; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; - -/** - *

Implements the coordinator client described in the interop testing specification - * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). This coordinator is built on - * top of the JUnit testing framework. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Find out what test clients are available. {@link ConversationFactory} - *
Decorate available tests to run on all available clients. {@link DistributedTestDecorator} - *
Attach XML test result logger. - *
Terminate the interop testing framework. - *
- * - * @todo Should accumulate failures over all tests, and return with success or fail code based on all results. May need - * to write a special TestResult to do this properly. At the moment only the last one used will be tested for - * errors, as the start method creates a fresh one for each test case run. - */ -public class Coordinator extends TKTestRunner -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(Coordinator.class); - - /** Used for reporting to the console. */ - private static final Logger console = Logger.getLogger("CONSOLE"); - - /** Defines the possible distributed test engines available to run coordinated test cases with. */ - public enum TestEngine - { - /** Specifies the interop test engine. This tests all available clients in pairs. */ - INTEROP, - - /** Specifies the fanout test engine. This sets up one publisher role, and many reciever roles. */ - FANOUT - } - - /** - * Holds the test context properties that provides the default test parameters, plus command line overrides. - * This is initialized with the default test parameters, to which command line overrides may be applied. - */ - protected static ParsedProperties testContextProperties = - TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); - - /** Holds the URL of the broker to coordinate the tests on. */ - protected String brokerUrl; - - /** Holds the virtual host to coordinate the tests on. If null, then the default virtual host is used. */ - protected String virtualHost; - - /** Holds the list of all clients that enlisted, when the compulsory invite was issued. */ - protected Set enlistedClients = new HashSet(); - - /** Holds the conversation helper for the control conversation. */ - protected ConversationFactory conversationFactory; - - /** Holds the connection that the coordinating messages are sent over. */ - protected Connection connection; - - /** Holds the path of the directory to output test results too, if one is defined. */ - protected String reportDir; - - /** Holds the coordinating test engine type to run the tests through. */ - protected TestEngine engine; - - /** Flag that indicates that all test clients should be terminated upon completion of the test cases. */ - protected boolean terminate; - - /** - * Creates an interop test coordinator on the specified broker and virtual host. - * - * @param repetitions The number of times to repeat the test, or test batch size. - * @param duration The length of time to run the tests for. -1 means no duration has been set. - * @param threads The concurrency levels to ramp up to. - * @param delay A delay in milliseconds between test runs. - * @param params The sets of 'size' parameters to pass to test. - * @param testCaseName The name of the test case to run. - * @param reportDir The directory to output the test results to. - * @param runName The name of the test run; used to name the output file. - * @param verbose Whether to print comments during test run. - * @param brokerUrl The URL of the broker to connect to. - * @param virtualHost The virtual host to run all tests on. Optional, may be null. - * @param engine The distributed test engine type to run the tests with. - * @param terminate true if test client nodes should be terminated at the end of the tests. - * @param csv true if the CSV results listener should be attached. - * @param xml true if the XML results listener should be attached. - * @param decoratorFactories List of factories for user specified decorators. - */ - public Coordinator(Integer repetitions, Long duration, int[] threads, int delay, int[] params, String testCaseName, - String reportDir, String runName, boolean verbose, String brokerUrl, String virtualHost, TestEngine engine, - boolean terminate, boolean csv, boolean xml, List decoratorFactories) - { - super(repetitions, duration, threads, delay, params, testCaseName, reportDir, runName, csv, xml, decoratorFactories); - - log.debug("public Coordinator(Integer repetitions = " + repetitions + " , Long duration = " + duration - + ", int[] threads = " + Arrays.toString(threads) + ", int delay = " + delay + ", int[] params = " - + Arrays.toString(params) + ", String testCaseName = " + testCaseName + ", String reportDir = " + reportDir - + ", String runName = " + runName + ", boolean verbose = " + verbose + ", String brokerUrl = " + brokerUrl - + ", String virtualHost =" + virtualHost + ", TestEngine engine = " + engine + ", boolean terminate = " - + terminate + ", boolean csv = " + csv + ", boolean xml = " + xml + "): called"); - - // Retain the connection parameters. - this.brokerUrl = brokerUrl; - this.virtualHost = virtualHost; - this.reportDir = reportDir; - this.engine = engine; - this.terminate = terminate; - } - - /** - * The entry point for the interop test coordinator. This client accepts the following command line arguments: - * - *

- *
-b The broker URL. Mandatory. - *
-h The virtual host. Optional. - *
-o The directory to output test results to. Optional. - *
-e The type of test distribution engine to use. Optional. One of: interop, fanout. - *
... Free arguments. The distributed test cases to run. - * Mandatory. At least one must be defined. - *
name=value Trailing argument define name/value pairs. Added to the test contenxt properties. - * Optional. - *
- * - * @param args The command line arguments. - */ - public static void main(String[] args) - { - NDC.push("coordinator"); - log.debug("public static void main(String[] args = " + Arrays.toString(args) + "): called"); - console.info("Qpid Distributed Test Coordinator."); - - // Override the default broker url to be localhost:5672. - testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672"); - - try - { - // Use the command line parser to evaluate the command line with standard handling behaviour (print errors - // and usage then exist if there are errors). - // Any options and trailing name=value pairs are also injected into the test context properties object, - // to override any defaults that may have been set up. - ParsedProperties options = - new ParsedProperties(CommandLineParser.processCommandLine(args, - new CommandLineParser( - new String[][] - { - { "b", "The broker URL.", "broker", "false" }, - { "h", "The virtual host to use.", "virtual host", "false" }, - { "o", "The name of the directory to output test timings to.", "dir", "false" }, - { - "e", "The test execution engine to use. Default is interop.", "engine", "interop", - "^interop$|^fanout$", "true" - }, - { "t", "Terminate test clients on completion of tests.", null, "false" }, - { "-csv", "Output test results in CSV format.", null, "false" }, - { "-xml", "Output test results in XML format.", null, "false" }, - { - "-trefaddr", "To specify an alternative to hostname for time singal reference.", - "address", "false" - }, - { - "c", "The number of tests to run concurrently.", "num", "false", - MathUtils.SEQUENCE_REGEXP - }, - { "r", "The number of times to repeat each test.", "num", "false" }, - { - "d", "The length of time to run the tests for.", "duration", "false", - MathUtils.DURATION_REGEXP - }, - { - "f", "The maximum rate to call the tests at.", "frequency", "false", - "^([1-9][0-9]*)/([1-9][0-9]*)$" - }, - { "s", "The size parameter to run tests with.", "size", "false", MathUtils.SEQUENCE_REGEXP }, - { "v", "Verbose mode.", null, "false" }, - { "n", "A name for this test run, used to name the output file.", "name", "true" }, - { - "X:decorators", "A list of additional test decorators to wrap the tests in.", - "\"class.name[:class.name]*\"", "false" - } - }), testContextProperties)); - - // Extract the command line options. - String brokerUrl = options.getProperty("b"); - String virtualHost = options.getProperty("h"); - String reportDir = options.getProperty("o"); - reportDir = (reportDir == null) ? "." : reportDir; - String testEngine = options.getProperty("e"); - TestEngine engine = "fanout".equals(testEngine) ? TestEngine.FANOUT : TestEngine.INTEROP; - boolean terminate = options.getPropertyAsBoolean("t"); - boolean csvResults = options.getPropertyAsBoolean("-csv"); - boolean xmlResults = options.getPropertyAsBoolean("-xml"); - String threadsString = options.getProperty("c"); - Integer repetitions = options.getPropertyAsInteger("r"); - String durationString = options.getProperty("d"); - String paramsString = options.getProperty("s"); - boolean verbose = options.getPropertyAsBoolean("v"); - String testRunName = options.getProperty("n"); - String decorators = options.getProperty("X:decorators"); - - int[] threads = (threadsString == null) ? null : MathUtils.parseSequence(threadsString); - int[] params = (paramsString == null) ? null : MathUtils.parseSequence(paramsString); - Long duration = (durationString == null) ? null : MathUtils.parseDuration(durationString); - - // If broker or virtual host settings were specified as command line options, override the defaults in the - // test context properties with them. - - // Collection all of the test cases to be run. - Collection> testCaseClasses = - new ArrayList>(); - - // Create a list of test decorator factories for use specified decorators to be applied. - List decoratorFactories = parseDecorators(decorators); - - // Scan for available test cases using a classpath scanner. - // ClasspathScanner.getMatches(DistributedTestCase.class, "^Test.*", true); - - // Hard code the test classes till the classpath scanner is fixed. - // Collections.addAll(testCaseClasses, InteropTestCase1DummyRun.class, InteropTestCase2BasicP2P.class, - // InteropTestCase3BasicPubSub.class); - - // Parse all of the free arguments as test cases to run. - for (int i = 1; true; i++) - { - String nextFreeArg = options.getProperty(Integer.toString(i)); - - // Terminate the loop once all free arguments have been consumed. - if (nextFreeArg == null) - { - break; - } - - try - { - Class nextClass = Class.forName(nextFreeArg); - - if (FrameworkBaseCase.class.isAssignableFrom(nextClass)) - { - testCaseClasses.add(nextClass); - console.info("Found distributed test case: " + nextFreeArg); - } - } - catch (ClassNotFoundException e) - { - console.info("Unable to instantiate the test case: " + nextFreeArg + "."); - } - } - - // Check that some test classes were actually found. - if (testCaseClasses.isEmpty()) - { - throw new RuntimeException( - "No test cases implementing FrameworkBaseCase were specified on the command line."); - } - - // Extract the names of all the test classes, to pass to the start method. - int i = 0; - String[] testClassNames = new String[testCaseClasses.size()]; - - for (Class testClass : testCaseClasses) - { - testClassNames[i++] = testClass.getName(); - } - - // Create a coordinator and begin its test procedure. - Coordinator coordinator = - new Coordinator(repetitions, duration, threads, 0, params, null, reportDir, testRunName, verbose, brokerUrl, - virtualHost, engine, terminate, csvResults, xmlResults, decoratorFactories); - - TestResult testResult = coordinator.start(testClassNames); - - // Return different error codes, depending on whether or not there were test failures. - if (testResult.failureCount() > 0) - { - System.exit(FAILURE_EXIT); - } - else - { - System.exit(SUCCESS_EXIT); - } - } - catch (Exception e) - { - log.debug("Top level handler caught execption.", e); - console.info(e.getMessage()); - e.printStackTrace(); - System.exit(EXCEPTION_EXIT); - } - } - - /** - * Starts all of the test classes to be run by this coordinator. - * - * @param testClassNames An array of all the coordinating test case implementations. - * - * @return A JUnit TestResult to run the tests with. - * - * @throws Exception Any underlying exceptions are allowed to fall through, and fail the test process. - */ - public TestResult start(String[] testClassNames) throws Exception - { - log.debug("public TestResult start(String[] testClassNames = " + Arrays.toString(testClassNames) + ": called"); - - // Connect to the broker. - connection = TestUtils.createConnection(TestContextProperties.getInstance()); - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - Destination controlTopic = session.createTopic("iop.control"); - Destination responseQueue = session.createQueue("coordinator"); - - conversationFactory = new ConversationFactory(connection, responseQueue, LinkedBlockingQueue.class); - ConversationFactory.Conversation conversation = conversationFactory.startConversation(); - - connection.start(); - - // Broadcast the compulsory invitation to find out what clients are available to test. - Message invite = session.createMessage(); - invite.setStringProperty("CONTROL_TYPE", "INVITE"); - invite.setJMSReplyTo(responseQueue); - - conversation.send(controlTopic, invite); - - // Wait for a short time, to give test clients an opportunity to reply to the invitation. - Collection enlists = conversation.receiveAll(0, 500); - enlistedClients = extractEnlists(enlists); - - for (TestClientDetails client : enlistedClients) - { - log.debug("Got enlisted test client: " + client); - console.info("Test node " + client.clientName + " available."); - } - - // Start the clock reference service running. - UDPClockReference clockReference = new UDPClockReference(); - Thread clockRefThread = new Thread(clockReference); - registerShutdownHook(clockReference); - clockRefThread.start(); - - // Broadcast to all clients to synchronize their clocks against the coordinators clock reference. - Message clockSynchRequest = session.createMessage(); - clockSynchRequest.setStringProperty("CONTROL_TYPE", "CLOCK_SYNCH"); - - String localAddress = InetAddress.getByName(InetAddress.getLocalHost().getHostName()).getHostAddress(); - clockSynchRequest.setStringProperty("ADDRESS", localAddress); - - conversation.send(controlTopic, clockSynchRequest); - - // Run the test in the suite using JUnit. - TestResult result = null; - - for (String testClassName : testClassNames) - { - // Record the current test class, so that the test results can be output to a file incorporating this name. - this.currentTestClassName = testClassName; - - result = super.start(new String[] { testClassName }); - } - - // At this point in time, all tests have completed. Broadcast the shutdown message, if the termination option - // was set on the command line. - if (terminate) - { - Message terminate = session.createMessage(); - terminate.setStringProperty("CONTROL_TYPE", "TERMINATE"); - - conversation.send(controlTopic, terminate); - } - - return result; - } - - /** - * For a collection of enlist messages, this method pulls out of the client details for the enlisting clients. - * - * @param enlists The enlist messages. - * - * @return A set of enlisting clients, extracted from the enlist messages. - * - * @throws JMSException Any underlying JMSException is allowed to fall through. - */ - public static Set extractEnlists(Collection enlists) throws JMSException - { - log.debug("public static Set extractEnlists(Collection enlists = " + enlists - + "): called"); - - Set enlistedClients = new HashSet(); - - // Retain the list of all available clients. - for (Message enlist : enlists) - { - TestClientDetails clientDetails = new TestClientDetails(); - clientDetails.clientName = enlist.getStringProperty("CLIENT_NAME"); - clientDetails.privateControlKey = enlist.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY"); - - String replyType = enlist.getStringProperty("CONTROL_TYPE"); - - if ("ENLIST".equals(replyType)) - { - enlistedClients.add(clientDetails); - } - else if ("DECLINE".equals(replyType)) - { - log.debug("Test client " + clientDetails.clientName + " declined the invite."); - } - else - { - log.warn("Got an unknown reply type, " + replyType + ", to the invite."); - } - } - - return enlistedClients; - } - - /** - * Runs a test or suite of tests, using the super class implemenation. This method wraps the test to be run - * in any test decorators needed to add in the coordinators ability to invite test clients to participate in - * tests. - * - * @param test The test to run. - * @param wait Undocumented. Nothing in the JUnit javadocs to say what this is for. - * - * @return The results of the test run. - */ - public TestResult doRun(Test test, boolean wait) - { - log.debug("public TestResult doRun(Test \"" + test + "\", boolean " + wait + "): called"); - - // Wrap all tests in the test suite with WrappedSuiteTestDecorators. This is quite ugly and a bit baffling, - // but the reason it is done is because the JUnit implementation of TestDecorator has some bugs in it. - WrappedSuiteTestDecorator targetTest = null; - - if (test instanceof TestSuite) - { - log.debug("targetTest is a TestSuite"); - - TestSuite suite = (TestSuite)test; - - int numTests = suite.countTestCases(); - log.debug("There are " + numTests + " in the suite."); - - for (int i = 0; i < numTests; i++) - { - Test nextTest = suite.testAt(i); - log.debug("suite.testAt(" + i + ") = " + nextTest); - - if (nextTest instanceof FrameworkBaseCase) - { - log.debug("nextTest is a FrameworkBaseCase"); - } - } - - targetTest = new WrappedSuiteTestDecorator(suite); - log.debug("Wrapped with a WrappedSuiteTestDecorator."); - } - - // Apply any optional user specified decorators. - targetTest = applyOptionalUserDecorators(targetTest); - - // Wrap the tests in a suitable distributed test decorator, to perform the invite/test cycle. - targetTest = newTestDecorator(targetTest, enlistedClients, conversationFactory, connection); - - // TestSuite suite = new TestSuite(); - // suite.addTest(targetTest); - - // Wrap the tests in a scaled test decorator to them them as a 'batch' in one thread. - // targetTest = new ScaledTestDecorator(targetTest, new int[] { 1 }); - - return super.doRun(targetTest, wait); - } - - /** - * Creates a wrapped test decorator, that is capable of inviting enlisted clients to participate in a specified - * test. This is the test engine that sets up the roles and sequences a distributed test case. - * - * @param targetTest The test decorator to wrap. - * @param enlistedClients The enlisted clients available to run the test. - * @param conversationFactory The conversation factory used to build conversation helper over the specified connection. - * @param connection The connection to talk to the enlisted clients over. - * - * @return An invititing test decorator, that invites all the enlisted clients to participate in tests, in pairs. - */ - protected DistributedTestDecorator newTestDecorator(WrappedSuiteTestDecorator targetTest, - Set enlistedClients, ConversationFactory conversationFactory, Connection connection) - { - switch (engine) - { - case FANOUT: - return new FanOutTestDecorator(targetTest, enlistedClients, conversationFactory, connection); - case INTEROP: - default: - return new InteropTestDecorator(targetTest, enlistedClients, conversationFactory, connection); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java deleted file mode 100644 index 49a01d3127..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import junit.framework.TestResult; -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import java.util.Collection; -import java.util.Set; - -/** - * DistributedTestDecorator is a base class for writing test decorators that invite test clients to participate in - * distributed test cases. It provides a helper method, {@link #signupClients}, that broadcasts an invitation and - * returns the set of test clients that are available to particiapte in the test. - * - *

When used to wrap a {@link FrameworkBaseCase} test, it replaces the default {@link CircuitFactory} implementations - * with a suitable circuit factory for distributed tests. Concrete implementations can use this to configure the sending - * and receiving roles on the test. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Broadcast test invitations and collect enlists. {@link ConversationFactory}. - *
- */ -public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(DistributedTestDecorator.class); - - /** Holds the contact information for all test clients that are available and that may take part in the test. */ - Set allClients; - - /** Holds the conversation helper for the control level conversation for coordinating the test through. */ - ConversationFactory conversationFactory; - - /** Holds the connection that the control conversation is held over. */ - Connection connection; - - /** Holds the underlying test suite that this decorator wraps. */ - WrappedSuiteTestDecorator testSuite; - - /** Holds the control topic, on which test invitations are broadcast. */ - protected Destination controlTopic; - - /** - * Creates a wrapped suite test decorator from another one. - * - * @param suite The test suite. - * @param availableClients The list of all clients that responded to the compulsory invite. - * @param controlConversation The conversation helper for the control level, test coordination conversation. - * @param controlConnection The connection that the coordination messages are sent over. - */ - public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set availableClients, - ConversationFactory controlConversation, Connection controlConnection) - { - super(suite); - - log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set allClients = " - + availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called"); - - testSuite = suite; - allClients = availableClients; - conversationFactory = controlConversation; - connection = controlConnection; - - // Set up the test control topic. - try - { - controlTopic = conversationFactory.getSession().createTopic("iop.control"); - } - catch (JMSException e) - { - throw new RuntimeException("Unable to create the coordinating control topic to broadcast test invites on.", e); - } - } - - /** - * Should run all of the tests in the wrapped test suite. - * - * @param testResult The the results object to monitor the test results with. - */ - public abstract void run(TestResult testResult); - - /** - * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase} - * tests. - * - * @return A distributed test sequencer. - */ - public abstract CircuitFactory getTestSequencer(); - - /** - * Broadcasts an invitation to participate in a coordinating test case to find out what clients are available to - * run the test case. - * - * @param coordTest The coordinating test case to broadcast an inviate for. - * - * @return A set of test clients that accepted the invitation. - */ - protected Set signupClients(FrameworkBaseCase coordTest) - { - // Broadcast the invitation to find out what clients are available to test. - Set enlists; - try - { - Message invite = conversationFactory.getSession().createMessage(); - - ConversationFactory.Conversation conversation = conversationFactory.startConversation(); - - invite.setStringProperty("CONTROL_TYPE", "INVITE"); - invite.setStringProperty("TEST_NAME", coordTest.getTestCaseNameForTestMethod(coordTest.getName())); - - conversation.send(controlTopic, invite); - - // Wait for a short time, to give test clients an opportunity to reply to the invitation. - Collection replies = conversation.receiveAll(allClients.size(), 500); - enlists = Coordinator.extractEnlists(replies); - } - catch (JMSException e) - { - throw new RuntimeException("There was a JMSException during the invite/enlist conversation.", e); - } - - return enlists; - } - - /** - * Prints a string summarizing this test decorator, mainly for debugging purposes. - * - * @return String representation for debugging purposes. - */ - public String toString() - { - return "DistributedTestDecorator: [ testSuite = " + testSuite + " ]"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java deleted file mode 100644 index 809bb1dd2f..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import junit.framework.Test; -import junit.framework.TestResult; -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; -import org.apache.qpid.test.framework.DropInTest; -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; -import org.apache.qpid.test.framework.sequencers.FanOutCircuitFactory; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import java.util.Iterator; -import java.util.Set; - -/** - * FanOutTestDecorator is an {@link DistributedTestDecorator} that runs one test client in the sender role, and the remainder - * in the receivers role. It also has the capability to listen for new test cases joining the test beyond the initial start - * point. This feature can be usefull when experimenting with adding more load, in the form of more test clients, to assess - * its impact on a running test. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Execute coordinated test cases. {@link FrameworkBaseCase} - *
Accept test clients joining a running test. - *
- */ -public class FanOutTestDecorator extends DistributedTestDecorator implements MessageListener -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(FanOutTestDecorator.class); - - /** Holds the currently running test case. */ - private FrameworkBaseCase currentTest = null; - - /** - * Creates a wrapped suite test decorator from another one. - * - * @param suite The test suite. - * @param availableClients The list of all clients that responded to the compulsory invite. - * @param controlConversation The conversation helper for the control level, test coordination conversation. - * @param controlConnection The connection that the coordination messages are sent over. - */ - public FanOutTestDecorator(WrappedSuiteTestDecorator suite, Set availableClients, - ConversationFactory controlConversation, Connection controlConnection) - { - super(suite, availableClients, controlConversation, controlConnection); - - log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set allClients = " - + availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called"); - - testSuite = suite; - allClients = availableClients; - conversationFactory = controlConversation; - connection = controlConnection; - - // Sign available clients up to the test. - for (Test test : getAllUnderlyingTests()) - { - FrameworkBaseCase coordTest = (FrameworkBaseCase) test; - - // Get all of the clients able to participate in the test. - Set enlists = signupClients(coordTest); - - // Check that there were some clients available. - if (enlists.size() == 0) - { - throw new RuntimeException("No clients to test with"); - } - - // Create a distributed test circuit factory for the test. - CircuitFactory circuitFactory = getTestSequencer(); - - // Set up the first client in the sender role, and the remainder in the receivers role. - Iterator clients = enlists.iterator(); - circuitFactory.setSender(clients.next()); - - while (clients.hasNext()) - { - // Set the sending and receiving client details on the test case. - circuitFactory.setReceiver(clients.next()); - } - - // Pass down the connection to hold the coordinating conversation over. - circuitFactory.setConversationFactory(conversationFactory); - - // If the current test case is a drop-in test, set it up as the currently running test for late joiners to - // add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed. - currentTest = (coordTest instanceof DropInTest) ? coordTest : null; - - // Execute the test case. - coordTest.setCircuitFactory(circuitFactory); - } - } - - /** - * Broadcasts a test invitation and accepts enlists from participating clients. The wrapped test cases are run - * with one test client in the sender role, and the remaining test clients in the receiving role. - * - *

Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime - * exceptions, resulting in the non-completion of the test run. - * - * @param testResult The the results object to monitor the test results with. - * - * @todo Better error recovery for failure of the invite/enlist conversation could be added. - */ - public void run(TestResult testResult) - { - log.debug("public void run(TestResult testResult): called"); - - // Listen for late joiners on the control topic. - try - { - conversationFactory.getSession().createConsumer(controlTopic).setMessageListener(this); - } - catch (JMSException e) - { - throw new RuntimeException("Unable to set up the message listener on the control topic.", e); - } - - // Run all of the test cases in the test suite. - /*for (Test test : getAllUnderlyingTests()) - { - FrameworkBaseCase coordTest = (FrameworkBaseCase) test; - - // Get all of the clients able to participate in the test. - Set enlists = signupClients(coordTest); - - // Check that there were some clients available. - if (enlists.size() == 0) - { - throw new RuntimeException("No clients to test with"); - } - - // Create a distributed test circuit factory for the test. - CircuitFactory circuitFactory = getTestSequencer(); - - // Set up the first client in the sender role, and the remainder in the receivers role. - Iterator clients = enlists.iterator(); - circuitFactory.setSender(clients.next()); - - while (clients.hasNext()) - { - // Set the sending and receiving client details on the test case. - circuitFactory.setReceiver(clients.next()); - } - - // Pass down the connection to hold the coordinating conversation over. - circuitFactory.setConversationFactory(conversationFactory); - - // If the current test case is a drop-in test, set it up as the currently running test for late joiners to - // add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed. - currentTest = (coordTest instanceof DropInTest) ? coordTest : null; - - // Execute the test case. - coordTest.setCircuitFactory(circuitFactory); - }*/ - - // Run all of the test cases in the test suite. - for (Test test : getAllUnderlyingTests()) - { - FrameworkBaseCase coordTest = (FrameworkBaseCase) test; - - coordTest.run(testResult); - - currentTest = null; - } - } - - /** - * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase} - * tests. - * - * @return A distributed test sequencer. - */ - public CircuitFactory getTestSequencer() - { - return new FanOutCircuitFactory(); - } - - /** - * Listens to incoming messages on the control topic. If the messages are 'join' messages, signalling a new - * test client wishing to join the current test, then the new client will be added to the current test in the - * receivers role. - * - * @param message The incoming control message. - */ - public void onMessage(Message message) - { - try - { - // Check if the message is from a test client attempting to join a running test, and join it to the current - // test case if so. - if (message.getStringProperty("CONTROL_TYPE").equals("JOIN") && (currentTest != null)) - { - ((DropInTest) currentTest).lateJoin(message); - } - } - // There is not a lot can be done with this error, so it is deliberately ignored. - catch (JMSException e) - { - log.debug("Unable to process message:" + message); - } - } - - /** - * Prints a string summarizing this test decorator, mainly for debugging purposes. - * - * @return String representation for debugging purposes. - */ - public String toString() - { - return "FanOutTestDecorator: [ testSuite = " + testSuite + " ]"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java deleted file mode 100644 index dd5007090b..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import junit.framework.Test; -import junit.framework.TestResult; -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; -import org.apache.qpid.test.framework.sequencers.InteropCircuitFactory; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * DistributedTestDecorator is a test decorator, written to implement the interop test specification. Given a list - * of enlisted test clients, that are available to run interop tests, this decorator invites them to participate - * in each test in the wrapped test suite. Amongst all the clients that respond to the invite, all pairs are formed, - * and each pairing (in both directions, but excluding the reflexive pairings) is split into a sender and receivers - * role and a test case run between them. Any enlisted combinations that do not accept a test invite are automatically - * failed. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Broadcast test invitations and collect enlists. {@link org.apache.qpid.test.utils.ConversationFactory}. - *
Output test failures for clients unwilling to run the test case. {@link Coordinator} - *
Execute distributed test cases. {@link FrameworkBaseCase} - *
Fail non-participating pairings. {@link OptOutTestCase} - *
- */ -public class InteropTestDecorator extends DistributedTestDecorator -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(InteropTestDecorator.class); - - /** - * Creates a wrapped suite test decorator from another one. - * - * @param suite The test suite. - * @param availableClients The list of all clients that responded to the compulsory invite. - * @param controlConversation The conversation helper for the control level, test coordination conversation. - * @param controlConnection The connection that the coordination messages are sent over. - */ - public InteropTestDecorator(WrappedSuiteTestDecorator suite, Set availableClients, - ConversationFactory controlConversation, Connection controlConnection) - { - super(suite, availableClients, controlConversation, controlConnection); - } - - /** - * Broadcasts a test invitation and accetps enlisting from participating clients. The wrapped test case is - * then repeated for every combination of test clients (provided the wrapped test case extends - * {@link FrameworkBaseCase}. - * - *

Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime exceptions, - * resulting in the non-completion of the test run. - * - * @todo Better error recovery for failure of the invite/enlist conversation could be added. - * - * @param testResult The the results object to monitor the test results with. - */ - public void run(TestResult testResult) - { - log.debug("public void run(TestResult testResult): called"); - - Collection tests = testSuite.getAllUnderlyingTests(); - - for (Test test : getAllUnderlyingTests()) - { - FrameworkBaseCase coordTest = (FrameworkBaseCase) test; - - // Broadcast the invitation to find out what clients are available to test. - Set enlists = signupClients(coordTest); - - // Compare the list of willing clients to the list of all available. - Set optOuts = new HashSet(allClients); - optOuts.removeAll(enlists); - - // Output test failures for clients that will not particpate in the test. - Set> failPairs = allPairs(optOuts, allClients); - - for (List failPair : failPairs) - { - // Create a distributed test circuit factory for the test. - CircuitFactory circuitFactory = getTestSequencer(); - - // Create an automatic failure test for the opted out test pair. - FrameworkBaseCase failTest = new OptOutTestCase("testOptOut"); - circuitFactory.setSender(failPair.get(0)); - circuitFactory.setReceiver(failPair.get(1)); - failTest.setCircuitFactory(circuitFactory); - - failTest.run(testResult); - } - - // Loop over all combinations of clients, willing to run the test. - Set> enlistedPairs = allPairs(enlists, enlists); - - for (List enlistedPair : enlistedPairs) - { - // Create a distributed test circuit factory for the test. - CircuitFactory circuitFactory = getTestSequencer(); - - // Set the sending and receiving client details on the test circuitFactory. - circuitFactory.setSender(enlistedPair.get(0)); - circuitFactory.setReceiver(enlistedPair.get(1)); - - // Pass down the connection to hold the coordination conversation over. - circuitFactory.setConversationFactory(conversationFactory); - - // Execute the test case. - coordTest.setCircuitFactory(circuitFactory); - coordTest.run(testResult); - } - } - } - - /** - * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase} - * tests. - * - * @return A distributed test sequencer. - */ - public CircuitFactory getTestSequencer() - { - return new InteropCircuitFactory(); - } - - /** - * Produces all pairs of combinations of elements from two sets. The ordering of the elements in the pair is - * important, that is the pair is distinct from ; both pairs are generated. For any element, i, in - * both the left and right sets, the reflexive pair is not generated. - * - * @param left The left set. - * @param right The right set. - * @param The type of the content of the pairs. - * - * @return All pairs formed from the permutations of all elements of the left and right sets. - */ - private Set> allPairs(Set left, Set right) - { - log.debug("private Set> allPairs(Set left = " + left + ", Set right = " + right + "): called"); - - Set> results = new HashSet>(); - - // Form all pairs from left to right. - // Form all pairs from right to left. - for (E le : left) - { - for (E re : right) - { - if (!le.equals(re)) - { - results.add(new Pair(le, re)); - results.add(new Pair(re, le)); - } - } - } - - log.debug("results = " + results); - - return results; - } - - /** - * A simple implementation of a pair, using a list. - */ - private class Pair extends ArrayList - { - /** - * Creates a new pair of elements. - * - * @param first The first element. - * @param second The second element. - */ - public Pair(T first, T second) - { - super(); - super.add(first); - super.add(second); - } - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java deleted file mode 100644 index 229c6a34da..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; - -/** - * An OptOutTestCase is a test case that automatically fails. It is used when a list of test clients has been generated - * from a compulsory invite, but only some of those clients have responded to a specific test case invite. The clients - * that did not respond, may automatically be given a fail for some tests. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Fail the test with a suitable reason. - *
- */ -public class OptOutTestCase extends FrameworkBaseCase -{ - /** - * Creates a new coordinating test case with the specified name. - * - * @param name The test case name. - */ - public OptOutTestCase(String name) - { - super(name); - } - - /** Generates an appropriate test failure assertion. */ - public void testOptOut() - { - CircuitFactory circuitFactory = getCircuitFactory(); - - fail("One of " + circuitFactory.getSender() + " and " + getCircuitFactory().getReceivers() - + " opted out of the test."); - } - - /** - * Should provide a translation from the junit method name of a test to its test case name as defined in the - * interop testing specification. For example the method "testP2P" might map onto the interop test case name - * "TC2_BasicP2P". - * - * @param methodName The name of the JUnit test method. - * @return The name of the corresponding interop test case. - */ - public String getTestCaseNameForTestMethod(String methodName) - { - return "OptOutTest"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java deleted file mode 100644 index f9b8cbb898..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java +++ /dev/null @@ -1,510 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import org.apache.qpid.junit.extensions.SleepThrottle; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.junit.extensions.util.TestContextProperties; -import org.apache.qpid.test.framework.MessagingTestConfigProperties; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.framework.clocksynch.ClockSynchThread; -import org.apache.qpid.test.framework.clocksynch.UDPClockSynchronizer; -import org.apache.qpid.test.utils.ReflectionUtils; -import org.apache.qpid.test.utils.ReflectionUtilsException; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.Topic; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * Implements a test client as described in the interop testing spec - * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that - * reacts to control message sequences send by the test {@link Coordinator}. - * - *

- *
Messages Handled by TestClient
Message Action - *
Invite(compulsory) Reply with Enlist. - *
Invite(test case) Reply with Enlist if test case available. - *
AssignRole(test case) Reply with Accept Role if matches an enlisted test. Keep test parameters. - *
Start Send test messages defined by test parameters. Send report on messages sent. - *
Status Request Send report on messages received. - *
Terminate Terminate the test client. - *
ClockSynch Synch clock against the supplied UDP address. - *
- * - *

- *
CRC Card
Responsibilities Collaborations - *
Handle all incoming control messages. {@link TestClientControlledTest} - *
Configure and look up test cases by name. {@link TestClientControlledTest} - *
- */ -public class TestClient implements MessageListener -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(TestClient.class); - - /** Used for reporting to the console. */ - private static final Logger console = Logger.getLogger("CONSOLE"); - - /** Holds the default identifying name of the test client. */ - public static final String CLIENT_NAME = "java"; - - /** - * Holds the test context properties that provides the default test parameters, plus command line overrides. - * This is initialized with the default test parameters, to which command line overrides may be applied. - */ - public static ParsedProperties testContextProperties = - TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); - - /** Holds all the test cases loaded from the classpath. */ - Map testCases = new HashMap(); - - /** Holds the test case currently being run by this client. */ - protected TestClientControlledTest currentTestCase; - - /** Holds the connection to the broker that the test is being coordinated on. */ - protected Connection connection; - - /** Holds the message producer to hold the test coordination over. */ - protected MessageProducer producer; - - /** Holds the JMS controlSession for the test coordination. */ - protected Session session; - - /** Holds the name of this client, with a default value. */ - protected String clientName = CLIENT_NAME; - - /** This flag indicates that the test client should attempt to join the currently running test case on start up. */ - protected boolean join; - - /** Holds the clock synchronizer for the test node. */ - ClockSynchThread clockSynchThread; - - /** - * Creates a new interop test client, listenting to the specified broker and virtual host, with the specified client - * identifying name. - * - * @param pBrokerUrl The url of the broker to connect to. - * @param pVirtualHost The virtual host to conect to. - * @param clientName The client name to use. - * @param join Flag to indicate that this client should attempt to join running tests. - */ - public TestClient(String pBrokerUrl, String pVirtualHost, String clientName, boolean join) - { - log.debug("public TestClient(String pBrokerUrl = " + pBrokerUrl + ", String pVirtualHost = " + pVirtualHost - + ", String clientName = " + clientName + ", boolean join = " + join + "): called"); - - // Retain the connection parameters. - this.clientName = clientName; - this.join = join; - - // Save properies from command line to defaults - if (pBrokerUrl != null) - { - testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, pBrokerUrl); - } - if (pVirtualHost != null) - { - testContextProperties.setProperty(MessagingTestConfigProperties.VIRTUAL_HOST_PROPNAME, pVirtualHost); - } - } - - /** - * The entry point for the interop test coordinator. This client accepts the following command line arguments: - * - *

- *
-b The broker URL. Optional. - *
-h The virtual host. Optional. - *
-n The test client name. Optional. - *
name=value Trailing argument define name/value pairs. Added to system properties. Optional. - *
- * - * @param args The command line arguments. - */ - public static void main(String[] args) - { - log.debug("public static void main(String[] args = " + Arrays.toString(args) + "): called"); - console.info("Qpid Distributed Test Client."); - - // Override the default broker url to be localhost:5672. - testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672"); - - // Use the command line parser to evaluate the command line with standard handling behaviour (print errors - // and usage then exist if there are errors). - // Any options and trailing name=value pairs are also injected into the test context properties object, - // to override any defaults that may have been set up. - ParsedProperties options = - new ParsedProperties(org.apache.qpid.junit.extensions.util.CommandLineParser.processCommandLine(args, - new org.apache.qpid.junit.extensions.util.CommandLineParser( - new String[][] - { - { "b", "The broker URL.", "broker", "false" }, - { "h", "The virtual host to use.", "virtual host", "false" }, - { "o", "The name of the directory to output test timings to.", "dir", "false" }, - { "n", "The name of the test client.", "name", "false" }, - { "j", "Join this test client to running test.", "false" } - }), testContextProperties)); - - // Extract the command line options. - String brokerUrl = options.getProperty("b"); - String virtualHost = options.getProperty("h"); - String clientName = options.getProperty("n"); - clientName = (clientName == null) ? CLIENT_NAME : clientName; - boolean join = options.getPropertyAsBoolean("j"); - - // To distinguish logging output set up an NDC on the client name. - NDC.push(clientName); - - // Create a test client and start it running. - TestClient client = new TestClient(brokerUrl, virtualHost, clientName, join); - - // Use a class path scanner to find all the interop test case implementations. - // Hard code the test classes till the classpath scanner is fixed. - Collection> testCaseClasses = - new ArrayList>(); - // ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true); - testCaseClasses.addAll(loadTestCases("org.apache.qpid.interop.clienttestcases.TestCase1DummyRun", - "org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P", - "org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub", - "org.apache.qpid.interop.clienttestcases.TestCase4P2PMessageSize", - "org.apache.qpid.interop.clienttestcases.TestCase5PubSubMessageSize", - "org.apache.qpid.test.framework.distributedcircuit.TestClientCircuitEnd")); - - try - { - client.start(testCaseClasses); - } - catch (Exception e) - { - log.error("The test client was unable to start.", e); - console.info(e.getMessage()); - System.exit(1); - } - } - - /** - * Parses a list of class names, and loads them if they are available on the class path. - * - * @param classNames The names of the classes to load. - * - * @return A list of the loaded test case classes. - */ - public static List> loadTestCases(String... classNames) - { - List> testCases = - new LinkedList>(); - - for (String className : classNames) - { - try - { - Class cls = ReflectionUtils.forName(className); - testCases.add((Class) cls); - } - catch (ReflectionUtilsException e) - { - // Ignore, class could not be found, so test not available. - console.warn("Requested class " + className + " cannot be found, ignoring it."); - } - catch (ClassCastException e) - { - // Ignore, class was not of correct type to be a test case. - console.warn("Requested class " + className + " is not an instance of TestClientControlledTest."); - } - } - - return testCases; - } - - /** - * Starts the interop test client running. This causes it to start listening for incoming test invites. - * - * @param testCaseClasses The classes of the available test cases. The test case names from these are used to - * matchin incoming test invites against. - * - * @throws JMSException Any underlying JMSExceptions are allowed to fall through. - */ - protected void start(Collection> testCaseClasses) throws JMSException - { - log.debug("protected void start(Collection> testCaseClasses = " - + testCaseClasses + "): called"); - - // Create all the test case implementations and index them by the test names. - for (Class nextClass : testCaseClasses) - { - try - { - TestClientControlledTest testCase = nextClass.newInstance(); - testCases.put(testCase.getName(), testCase); - } - catch (InstantiationException e) - { - log.warn("Could not instantiate test case class: " + nextClass.getName(), e); - // Ignored. - } - catch (IllegalAccessException e) - { - log.warn("Could not instantiate test case class due to illegal access: " + nextClass.getName(), e); - // Ignored. - } - } - - // Open a connection to communicate with the coordinator on. - connection = TestUtils.createConnection(testContextProperties); - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - // Set this up to listen for control messages. - Topic privateControlTopic = session.createTopic("iop.control." + clientName); - MessageConsumer consumer = session.createConsumer(privateControlTopic); - consumer.setMessageListener(this); - - Topic controlTopic = session.createTopic("iop.control"); - MessageConsumer consumer2 = session.createConsumer(controlTopic); - consumer2.setMessageListener(this); - - // Create a producer to send replies with. - producer = session.createProducer(null); - - // If the join flag was set, then broadcast a join message to notify the coordinator that a new test client - // is available to join the current test case, if it supports it. This message may be ignored, or it may result - // in this test client receiving a test invite. - if (join) - { - Message joinMessage = session.createMessage(); - - joinMessage.setStringProperty("CONTROL_TYPE", "JOIN"); - joinMessage.setStringProperty("CLIENT_NAME", clientName); - joinMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName); - producer.send(controlTopic, joinMessage); - } - - // Start listening for incoming control messages. - connection.start(); - } - - /** - * Handles all incoming control messages. - * - * @param message The incoming message. - */ - public void onMessage(Message message) - { - NDC.push(clientName); - log.debug("public void onMessage(Message message = " + message + "): called"); - - try - { - String controlType = message.getStringProperty("CONTROL_TYPE"); - String testName = message.getStringProperty("TEST_NAME"); - - log.debug("Received control of type '" + controlType + "' for the test '" + testName + "'"); - - // Check if the message is a test invite. - if ("INVITE".equals(controlType)) - { - // Flag used to indicate that an enlist should be sent. Only enlist to compulsory invites or invites - // for which test cases exist. - boolean enlist = false; - - if (testName != null) - { - log.debug("Got an invite to test: " + testName); - - // Check if the requested test case is available. - TestClientControlledTest testCase = testCases.get(testName); - - if (testCase != null) - { - log.debug("Found implementing class for test '" + testName + "', enlisting for it."); - - // Check if the test case will accept the invitation. - enlist = testCase.acceptInvite(message); - - log.debug("The test case " - + (enlist ? " accepted the invite, enlisting for it." - : " did not accept the invite, not enlisting.")); - - // Make the requested test case the current test case. - currentTestCase = testCase; - } - else - { - log.debug("Received an invite to the test '" + testName + "' but this test is not known."); - } - } - else - { - log.debug("Got a compulsory invite, enlisting for it."); - - enlist = true; - } - - if (enlist) - { - // Reply with the client name in an Enlist message. - Message enlistMessage = session.createMessage(); - enlistMessage.setStringProperty("CONTROL_TYPE", "ENLIST"); - enlistMessage.setStringProperty("CLIENT_NAME", clientName); - enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName); - enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID()); - - log.debug("Sending enlist message '" + enlistMessage.getJMSMessageID() + "' to " + message.getJMSReplyTo()); - - producer.send(message.getJMSReplyTo(), enlistMessage); - } - else - { - // Reply with the client name in an Decline message. - Message enlistMessage = session.createMessage(); - enlistMessage.setStringProperty("CONTROL_TYPE", "DECLINE"); - enlistMessage.setStringProperty("CLIENT_NAME", clientName); - enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName); - enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID()); - - log.debug("Sending decline message '" + enlistMessage.getJMSMessageID() + "' to " + message.getJMSReplyTo()); - - producer.send(message.getJMSReplyTo(), enlistMessage); - } - } - else if ("ASSIGN_ROLE".equals(controlType)) - { - // Assign the role to the current test case. - String roleName = message.getStringProperty("ROLE"); - - log.debug("Got a role assignment to role: " + roleName); - - TestClientControlledTest.Roles role = Enum.valueOf(TestClientControlledTest.Roles.class, roleName); - - currentTestCase.assignRole(role, message); - - // Reply by accepting the role in an Accept Role message. - Message acceptRoleMessage = session.createMessage(); - acceptRoleMessage.setStringProperty("CLIENT_NAME", clientName); - acceptRoleMessage.setStringProperty("CONTROL_TYPE", "ACCEPT_ROLE"); - acceptRoleMessage.setJMSCorrelationID(message.getJMSCorrelationID()); - - log.debug("Sending accept role message '" + acceptRoleMessage.getJMSMessageID() + "' to " + message.getJMSReplyTo()); - - producer.send(message.getJMSReplyTo(), acceptRoleMessage); - } - else if ("START".equals(controlType) || "STATUS_REQUEST".equals(controlType)) - { - if ("START".equals(controlType)) - { - log.debug("Got a start notification."); - - // Extract the number of test messages to send from the start notification. - int numMessages; - - try - { - numMessages = message.getIntProperty("MESSAGE_COUNT"); - } - catch (NumberFormatException e) - { - // If the number of messages is not specified, use the default of one. - numMessages = 1; - } - - // Start the current test case. - currentTestCase.start(numMessages); - } - else - { - log.debug("Got a status request."); - } - - // Generate the report from the test case and reply with it as a Report message. - Message reportMessage = currentTestCase.getReport(session); - reportMessage.setStringProperty("CLIENT_NAME", clientName); - reportMessage.setStringProperty("CONTROL_TYPE", "REPORT"); - reportMessage.setJMSCorrelationID(message.getJMSCorrelationID()); - - log.debug("Sending report message '" + reportMessage.getJMSMessageID() + "' to " + message.getJMSReplyTo()); - - producer.send(message.getJMSReplyTo(), reportMessage); - } - else if ("TERMINATE".equals(controlType)) - { - console.info("Received termination instruction from coordinator."); - - // Is a cleaner shutdown needed? - connection.close(); - System.exit(0); - } - else if ("CLOCK_SYNCH".equals(controlType)) - { - log.debug("Received clock synch command."); - String address = message.getStringProperty("ADDRESS"); - - log.debug("address = " + address); - - // Re-create (if necessary) and start the clock synch thread to synch the clock every ten seconds. - if (clockSynchThread != null) - { - clockSynchThread.terminate(); - } - - SleepThrottle throttle = new SleepThrottle(); - throttle.setRate(0.1f); - - clockSynchThread = new ClockSynchThread(new UDPClockSynchronizer(address), throttle); - clockSynchThread.start(); - } - else - { - // Log a warning about this but otherwise ignore it. - log.warn("Got an unknown control message, controlType = " + controlType + ", message = " + message); - } - } - catch (JMSException e) - { - // Log a warning about this, but otherwise ignore it. - log.warn("Got JMSException whilst handling message: " + message, e); - } - // Log any runtimes that fall through this message handler. These are fatal errors for the test client. - catch (RuntimeException e) - { - log.error("The test client message handler got an unhandled exception: ", e); - console.info("The message handler got an unhandled exception, terminating the test client."); - System.exit(1); - } - finally - { - NDC.pop(); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java deleted file mode 100644 index 2e64c9ca2d..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; - -/** - * TestClientControlledTest provides an interface that classes implementing test cases to run on a {@link TestClient} - * node can use. Implementations must be Java beans, that is, to provide a default constructor and to implement the - * {@link #getName} method. - * - *

The methods specified in this interface are called when the {@link TestClient} receives control instructions to - * apply to the test. There are control instructions to present the test case with the test invite, so that it may - * choose whether or not to participate in the test, assign the test to play the sender or receiver role, start the - * test and obtain the test status report. - * - *

- *
CRC Card
Responsibilities - *
Supply the name of the test case that this implements. - *
Accept/Reject invites based on test parameters. - *
Adapt to assigned roles. - *
Perform test case actions. - *
Generate test reports. - *
- */ -public interface TestClientControlledTest -{ - /** Defines the possible test case roles that an interop test case can take on. */ - public enum Roles - { - /** Specifies the sender role. */ - SENDER, - - /** Specifies the receivers role. */ - RECEIVER - } - - /** - * Should provide the name of the test case that this class implements. The exact names are defined in the - * interop testing spec. - * - * @return The name of the test case that this implements. - */ - public String getName(); - - /** - * Determines whether the test invite that matched this test case is acceptable. - * - * @param inviteMessage The invitation to accept or reject. - * - * @return true to accept the invitation, false to reject it. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public boolean acceptInvite(Message inviteMessage) throws JMSException; - - /** - * Assigns the role to be played by this test case. The test parameters are fully specified in the - * assignment message. When this method return the test case will be ready to execute. - * - * @param role The role to be played; sender or receivers. - * @param assignRoleMessage The role assingment message, contains the full test parameters. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public void assignRole(Roles role, Message assignRoleMessage) throws JMSException; - - /** - * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. - * - * @param numMessages The number of test messages to send. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public void start(int numMessages) throws JMSException; - - /** - * Gets a report on the actions performed by the test case in its assigned role. - * - * @param session The controlSession to create the report message in. - * - * @return The report message. - * - * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through. - */ - public Message getReport(Session session) throws JMSException; -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java b/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java deleted file mode 100644 index ad2c196adb..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.listeners; - -import junit.framework.AssertionFailedError; -import junit.framework.Test; -import junit.framework.TestCase; -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.ShutdownHookable; -import org.apache.qpid.junit.extensions.listeners.TKTestListener; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * Listens for test results for a named test and outputs these in the standard JUnit XML format to the specified - * writer. - * - *

The API for this listener accepts notifications about different aspects of a tests results through different - * methods, so some assumption needs to be made as to which test result a notification refers to. For example - * {@link #startTest} will be called, then possibly {@link #timing} will be called, even though the test instance is - * passed in both cases, it is not enough to distinguish a particular run of the test, as the test case instance may - * be being shared between multiple threads, or being run a repeated number of times, and can therfore be re-used - * between calls. The listeners make the assumption that, for every test, a unique thread will call {@link #startTest} - * and {@link #endTest} to delimit each test. All calls to set test parameters, timings, state and so on, will occur - * between the start and end and will be given with the same thread id as the start and end, so the thread id provides - * a unqiue value to identify a particular test run against. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Listen to test lifecycle notifications. - *
Listen to test errors and failures. - *
Listen to test timings. - *
Listen to test memory usages. - *
Listen to parameterized test parameters. - *
Responsibilities - *
- * - * @todo Merge this class with CSV test listener, making the collection of results common to both, and only factoring - * out the results printing code into sub-classes. Provide a simple XML results formatter with the same format as - * the ant XML formatter, and a more structured one for outputing results with timings and summaries from - * performance tests. - */ -public class XMLTestListener implements TKTestListener, ShutdownHookable -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(XMLTestListener.class); - - /** The results file writer. */ - protected Writer writer; - - /** Holds the results for individual tests. */ - // protected Map results = new LinkedHashMap(); - // protected List results = new ArrayList(); - - /** - * Map for holding results on a per thread basis as they come in. A ThreadLocal is not used as sometimes an - * explicit thread id must be used, where notifications come from different threads than the ones that called - * the test method. - */ - Map threadLocalResults = Collections.synchronizedMap(new LinkedHashMap()); - - /** - * Holds results for tests that have ended. Transferring these results here from the per-thread results map, means - * that the thread id is freed for the thread to generate more results. - */ - List results = new ArrayList(); - - /** Holds the overall error count. */ - protected int errors = 0; - - /** Holds the overall failure count. */ - protected int failures = 0; - - /** Holds the overall tests run count. */ - protected int runs = 0; - - /** Holds the name of the class that tests are being run for. */ - String testClassName; - - /** - * Creates a new XML results output listener that writes to the specified location. - * - * @param writer The location to write results to. - * @param testClassName The name of the test class to include in the test results. - */ - public XMLTestListener(Writer writer, String testClassName) - { - log.debug("public XMLTestListener(Writer writer, String testClassName = " + testClassName + "): called"); - - this.writer = writer; - this.testClassName = testClassName; - } - - /** - * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed. - * - * @param test The test to resest any results for. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void reset(Test test, Long threadId) - { - log.debug("public void reset(Test test = " + test + ", Long threadId = " + threadId + "): called"); - - XMLTestListener.Result r = - (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId); - - r.error = null; - r.failure = null; - - } - - /** - * Notification that a test started. - * - * @param test The test that started. - */ - public void startTest(Test test) - { - log.debug("public void startTest(Test test = " + test + "): called"); - - Result newResult = new Result(test.getClass().getName(), ((TestCase) test).getName()); - - // Initialize the thread local test results. - threadLocalResults.put(Thread.currentThread().getId(), newResult); - runs++; - } - - /** - * Should be called every time a test completes with the run time of that test. - * - * @param test The name of the test. - * @param nanos The run time of the test in nanoseconds. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void timing(Test test, long nanos, Long threadId) - { } - - /** - * Optionally called every time a test completes with the second timing test. - * - * @param test The name of the test. - * @param nanos The second timing information of the test in nanoseconds. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void timing2(Test test, Long nanos, Long threadId) - { } - - /** - * Should be called every time a test completed with the amount of memory used before and after the test was run. - * - * @param test The test which memory was measured for. - * @param memStart The total JVM memory used before the test was run. - * @param memEnd The total JVM memory used after the test was run. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void memoryUsed(Test test, long memStart, long memEnd, Long threadId) - { } - - /** - * Should be called every time a parameterized test completed with the int value of its test parameter. - * - * @param test The test which memory was measured for. - * @param parameter The int parameter value. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void parameterValue(Test test, int parameter, Long threadId) - { } - - /** - * Should be called every time a test completes with the current number of test threads running. - * - * @param test The test for which the measurement is being generated. - * @param threads The number of tests being run concurrently. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void concurrencyLevel(Test test, int threads, Long threadId) - { } - - /** - * Notifies listeners of the tests read/set properties. - * - * @param properties The tests read/set properties. - */ - public void properties(Properties properties) - { } - - /** - * Notification that a test ended. - * - * @param test The test that ended. - */ - public void endTest(Test test) - { - log.debug("public void endTest(Test test = " + test + "): called"); - - // Move complete test results into the completed tests list. - Result r = threadLocalResults.get(Thread.currentThread().getId()); - results.add(r); - - // Clear all the test results for the thread. - threadLocalResults.remove(Thread.currentThread().getId()); - } - - /** - * Called when a test completes. Success, failure and errors. This method should be used when registering an - * end test from a different thread than the one that started the test. - * - * @param test The test which completed. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void endTest(Test test, Long threadId) - { - log.debug("public void endTest(Test test = " + test + ", Long threadId = " + threadId + "): called"); - - // Move complete test results into the completed tests list. - Result r = - (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId); - results.add(r); - - // Clear all the test results for the thread. - threadLocalResults.remove(Thread.currentThread().getId()); - } - - /** - * An error occurred. - * - * @param test The test in which the error occurred. - * @param t The throwable that resulted from the error. - */ - public void addError(Test test, Throwable t) - { - log.debug("public void addError(Test test = " + test + ", Throwable t = " + t + "): called"); - - Result r = threadLocalResults.get(Thread.currentThread().getId()); - r.error = t; - errors++; - } - - /** - * A failure occurred. - * - * @param test The test in which the failure occurred. - * @param t The JUnit assertions that led to the failure. - */ - public void addFailure(Test test, AssertionFailedError t) - { - log.debug("public void addFailure(Test test = " + test + ", AssertionFailedError t = " + t + "): called"); - - Result r = threadLocalResults.get(Thread.currentThread().getId()); - r.failure = t; - failures++; - } - - /** - * Called when a test completes to mark it as a test fail. This method should be used when registering a - * failure from a different thread than the one that started the test. - * - * @param test The test which failed. - * @param e The assertion that failed the test. - * @param threadId Optional thread id if not calling from thread that started the test method. May be null. - */ - public void addFailure(Test test, AssertionFailedError e, Long threadId) - { - log.debug("public void addFailure(Test test, AssertionFailedError e, Long threadId): called"); - - Result r = - (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId); - r.failure = e; - failures++; - } - - /** - * Notifies listeners of the start of a complete run of tests. - */ - public void startBatch() - { - log.debug("public void startBatch(): called"); - - // Reset all results counts. - threadLocalResults = Collections.synchronizedMap(new HashMap()); - errors = 0; - failures = 0; - runs = 0; - - // Write out the file header. - try - { - writer.write("\n"); - } - catch (IOException e) - { - throw new RuntimeException("Unable to write the test results.", e); - } - } - - /** - * Notifies listeners of the end of a complete run of tests. - * - * @param parameters The optional test parameters to log out with the batch results. - */ - public void endBatch(Properties parameters) - { - log.debug("public void endBatch(Properties parameters = " + parameters + "): called"); - - // Write out the results. - try - { - // writer.write("\n"); - writer.write("\n"); - - for (Result result : results) - { - writer.write(" \n"); - - if (result.error != null) - { - writer.write(" "); - result.error.printStackTrace(new PrintWriter(writer)); - writer.write(" "); - } - else if (result.failure != null) - { - writer.write(" "); - result.failure.printStackTrace(new PrintWriter(writer)); - writer.write(" "); - } - - writer.write(" \n"); - } - - writer.write("\n"); - writer.flush(); - } - catch (IOException e) - { - throw new RuntimeException("Unable to write the test results.", e); - } - } - - /** - * Supplies the shutdown hook. - * - * @return The shut down hook. - */ - public Thread getShutdownHook() - { - return new Thread(new Runnable() - { - public void run() - { - log.debug("XMLTestListener::ShutdownHook: called"); - } - }); - } - - /** - * Used to capture the results of a particular test run. - */ - protected static class Result - { - /** Holds the name of the test class. */ - public String testClass; - - /** Holds the name of the test method. */ - public String testName; - - /** Holds the exception that caused error in this test. */ - public Throwable error; - - /** Holds the assertion exception that caused failure in this test. */ - public AssertionFailedError failure; - - /** - * Creates a placeholder for the results of a test. - * - * @param testClass The test class. - * @param testName The name of the test that was run. - */ - public Result(String testClass, String testName) - { - this.testClass = testClass; - this.testName = testName; - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java deleted file mode 100644 index 6a0e8cba4b..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.qpid.client.AMQNoConsumersException; -import org.apache.qpid.client.AMQNoRouteException; -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.AMQPPublisher; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.AssertionBase; -import org.apache.qpid.test.framework.CircuitEndBase; -import org.apache.qpid.test.framework.ExceptionMonitor; -import org.apache.qpid.test.framework.MessageMonitor; - -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * LocalAMQPPublisherImpl is an extension of {@link LocalPublisherImpl} that adds AMQP specific features. Specifically - * extra assertions for AMQP features not available through generic JMS. - * - *

- *
CRC Card
Responsibilities Collaborations - *
- *
- */ -public class LocalAMQPPublisherImpl extends LocalPublisherImpl implements AMQPPublisher -{ - /** - * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured - * for messages and exceptions received by the circuit end. - * - * @param producer The message producer for the circuit end point. - * @param consumer The message consumer for the circuit end point. - * @param session The controlSession for the circuit end point. - * @param messageMonitor The monitor to notify of all messages received by the circuit end. - * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end. - */ - public LocalAMQPPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session, - MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor) - { - super(producer, consumer, session, messageMonitor, exceptionMonitor); - } - - /** - * Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation. - * - * @param end The circuit end base implementation to take producers and consumers from. - */ - public LocalAMQPPublisherImpl(CircuitEndBase end) - { - super(end); - } - - /** - * Provides an assertion that the publisher got a no consumers exception on every message. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the publisher got a no consumers exception on every message. - */ - public Assertion noConsumersAssertion(ParsedProperties testProps) - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class)) - { - passed = false; - - addError("Was expecting linked exception type " + AMQNoConsumersException.class.getName() - + " on the connection.\n"); - addError((connectionExceptionMonitor.size() > 0) - ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor) - : "Got no exceptions on the connection."); - } - - return passed; - } - }; - } - - /** - * Provides an assertion that the publisher got a no rout exception on every message. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the publisher got a no rout exception on every message. - */ - public Assertion noRouteAssertion(ParsedProperties testProps) - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class)) - { - passed = false; - - addError("Was expecting linked exception type " + AMQNoRouteException.class.getName() - + " on the connection.\n"); - addError((connectionExceptionMonitor.size() > 0) - ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor) - : "Got no exceptions on the connection."); - } - - return passed; - } - }; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java deleted file mode 100644 index dc9ee0ac28..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.CircuitEnd; -import org.apache.qpid.test.framework.ExceptionMonitor; -import org.apache.qpid.test.framework.MessagingTestConfigProperties; -import org.apache.qpid.test.framework.Publisher; -import org.apache.qpid.test.framework.Receiver; -import org.apache.qpid.test.framework.TestUtils; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import java.util.LinkedList; -import java.util.List; - -/** - * LocalCircuitImpl provides an implementation of the test circuit. This is a local only circuit implementation that - * supports a single producer/consumer on each end of the circuit, with both ends of the circuit on the same JVM. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Supply the publishing and receiving ends of a test messaging circuit. - * {@link LocalPublisherImpl}, {@link LocalReceiverImpl} - *
Start the circuit running. - *
Close the circuit down. - *
Take a reading of the circuits state. - *
Apply assertions against the circuits state. {@link Assertion} - *
Send test messages over the circuit. - *
Perform the default test procedure on the circuit. - *
Provide access to connection and controlSession exception monitors. {@link ExceptionMonitor} - *
- */ -public class LocalCircuitImpl implements Circuit -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(LocalCircuitImpl.class); - - /** Holds the test configuration for the circuit. */ - private ParsedProperties testProps; - - /** Holds the publishing end of the circuit. */ - private LocalPublisherImpl publisher; - - /** Holds the receiving end of the circuit. */ - private LocalReceiverImpl receiver; - - /** Holds the connection for the publishing end of the circuit. */ - private Connection connection; - - /** Holds the exception listener for the connection on the publishing end of the circuit. */ - private ExceptionMonitor connectionExceptionMonitor; - - /** Holds the exception listener for the controlSession on the publishing end of the circuit. */ - private ExceptionMonitor exceptionMonitor; - - /** - * Creates a test circuit using the specified test parameters. The publisher, receivers, connection and - * connection monitor must already have been created, to assemble the circuit. - * - * @param testProps The test parameters. - * @param publisher The test publisher. - * @param receiver The test receivers. - * @param connection The connection. - * @param connectionExceptionMonitor The connection exception monitor. - */ - public LocalCircuitImpl(ParsedProperties testProps, LocalPublisherImpl publisher, LocalReceiverImpl receiver, - Connection connection, ExceptionMonitor connectionExceptionMonitor) - { - this.testProps = testProps; - this.publisher = publisher; - this.receiver = receiver; - this.connection = connection; - this.connectionExceptionMonitor = connectionExceptionMonitor; - this.exceptionMonitor = new ExceptionMonitor(); - - // Set this as the parent circuit on the publisher and receivers. - publisher.setCircuit(this); - receiver.setCircuit(this); - } - - /** - * Gets the interface on the publishing end of the circuit. - * - * @return The publishing end of the circuit. - */ - public Publisher getPublisher() - { - return publisher; - } - - /** - * Gets the local publishing circuit end, for direct manipulation. - * - * @return The local publishing circuit end. - */ - public CircuitEnd getLocalPublisherCircuitEnd() - { - return publisher; - } - - /** - * Gets the interface on the receiving end of the circuit. - * - * @return The receiving end of the circuit. - */ - public Receiver getReceiver() - { - return receiver; - } - - /** - * Gets the local receiving circuit end, for direct manipulation. - * - * @return The local receiving circuit end. - */ - public CircuitEnd getLocalReceiverCircuitEnd() - { - return receiver; - } - - /** - * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit, - * into a report, against which assertions may be checked. - */ - public void check() - { } - - /** - * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing - * this, to ensure that the circuit has gathered its state into a report to assert against. - * - * @param assertions The list of assertions to apply. - * @return Any assertions that failed. - */ - public List applyAssertions(List assertions) - { - List failures = new LinkedList(); - - for (Assertion assertion : assertions) - { - if (!assertion.apply()) - { - failures.add(assertion); - } - } - - return failures; - } - - /** - * Connects and starts the circuit. After this method is called the circuit is ready to send messages. - */ - public void start() - { } - - /** - * Closes the circuit. All associated resources are closed. - */ - public void close() - { - try - { - publisher.close(); - receiver.close(); - connection.close(); - } - catch (JMSException e) - { - throw new RuntimeException("Got JMSException during close:" + e.getMessage(), e); - } - } - - /** - * Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters. - */ - protected void send() - { - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps); - - boolean transactional = props.getPublisherTransacted(); - boolean rollback = props.getRollbackPublisher(); - - // Send a message through the publisher and log any exceptions raised. - try - { - CircuitEnd end = getLocalPublisherCircuitEnd(); - - end.send(createTestMessage(end)); - - if (rollback) - { - end.getSession().rollback(); - } - else if (transactional) - { - end.getSession().commit(); - } - } - catch (JMSException e) - { - exceptionMonitor.onException(e); - } - } - - /** - * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. The - * outline of the default test procedure is: - * - *

-     * Start the circuit.
-     * Send test messages.
-     * Request a status report.
-     * Assert conditions on the publishing end of the circuit.
-     * Assert conditions on the receiving end of the circuit.
-     * Close the circuit.
-     * Pass with no failed assertions or fail with a list of failed assertions.
-     * 
- * - * @param numMessages The number of messages to send using the default test procedure. - * @param assertions The list of assertions to apply. - * @return Any assertions that failed. - */ - public List test(int numMessages, List assertions) - { - // Start the test circuit. - start(); - - // Send the requested number of test messages. - for (int i = 0; i < numMessages; i++) - { - send(); - } - - // Inject a short pause to allow time for exceptions to come back asynchronously. - TestUtils.pause(500L); - - // Request a status report. - check(); - - // Clean up the publisher/receivers/controlSession/connections. - close(); - - // Apply all of the requested assertions, keeping record of any that fail. - List failures = applyAssertions(assertions); - - // Return any failed assertions to the caller. - return failures; - } - - /** - * Creates a message with the properties defined as per the test parameters. - * - * @param client The circuit end to create the message on. - * - * @return The test message. - * - * @throws JMSException Any JMSException occurring during creation of the message is allowed to fall through. - */ - private Message createTestMessage(CircuitEnd client) throws JMSException - { - // Cast the test properties into a typed interface for convenience. - MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps); - - return TestUtils.createTestMessageOfSize(client.getSession(), props.getMessageSize()); - } - - /** - * Gets the exception monitor for the publishing ends connection. - * - * @return The exception monitor for the publishing ends connection. - */ - public ExceptionMonitor getConnectionExceptionMonitor() - { - return connectionExceptionMonitor; - } - - /** - * Gets the exception monitor for the publishing ends controlSession. - * - * @return The exception monitor for the publishing ends controlSession. - */ - public ExceptionMonitor getExceptionMonitor() - { - return exceptionMonitor; - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java deleted file mode 100644 index 9920be003a..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.AssertionBase; -import org.apache.qpid.test.framework.CircuitEnd; -import org.apache.qpid.test.framework.CircuitEndBase; -import org.apache.qpid.test.framework.ExceptionMonitor; -import org.apache.qpid.test.framework.MessageMonitor; -import org.apache.qpid.test.framework.NotApplicableAssertion; -import org.apache.qpid.test.framework.Publisher; - -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * Provides an implementation of the {@link Publisher} interface and wraps a single message producer and consumer on - * a single controlSession, as a {@link CircuitEnd}. A local publisher also acts as a circuit end, because for a locally - * located circuit the assertions may be applied directly, there does not need to be any inter-process messaging - * between the publisher and its single circuit end, in order to ascertain its status. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a message producer for sending messages. - *
Provide a message consumer for receiving messages. - *
Provide assertion that the publisher received no exceptions. - *
Provide assertion that the publisher received a no consumers error code. - *
Provide assertion that the publisher received a no route error code. - *
- */ -public class LocalPublisherImpl extends CircuitEndBase implements Publisher -{ - /** Holds a reference to the containing circuit. */ - protected LocalCircuitImpl circuit; - - /** - * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured - * for messages and exceptions received by the circuit end. - * - * @param producer The message producer for the circuit end point. - * @param consumer The message consumer for the circuit end point. - * @param session The controlSession for the circuit end point. - * @param messageMonitor The monitor to notify of all messages received by the circuit end. - * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end. - */ - public LocalPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session, - MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor) - { - super(producer, consumer, session, messageMonitor, exceptionMonitor); - } - - /** - * Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation. - * - * @param end The circuit end base implementation to take producers and consumers from. - */ - public LocalPublisherImpl(CircuitEndBase end) - { - super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor()); - } - - /** - * Provides an assertion that the publisher encountered no exceptions. - * - * @param testProps - * - * @return An assertion that the publisher encountered no exceptions. - */ - public Assertion noExceptionsAssertion(ParsedProperties testProps) - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor sessionExceptionMonitor = circuit.getExceptionMonitor(); - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertNoExceptions()) - { - passed = false; - - addError("Was expecting no exceptions.\n"); - addError("Got the following exceptions on the connection, " - + circuit.getConnectionExceptionMonitor()); - } - - if (!sessionExceptionMonitor.assertNoExceptions()) - { - passed = false; - - addError("Was expecting no exceptions.\n"); - addError("Got the following exceptions on the producer, " + circuit.getExceptionMonitor()); - } - - return passed; - } - }; - } - - /** - * Provides an assertion that the AMQP channel was forcibly closed by an error condition. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the AMQP channel was forcibly closed by an error condition. - */ - public Assertion channelClosedAssertion(ParsedProperties testProps) - { - return new NotApplicableAssertion(testProps); - } - - /** - * Provides an assertion that the publisher got a given exception during the test. - * - * @param testProps The test configuration properties. - * @param exceptionClass The exception class to check for. - * - * @return An assertion that the publisher got a given exception during the test. - */ - public Assertion exceptionAssertion(ParsedProperties testProps, final Class exceptionClass) - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertExceptionOfType(exceptionClass)) - { - passed = false; - - addError("Was expecting linked exception type " + exceptionClass.getName() - + " on the connection.\n"); - addError((connectionExceptionMonitor.size() > 0) - ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor) - : "Got no exceptions on the connection."); - } - - return passed; - } - }; - } - - /** - * Sets the contianing circuit. - * - * @param circuit The containing circuit. - */ - public void setCircuit(LocalCircuitImpl circuit) - { - this.circuit = circuit; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java deleted file mode 100644 index bb242faf90..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.CircuitEnd; -import org.apache.qpid.test.framework.CircuitEndBase; -import org.apache.qpid.test.framework.ExceptionMonitor; -import org.apache.qpid.test.framework.MessageMonitor; -import org.apache.qpid.test.framework.NotApplicableAssertion; -import org.apache.qpid.test.framework.Receiver; - -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * Provides an implementation of the {@link Receiver} interface that wraps a single message producer and consumer on - * a single controlSession, as a {@link CircuitEnd}. A local receiver also acts as a circuit end, because for a locally - * located circuit the assertions may be applied directly, there does not need to be any inter process messaging - * between the publisher and its single circuit end, in order to ascertain its status. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a message producer for sending messages. - *
Provide a message consumer for receiving messages. - *
Provide assertion that the receivers received no exceptions. - *
Provide assertion that the receivers received all test messages sent to it. - *
- */ -public class LocalReceiverImpl extends CircuitEndBase implements Receiver -{ - /** Holds a reference to the containing circuit. */ - private LocalCircuitImpl circuit; - - /** - * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured - * for messages and exceptions received by the circuit end. - * - * @param producer The message producer for the circuit end point. - * @param consumer The message consumer for the circuit end point. - * @param session The controlSession for the circuit end point. - * @param messageMonitor The monitor to notify of all messages received by the circuit end. - * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end. - */ - public LocalReceiverImpl(MessageProducer producer, MessageConsumer consumer, Session session, - MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor) - { - super(producer, consumer, session, messageMonitor, exceptionMonitor); - } - - /** - * Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation. - * - * @param end The circuit end base implementation to take producers and consumers from. - */ - public LocalReceiverImpl(CircuitEndBase end) - { - super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor()); - } - - /** - * Provides an assertion that the receivers encountered no exceptions. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the receivers encountered no exceptions. - */ - public Assertion noExceptionsAssertion(ParsedProperties testProps) - { - return new NotApplicableAssertion(testProps); - } - - /** - * Provides an assertion that the AMQP channel was forcibly closed by an error condition. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the AMQP channel was forcibly closed by an error condition. - */ - public Assertion channelClosedAssertion(ParsedProperties testProps) - { - return new NotApplicableAssertion(testProps); - } - - /** - * Provides an assertion that the receivers got all messages that were sent to it. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the receivers got all messages that were sent to it. - */ - public Assertion allMessagesReceivedAssertion(ParsedProperties testProps) - { - return new NotApplicableAssertion(testProps); - } - - /** - * Provides an assertion that the receivers got none of the messages that were sent to it. - * - * @param testProps The test configuration properties. - * - * @return An assertion that the receivers got none of the messages that were sent to it. - */ - public Assertion noMessagesReceivedAssertion(ParsedProperties testProps) - { - return new NotApplicableAssertion(testProps); - } - - /** - * Provides an assertion that the receiver got a given exception during the test. - * - * @param testProps The test configuration properties. - * @param exceptionClass The exception class to check for. @return An assertion that the receiver got a given exception during the test. - */ - public Assertion exceptionAssertion(ParsedProperties testProps, Class exceptionClass) - { - return new NotApplicableAssertion(testProps); - } - - /** - * Sets the contianing circuit. - * - * @param circuit The containing circuit. - */ - public void setCircuit(LocalCircuitImpl circuit) - { - this.circuit = circuit; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/package.html b/java/systests/src/main/java/org/apache/qpid/test/framework/package.html deleted file mode 100644 index ac4e30d312..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/package.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - -

A framework for testing Qpid, built around a standard 'test circuit' design. The idea behind this framework is the -use of a test circuit which is configured by a set of test parameters, that may be projected onto a topology of -test nodes, with tests scripted to run over test circuits, making as few assumptions as possible about the underlying -topology. The standardization of the design, whilst limiting in some respectes, allows a large variety of test -scenarios to be written with minimal amounts of coding. - -

The standard consruction block for a test, is a test circuit. This consists of a publisher, and a receiver. The -publisher and receiver may reside on the same machine, or may be distributed. Will use a standard set of properties to -define the desired circuit topology. - -

Tests are always to be controlled from the publishing side only. The receiving end of the circuit is to be exposed -to the test code through an interface, that abstracts as much as possible the receiving end of the test. The interface -exposes a set of 'assertions' that may be applied to the receiving end of the test circuit. - -

In the case where the receiving end of the circuit resides on the same JVM, the assertions will call the receivers -code locally. Where the receiving end is distributed accross one or more machines, the assertions will be applied to a -test report gethered from all of the receivers. Test code will be written to the assertions making as few assumptions -as possible about the exact test topology. - - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java deleted file mode 100644 index bd27fc3d90..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.utils.ConversationFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -/** - * BaseCircuitFactory provides some functionality common to all {@link CircuitFactory}s, such as the details of - * all {@link org.apache.qpid.test.framework.distributedtesting.TestClient}s that make up the end-points of - * the circuits that the factory creates, and an active {@link ConversationFactory} that can be used to generate - * control conversations with those circuit end-points. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Hold the details of the sending and receiving end-points to create circuits from. - *
Provide a conversation factory to create control conversations with the end-points. - *
- */ -public abstract class BaseCircuitFactory implements CircuitFactory -{ - - /** Used for debugging. */ - private final Logger log = Logger.getLogger(BaseCircuitFactory.class); - - /** Holds the contact details for the sending test client. */ - protected TestClientDetails sender; - - /** Holds the contact details for the receving test client. */ - protected List receivers = new LinkedList(); - - /** Holds the conversation factory over which to coordinate the test. */ - protected ConversationFactory conversationFactory; - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * @return A test circuit. - */ - public Circuit createCircuit(Properties testProperties) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Sets the sender test client to coordinate the test with. - * - * @param sender The contact details of the sending client in the test. - */ - public void setSender(TestClientDetails sender) - { - log.debug("public void setSender(TestClientDetails sender = " + sender + "): called"); - - this.sender = sender; - } - - /** - * Sets the receiving test client to coordinate the test with. - * - * @param receiver The contact details of the sending client in the test. - */ - public void setReceiver(TestClientDetails receiver) - { - log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called"); - - this.receivers.add(receiver); - } - - /** - * Supplies the sending test client. - * - * @return The sending test client. - */ - public TestClientDetails getSender() - { - return sender; - } - - /** - * Supplies the receiving test client. - * - * @return The receiving test client. - */ - public List getReceivers() - { - return receivers; - } - - /** - * Accepts the conversation factory over which to hold the test coordinating conversation. - * - * @param conversationFactory The conversation factory to coordinate the test over. - */ - public void setConversationFactory(ConversationFactory conversationFactory) - { - this.conversationFactory = conversationFactory; - } - - /** - * Provides the conversation factory for providing the distributed test sequencing conversations over the test - * connection. - * - * @return The conversation factory to create test sequencing conversations with. - */ - public ConversationFactory getConversationFactory() - { - return conversationFactory; - } -} - diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java deleted file mode 100644 index 9b5d40fd48..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import java.util.List; -import java.util.Properties; - -/** - * A CircuitFactory is responsibile for creating test circuits appropriate to the context that a test case is - * running in, and providing an implementation of a standard test procedure over a test circuit. - * - *

- *
CRC Card
Responsibilities - *
Provide a standard test procedure over a test circuit. - *
Construct test circuits appropriate to a tests context. - *
- */ -public interface CircuitFactory -{ - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test, gathering the test reports from the participants, and checking for assertion failures against - * the test reports. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - * - * @deprecated Use test circuits and Circuit.test instead. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties); - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * - * @return A test circuit. - */ - public Circuit createCircuit(Connection connection, ParsedProperties testProperties); - - /** - * Sets the sender test client to coordinate the test with. - * - * @param sender The contact details of the sending client in the test. - */ - public void setSender(TestClientDetails sender); - - /** - * Sets the receiving test client to coordinate the test with. - * - * @param receiver The contact details of the sending client in the test. - */ - public void setReceiver(TestClientDetails receiver); - - /** - * Supplies the sending test client. - * - * @return The sending test client. - */ - public TestClientDetails getSender(); - - /** - * Supplies the receiving test client. - * - * @return The receiving test client. - */ - public List getReceivers(); - - /** - * Accepts the conversation factory over which to hold the test coordinating conversation. - * - * @param conversationFactory The conversation factory to coordinate the test over. - */ - public void setConversationFactory(ConversationFactory conversationFactory); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java deleted file mode 100644 index 833f5fb674..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.framework.distributedcircuit.DistributedCircuitImpl; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -/** - * FanOutCircuitFactory is a circuit factory that creates distributed test circuits. Given a set of participating - * test client nodes, it assigns one node to the SENDER role and the remainder to the RECEIVER role. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Create distributed circuits from one to many test nodes, for fanout style testing. - *
- * - * @todo Adapt this to be an n*m topology circuit factory. Need to add circuit topology definitions to the test - * parameters. Place n senders onto the available test clients, and m receivers. Where n or m is larger than - * the available nodes, start stacking multiple test clients on each node. There will also be an option that - * indicates whether nodes can play both roles, and how many nodes out of all available may be assigned to - * each role. - * - * @todo The createCircuit methods on this and InteropCircuitFactory are going to be identical. This is because the - * partitioning into senders and receivers is already done by the test decorators. Either eliminate these factories - * as unnesesary, or move the partitioning functionality into the factories, in which case the test decorators - * can probably be merged or eliminated. There is confusion over the placement of responsibilities between the - * factories and the test decorators... although the test decorators may well do more than just circuit creation - * in the future. For example, there may have to be a special decorator for test repetition that does one circuit - * creation, but the runs many tests over it, in which case the handling of responsibilities becomes clearer. - */ -public class FanOutCircuitFactory extends BaseCircuitFactory -{ - /** Used for debugging. */ - private Logger log = Logger.getLogger(FanOutCircuitFactory.class); - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * @return A test circuit. - */ - public Circuit createCircuit(Connection connection, ParsedProperties testProperties) - { - log.debug("public Circuit createCircuit(ParsedProperties testProperties): called"); - - List senders = new LinkedList(); - senders.add(getSender()); - List receivers = getReceivers(); - ConversationFactory conversationFactory = getConversationFactory(); - - return DistributedCircuitImpl.createCircuit(testProperties, senders, receivers, conversationFactory); - } - - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test, gathering the test reports from the participants, and checking for assertion failures against - * the test reports. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - * - * @deprecated Scheduled for removal once existing tests converted over to use test circuits. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) - { - log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); - - TestClientDetails sender = getSender(); - List receivers = getReceivers(); - ConversationFactory conversationFactory = getConversationFactory(); - - try - { - // Create a conversation on the sender clients private control route. - Session session = conversationFactory.getSession(); - Destination senderControlTopic = session.createTopic(sender.privateControlKey); - ConversationFactory.Conversation senderConversation = conversationFactory.startConversation(); - - // Assign the sender role to the sending test client. - Message assignSender = conversationFactory.getSession().createMessage(); - TestUtils.setPropertiesOnMessage(assignSender, testProperties); - assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignSender.setStringProperty("ROLE", "SENDER"); - assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER"); - - senderConversation.send(senderControlTopic, assignSender); - - // Wait for the sender to confirm its role. - senderConversation.receive(); - - // Assign the receivers roles. - for (TestClientDetails receiver : receivers) - { - assignReceiverRole(receiver, testProperties, true); - } - - // Start the test on the sender. - Message start = session.createMessage(); - start.setStringProperty("CONTROL_TYPE", "START"); - - senderConversation.send(senderControlTopic, start); - - // Wait for the test sender to return its report. - Message senderReport = senderConversation.receive(); - TestUtils.pause(500); - - // Ask the receivers for their reports. - Message statusRequest = session.createMessage(); - statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); - - // Gather the reports from all of the receiving clients. - - // Return all of the test reports, the senders report first. - // return new Message[] { senderReport }; - } - catch (JMSException e) - { - throw new RuntimeException("Unhandled JMSException."); - } - } - - /** - * Assigns the receivers role to the specified test client that is to act as a receivers during the test. This method - * does not always wait for the receiving clients to confirm their role assignments. This is because this method - * may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it - * is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether - * or not to wait for role confirmations. - * - * @param receiver The test client to assign the receivers role to. - * @param testProperties The test parameters. - * @param confirm Indicates whether role confirmation should be waited for. - * - * @throws JMSException Any JMSExceptions occurring during the conversation are allowed to fall through. - * - * @deprecated Scheduled for removal once existing tests converted over to use test circuits. - */ - protected void assignReceiverRole(TestClientDetails receiver, Properties testProperties, boolean confirm) - throws JMSException - { - log.info("assignReceiverRole(TestClientDetails receivers = " + receiver + ", Map testProperties = " - + testProperties + "): called"); - - ConversationFactory conversationFactory = getConversationFactory(); - - // Create a conversation with the receiving test client. - Session session = conversationFactory.getSession(); - Destination receiverControlTopic = session.createTopic(receiver.privateControlKey); - ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation(); - - // Assign the receivers role to the receiving client. - Message assignReceiver = session.createMessage(); - TestUtils.setPropertiesOnMessage(assignReceiver, testProperties); - assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignReceiver.setStringProperty("ROLE", "RECEIVER"); - assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName); - - receiverConversation.send(receiverControlTopic, assignReceiver); - - // Wait for the role confirmation to come back. - if (confirm) - { - receiverConversation.receive(); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java deleted file mode 100644 index a4c6888d68..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.log4j.Logger; - -import org.apache.qpid.junit.extensions.util.ParsedProperties; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.framework.distributedcircuit.DistributedCircuitImpl; -import org.apache.qpid.test.utils.ConversationFactory; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -/** - * InteropCircuitFactory is a circuit factory that creates distributed test circuits. Given a set of participating - * test client nodes, it assigns one node to the SENDER role and one the RECEIVER role. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Create distributed circuits from pairs of test nodes, for interop style testing. - *
- * - * @todo The partitioning of a set of nodes into sender and receiver roles is actually done by the interop test - * decorator. See the todo comment in FanOutCircuitFactory about merging the factories with the decorators, or - * more carefully dividing up responsibilities between them. - * - * @todo The squenceTest code is deprecated, but currently still used by the interop tests. It will be removed once it - * have been fully replaced by the default test procedure. - */ -public class InteropCircuitFactory extends BaseCircuitFactory -{ - /** Used for debugging. */ - private Logger log = Logger.getLogger(InteropCircuitFactory.class); - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * @return A test circuit. - */ - public Circuit createCircuit(Connection connection, ParsedProperties testProperties) - { - log.debug("public Circuit createCircuit(ParsedProperties testProperties): called"); - - List senders = new LinkedList(); - senders.add(getSender()); - List receivers = getReceivers(); - ConversationFactory conversationFactory = getConversationFactory(); - - return DistributedCircuitImpl.createCircuit(testProperties, senders, receivers, conversationFactory); - } - - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test, gathering the test reports from the participants, and checking for assertion failures against - * the test reports. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) - { - log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); - - TestClientDetails sender = getSender(); - List receivers = getReceivers(); - ConversationFactory conversationFactory = getConversationFactory(); - - try - { - Session session = conversationFactory.getSession(); - Destination senderControlTopic = session.createTopic(sender.privateControlKey); - Destination receiverControlTopic = session.createTopic(receivers.get(0).privateControlKey); - - ConversationFactory.Conversation senderConversation = conversationFactory.startConversation(); - ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation(); - - Message assignSender = conversationFactory.getSession().createMessage(); - TestUtils.setPropertiesOnMessage(assignSender, testProperties); - assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignSender.setStringProperty("ROLE", "SENDER"); - - senderConversation.send(senderControlTopic, assignSender); - - // Assign the receivers role the receiving client. - Message assignReceiver = session.createMessage(); - TestUtils.setPropertiesOnMessage(assignReceiver, testProperties); - assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignReceiver.setStringProperty("ROLE", "RECEIVER"); - - receiverConversation.send(receiverControlTopic, assignReceiver); - - // Wait for the senders and receivers to confirm their roles. - senderConversation.receive(); - receiverConversation.receive(); - - // Start the test. - Message start = session.createMessage(); - start.setStringProperty("CONTROL_TYPE", "START"); - - senderConversation.send(senderControlTopic, start); - - // Wait for the test sender to return its report. - Message senderReport = senderConversation.receive(); - TestUtils.pause(500); - - // Ask the receivers for its report. - Message statusRequest = session.createMessage(); - statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); - - receiverConversation.send(receiverControlTopic, statusRequest); - - // Wait for the receivers to send its report. - Message receiverReport = receiverConversation.receive(); - - // return new Message[] { senderReport, receiverReport }; - - // Apply assertions. - } - catch (JMSException e) - { - throw new RuntimeException("JMSException not handled."); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java index 707c4b6a47..841d0ea4ba 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java @@ -56,7 +56,6 @@ public class AcknowledgeTest extends QpidBrokerTestCase _queue = getTestQueue(); - _logger.info("AT: setup"); //Create Producer put some messages on the queue _connection = getConnection(); } @@ -70,13 +69,10 @@ public class AcknowledgeTest extends QpidBrokerTestCase // These should all end up being prefetched by session sendMessage(_consumerSession, _queue, 1); - if(!transacted) - { - ((AMQSession)_consumerSession).sync(); - } + syncIfNotTransacted(transacted); assertEquals("Wrong number of messages on queue", 1, - ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); } /** @@ -114,6 +110,7 @@ public class AcknowledgeTest extends QpidBrokerTestCase { //Send the next message _producer.send(createNextMessage(_consumerSession, count)); + syncIfNotTransacted(transacted); } doAcknowlegement(msg); @@ -128,7 +125,7 @@ public class AcknowledgeTest extends QpidBrokerTestCase } assertEquals("Wrong number of messages on queue", 0, - ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); } /** @@ -181,4 +178,11 @@ public class AcknowledgeTest extends QpidBrokerTestCase testAcking(false, AMQSession.PRE_ACKNOWLEDGE); } + private void syncIfNotTransacted(boolean transacted) throws Exception + { + if(!transacted) + { + ((AMQSession)_consumerSession).sync(); + } + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java index 8afc3f6997..a121b39a56 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java @@ -36,6 +36,7 @@ import javax.jms.Connection; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; +import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageNotReadableException; import javax.jms.MessageNotWriteableException; @@ -278,4 +279,46 @@ public class BytesMessageTest extends QpidBrokerTestCase implements MessageListe test._count = count; test.test(); } + + public void testModificationAfterSend() throws Exception + { + Connection connection = getConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + BytesMessage jmsMsg = session.createBytesMessage(); + Destination destination = getTestQueue(); + + /* Set the constant message contents. */ + + jmsMsg.setStringProperty("foo", "test"); + + /* Pre-populate the message body buffer to the target size. */ + byte[] jmsMsgBodyBuffer = new byte[1024]; + + connection.start(); + + /* Send messages. */ + MessageProducer producer = session.createProducer(destination); + + MessageConsumer consumer = session.createConsumer(destination); + + for(int writtenMsgCount = 0; writtenMsgCount < 10; writtenMsgCount++) + { + /* Set the per send message contents. */ + jmsMsgBodyBuffer[0] = (byte) writtenMsgCount; + jmsMsg.writeBytes(jmsMsgBodyBuffer, 0, jmsMsgBodyBuffer.length); + /** Try to write a message. */ + producer.send(jmsMsg); + } + + + for(int writtenMsgCount = 0; writtenMsgCount < 10; writtenMsgCount++) + { + BytesMessage recvdMsg = (BytesMessage) consumer.receive(1000L); + assertNotNull("Expected to receive message " + writtenMsgCount + " but did not", recvdMsg); + assertEquals("Message "+writtenMsgCount+" not of expected size", (long) ((writtenMsgCount + 1)*1024), + recvdMsg.getBodyLength()); + + } + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java deleted file mode 100644 index c764eda799..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.unit.basic; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Message; -import javax.jms.MessageConsumer; - -public class ReceiveTest extends QpidBrokerTestCase -{ - private AMQConnection _connection; - private AMQDestination _destination; - private AMQSession _session; - private MessageConsumer _consumer; - - protected void setUp() throws Exception - { - super.setUp(); - init((AMQConnection) getConnection("guest", "guest")); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } - - private void init(AMQConnection connection) throws Exception - { - init(connection, new AMQQueue(connection,"ReceiveTest", true)); - } - - private void init(AMQConnection connection, AMQDestination destination) throws Exception - { - _connection = connection; - _destination = destination; - _session = (AMQSession) connection.createSession(true, AMQSession.NO_ACKNOWLEDGE); - _consumer = _session.createConsumer(_destination); - _connection.start(); - } - - public void test() throws Exception - { - Message m = _consumer.receive(5000); - assertNull("should not have received a message", m); - _connection.close(); - } - - - public static junit.framework.Test suite() - { - // TODO: note that this test doesn't use the VMBrokerSetup - // test helper class to create and tear down its - // VMBroker. This is because the main() above seems to - // indicate that it's also used outside of the surefire test - // framework. If it isn't, then this test should also be - // changed to use VMBrokerSetup here. - return new junit.framework.TestSuite(ReceiveTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java index 6b83929258..5b3bca7033 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java @@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit; import org.apache.qpid.AMQConnectionClosedException; import org.apache.qpid.AMQDisconnectedException; +import org.apache.qpid.client.AMQConnection; import org.apache.qpid.management.jmx.ManagedConnectionMBeanTest; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.transport.ConnectionException; @@ -62,10 +63,13 @@ public class BrokerClosesClientConnectionTest extends QpidBrokerTestCase { final Class expectedLinkedException = isBroker010() ? ConnectionException.class : AMQConnectionClosedException.class; + assertConnectionOpen(); + stopBroker(); JMSException exception = _recordingExceptionListener.awaitException(10000); assertConnectionCloseWasReported(exception, expectedLinkedException); + assertConnectionClosed(); ensureCanCloseWithoutException(); } @@ -79,10 +83,13 @@ public class BrokerClosesClientConnectionTest extends QpidBrokerTestCase return; } + assertConnectionOpen(); + killBroker(); JMSException exception = _recordingExceptionListener.awaitException(10000); assertConnectionCloseWasReported(exception, expectedLinkedException); + assertConnectionClosed(); ensureCanCloseWithoutException(); } @@ -107,6 +114,16 @@ public class BrokerClosesClientConnectionTest extends QpidBrokerTestCase assertEquals("Unexpected linked exception", linkedExceptionClass, exception.getLinkedException().getClass()); } + private void assertConnectionClosed() + { + assertTrue("Connection should be marked as closed", ((AMQConnection)_connection).isClosed()); + } + + private void assertConnectionOpen() + { + assertFalse("Connection should not be marked as closed", ((AMQConnection)_connection).isClosed()); + } + private final class RecordingExceptionListener implements ExceptionListener { private final CountDownLatch _exceptionReceivedLatch = new CountDownLatch(1); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java deleted file mode 100644 index 4da9a1db29..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.unit.close; - -import junit.framework.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.junit.concurrency.TestRunnable; -import org.apache.qpid.junit.concurrency.ThreadTestCoordinator; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.Session; - -/** - * This test forces the situation where a session is closed whilst a message consumer is still in its onMessage method. - * Running in AUTO_ACK mode, the close call ought to wait until the onMessage method completes, and the ack is sent - * before closing the connection. - * - *

CRC Card
Responsibilities Collaborations
Check that - * closing a connection whilst handling a message, blocks till completion of the handler.
- */ -public class CloseBeforeAckTest extends QpidBrokerTestCase -{ - private static final Logger log = LoggerFactory.getLogger(CloseBeforeAckTest.class); - - private Connection connection; - private Session session; - public static final String TEST_QUEUE_NAME = "TestQueue"; - private int TEST_COUNT = 25; - - class TestThread1 extends TestRunnable implements MessageListener - { - public void runWithExceptions() throws Exception - { - // Set this up to listen for message on the test session. - session.createConsumer(session.createQueue(TEST_QUEUE_NAME)).setMessageListener(this); - } - - public void onMessage(Message message) - { - // Give thread 2 permission to close the session. - allow(new int[] { 1 }); - - // Wait until thread 2 has closed the connection, or is blocked waiting for this to complete. - waitFor(new int[] { 1 }, true); - } - } - - private TestThread1 testThread1 = new TestThread1(); - - private TestRunnable testThread2 = - new TestRunnable() - { - public void runWithExceptions() throws Exception - { - // Send a message to be picked up by thread 1. - session.createProducer(null).send(session.createQueue(TEST_QUEUE_NAME), - session.createTextMessage("Hi there thread 1!")); - - // Wait for thread 1 to pick up the message and give permission to continue. - waitFor(new int[] { 0 }, false); - - // Close the connection. - session.close(); - - // Allow thread 1 to continue to completion, if it is erronously still waiting. - allow(new int[] { 1 }); - } - }; - - public void testCloseBeforeAutoAck_QPID_397() throws Exception - { - // Create a session in auto acknowledge mode. This problem shows up in auto acknowledge if the client acks - // message at the end of the onMessage method, after a close has been sent. - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - ThreadTestCoordinator tt = new ThreadTestCoordinator(2); - - tt.addTestThread(testThread1, 0); - tt.addTestThread(testThread2, 1); - tt.setDeadlockTimeout(500); - tt.run(); - - String errorMessage = tt.joinAndRetrieveMessages(); - - // Print any error messages or exceptions. - log.debug(errorMessage); - - if (!tt.getExceptions().isEmpty()) - { - for (Exception e : tt.getExceptions()) - { - log.debug("Exception thrown during test thread: ", e); - } - } - - Assert.assertTrue(errorMessage, "".equals(errorMessage)); - } - - public void closeBeforeAutoAckManyTimes() throws Exception - { - for (int i = 0; i < TEST_COUNT; i++) - { - testCloseBeforeAutoAck_QPID_397(); - } - } - - protected void setUp() throws Exception - { - super.setUp(); - connection = getConnection("guest", "guest"); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java new file mode 100644 index 0000000000..df32bd7858 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageConsumerCloseTest.java @@ -0,0 +1,77 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.test.unit.close; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.Session; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class MessageConsumerCloseTest extends QpidBrokerTestCase +{ + Exception _exception; + + public void testConsumerCloseAndSessionRollback() throws Exception + { + Connection connection = getConnection(); + final CountDownLatch receiveLatch = new CountDownLatch(1); + final Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + Destination destination = getTestQueue(); + MessageConsumer consumer = session.createConsumer(destination); + sendMessage(session, destination, 2); + connection.start(); + consumer.setMessageListener(new MessageListener() + { + @Override + public void onMessage(Message message) + { + try + { + receiveLatch.countDown(); + session.rollback(); + } + catch (JMSException e) + { + _exception = e; + } + } + }); + boolean messageReceived = receiveLatch.await(1l, TimeUnit.SECONDS); + consumer.close(); + + assertNull("Exception occured on rollback:" + _exception, _exception); + assertTrue("Message is not received", messageReceived); + + consumer = session.createConsumer(destination); + Message message1 = consumer.receive(1000l); + assertNotNull("message1 is not received", message1); + Message message2 = consumer.receive(1000l); + assertNotNull("message2 is not received", message2); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java index 77627e2782..c292c718bb 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java @@ -379,7 +379,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase // Create durable subscriber that matches A TopicSubscriber subA = session.createDurableSubscriber(topic, - "testResubscribeWithChangedSelector", + "testResubscribeWithChangedSelectorAndRestart", "Match = True", false); // Send 1 matching message and 1 non-matching message @@ -397,8 +397,8 @@ public class DurableSubscriberTest extends QpidBrokerTestCase ((TextMessage) rMsg).getText()); // Queue has no messages left - AMQQueue subQueueTmp = new AMQQueue("amq.topic", "clientid" + ":" + "testResubscribeWithChangedSelectorAndRestart"); - assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueueTmp)); + AMQQueue subQueue = new AMQQueue("amq.topic", "clientid" + ":" + "testResubscribeWithChangedSelectorAndRestart"); + assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue, true)); rMsg = subA.receive(1000); assertNull(rMsg); @@ -423,8 +423,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase //verify no messages are now present on the queue as changing selector should have issued //an unsubscribe and thus deleted the previous durable backing queue for the subscription. //check the dur sub's underlying queue now has msg count 0 - AMQQueue subQueue = new AMQQueue("amq.topic", "clientid" + ":" + "testResubscribeWithChangedSelectorAndRestart"); - assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue)); + assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue, true)); // Check that new messages are received properly msg = session.createTextMessage("testResubscribeWithChangedSelectorAndRestart1"); @@ -444,8 +443,8 @@ public class DurableSubscriberTest extends QpidBrokerTestCase assertNull(rMsg); //check the dur sub's underlying queue now has msg count 0 - subQueue = new AMQQueue("amq.topic", "clientid" + ":" + "testResubscribeWithChangedSelectorAndRestart"); - assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue)); + assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue, true)); + conn.close(); //now restart the server try @@ -467,8 +466,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase //verify no messages now present on the queue after we restart the broker //check the dur sub's underlying queue now has msg count 0 - subQueue = new AMQQueue("amq.topic", "clientid" + ":" + "testResubscribeWithChangedSelectorAndRestart"); - assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue)); + assertEquals("Msg count should be 0", 0, ((AMQSession) session).getQueueDepth(subQueue, true)); // Reconnect with new selector that matches B TopicSubscriber subC = session.createDurableSubscriber(topic, @@ -484,8 +482,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase producer.send(msg); //check the dur sub's underlying queue now has msg count 1 - subQueue = new AMQQueue("amq.topic", "clientid" + ":" + "testResubscribeWithChangedSelectorAndRestart"); - assertEquals("Msg count should be 1", 1, ((AMQSession) session).getQueueDepth(subQueue)); + assertEquals("Msg count should be 1", 1, ((AMQSession) session).getQueueDepth(subQueue, true)); rMsg = subC.receive(1000); assertNotNull(rMsg); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java index 40c78284da..a07e531b98 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java @@ -147,7 +147,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase ((AMQSession) session2).sync(); - if(isJavaBroker() && isExternalBroker()) + if(isJavaBroker()) { //Verify that the queue was deleted by querying for its JMX MBean _jmxc = JMXConnnectionFactory.getJMXConnection(5000, "127.0.0.1", diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java index f554b0089e..cc76d89a67 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java @@ -20,6 +20,12 @@ */ package org.apache.qpid.test.unit.transacted; +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.Queue; + /** * This tests the behaviour of transactional sessions when the {@code transactionTimeout} configuration * is set for a virtual host. @@ -305,4 +311,33 @@ public class TransactionTimeoutTest extends TransactionTimeoutTestCase monitor(0, 0); } + + /** + * Tests that sending an unroutable persistent message does not result in a long running store transaction [warning]. + */ + public void testTransactionCommittedOnNonRoutableQueuePersistentMessage() throws Exception + { + checkTransactionCommittedOnNonRoutableQueueMessage(DeliveryMode.PERSISTENT); + } + + /** + * Tests that sending an unroutable transient message does not result in a long running store transaction [warning]. + */ + public void testTransactionCommittedOnNonRoutableQueueTransientMessage() throws Exception + { + checkTransactionCommittedOnNonRoutableQueueMessage(DeliveryMode.NON_PERSISTENT); + } + + private void checkTransactionCommittedOnNonRoutableQueueMessage(int deliveryMode) throws JMSException, Exception + { + Queue nonExisting = _psession.createQueue(getTestQueueName() + System.currentTimeMillis()); + MessageProducer producer = _psession.createProducer(nonExisting); + Message message = _psession.createMessage(); + producer.send(message, deliveryMode, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); + _psession.commit(); + + // give time to house keeping thread to log messages + sleep(3f); + monitor(0, 0); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java index 86ba5c2cb7..e940a73bbb 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java @@ -118,7 +118,7 @@ public class FaultTest extends AbstractXATestCase _queueFactory = getConnectionFactory(); _xaqueueConnection = _queueFactory.createXAQueueConnection("guest", "guest"); XAQueueSession session = _xaqueueConnection.createXAQueueSession(); - _queueConnection = _queueFactory.createQueueConnection(); + _queueConnection = _queueFactory.createQueueConnection("guest","guest"); _nonXASession = _queueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE); init(session, _queue); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java index eb19504dec..3fbe76323a 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java @@ -162,11 +162,12 @@ public class QueueTest extends AbstractXATestCase // create a standard session try { - _queueConnection = _queueFactory.createQueueConnection(); + _queueConnection = _queueFactory.createQueueConnection("guest", "guest"); _nonXASession = _queueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE); } catch (JMSException e) { + e.printStackTrace(); fail("cannot create queue session: " + e.getMessage()); } init(session, _queue); @@ -638,7 +639,8 @@ public class QueueTest extends AbstractXATestCase TextMessage message1 = (TextMessage) nonXAConsumer.receive(1000); if (message1 != null) { - fail("The queue is not empty! "); + + fail("The queue is not empty! " + message1.getLongProperty(_sequenceNumberPropertyName)); } } catch (JMSException e) diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java index 3a6d573205..d955979ad6 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java @@ -18,6 +18,7 @@ package org.apache.qpid.test.unit.xa; import junit.framework.TestSuite; +import org.apache.qpid.configuration.ClientProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +26,8 @@ import javax.jms.*; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -103,7 +106,7 @@ public class TopicTest extends AbstractXATestCase } catch (Exception e) { - fail("Exception thrown when cleaning standard connection: " + e.getStackTrace()); + fail("Exception thrown when cleaning standard connection: " + e); } } super.tearDown(); @@ -116,6 +119,7 @@ public class TopicTest extends AbstractXATestCase { if (!isBroker08()) { + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, "1"); // lookup test queue try { @@ -650,7 +654,12 @@ public class TopicTest extends AbstractXATestCase { message = (TextMessage) xaDurSub.receive(1000); - _logger.debug(" received message: " + message.getLongProperty(_sequenceNumberPropertyName)); + + if(message != null) + { + _logger.debug(" received message: " + message.getLongProperty(_sequenceNumberPropertyName)); + } + if (message == null) { fail("no message received! expected: " + i); @@ -882,35 +891,40 @@ public class TopicTest extends AbstractXATestCase // receive 3 message within tx1: 3, 4 and 7 _xaResource.start(xid1, XAResource.TMRESUME); // receive messages 3, 4 and 7 + Set expected = new HashSet(); + expected.add(3L); + expected.add(4L); + expected.add(7L); message = (TextMessage) xaDurSub.receive(1000); if (message == null) { - fail("no message received! expected: " + 3); + fail("no message received! expected one of: " + expected); } - else if (message.getLongProperty(_sequenceNumberPropertyName) != 3) + else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName))) { fail("wrong sequence number: " + message - .getLongProperty(_sequenceNumberPropertyName) + " 3 was expected"); + .getLongProperty(_sequenceNumberPropertyName) + " expected one from " + expected); } message = (TextMessage) xaDurSub.receive(1000); if (message == null) { - fail("no message received! expected: " + 4); + fail("no message received! expected one of: " + expected); } - else if (message.getLongProperty(_sequenceNumberPropertyName) != 4) + else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName))) { + fail("wrong sequence number: " + message - .getLongProperty(_sequenceNumberPropertyName) + " 4 was expected"); + .getLongProperty(_sequenceNumberPropertyName) + " expected one from " + expected); } message = (TextMessage) xaDurSub.receive(1000); if (message == null) { - fail("no message received! expected: " + 7); + fail("no message received! expected one of: " + expected); } - else if (message.getLongProperty(_sequenceNumberPropertyName) != 7) + else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName))) { fail("wrong sequence number: " + message - .getLongProperty(_sequenceNumberPropertyName) + " 7 was expected"); + .getLongProperty(_sequenceNumberPropertyName) + " expected one from " + expected); } } catch (Exception e) @@ -936,8 +950,18 @@ public class TopicTest extends AbstractXATestCase try { - // consume messages 1 - 4 - //----- start xid1 + // consume messages: could be any from (1 - 4, 7-10) + //----- start xid4 + Set expected = new HashSet(); + Set xid4msgs = new HashSet(); + for(long l = 1; l <= 4l; l++) + { + expected.add(l); + } + for(long l = 7; l <= 10l; l++) + { + expected.add(l); + } _xaResource.start(xid4, XAResource.TMNOFLAGS); for (int i = 1; i <= 4; i++) { @@ -946,9 +970,14 @@ public class TopicTest extends AbstractXATestCase { fail("no message received! expected: " + i); } - else if (message.getLongProperty(_sequenceNumberPropertyName) != i) + + long seqNo = message.getLongProperty(_sequenceNumberPropertyName); + xid4msgs.add(seqNo); + + if (!expected.remove(seqNo)) { - fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName)); + fail("wrong sequence number: " + seqNo + + " expected one from " + expected); } } _xaResource.end(xid4, XAResource.TMSUSPEND); @@ -961,15 +990,17 @@ public class TopicTest extends AbstractXATestCase { fail("no message received! expected: " + i); } - else if (message.getLongProperty(_sequenceNumberPropertyName) != i) + else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName))) { - fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName)); + fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName) + + " expected one from " + expected); } } _xaResource.end(xid5, XAResource.TMSUSPEND); // abort tx4 _xaResource.prepare(xid4); _xaResource.rollback(xid4); + expected.addAll(xid4msgs); // consume messages 1-4 with tx5 _xaResource.start(xid5, XAResource.TMRESUME); for (int i = 1; i <= 4; i++) @@ -979,13 +1010,15 @@ public class TopicTest extends AbstractXATestCase { fail("no message received! expected: " + i); } - else if (message.getLongProperty(_sequenceNumberPropertyName) != i) + else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName))) { - fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName)); + fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName) + + " expected one from " + expected); } } _xaResource.end(xid5, XAResource.TMSUSPEND); // commit tx5 + _xaResource.prepare(xid5); _xaResource.commit(xid5, false); } @@ -1602,6 +1635,7 @@ public class TopicTest extends AbstractXATestCase } _xaResource.end(xid2, XAResource.TMSUCCESS); _xaResource.commit(xid2, true); + _session.close(); } catch (Exception e) { diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java index 2b7c3f2664..d9c259c389 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java @@ -329,7 +329,11 @@ public class JMXTestUtils public boolean isManagedObjectExist(String query) { return !queryObjects(query).isEmpty(); + } + public int getNumberOfObjects(String query) + { + return queryObjects(query).size(); } public T getManagedObject(Class managedClass, ObjectName objectName) @@ -430,8 +434,7 @@ public class JMXTestUtils } /** - * Returns the Set of ObjectNames returned by the broker for the given query, - * or null if there is problem while performing the query. + * Returns the Set of ObjectNames returned by the broker for the given query. */ private Set queryObjects(String query) { @@ -441,8 +444,7 @@ public class JMXTestUtils } catch (Exception e) { - e.printStackTrace(); - return null; + throw new RuntimeException("Error using query: " + query, e); } } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index 32c6094adb..c070fb4de0 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -35,7 +35,8 @@ import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.ProtocolExclusion; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.store.DerbyMessageStore; +import org.apache.qpid.server.store.MessageStoreConstants; +import org.apache.qpid.server.store.derby.DerbyMessageStoreFactory; import org.apache.qpid.url.URLSyntaxException; import org.apache.qpid.util.FileUtils; import org.apache.qpid.util.LogMonitor; @@ -63,9 +64,12 @@ import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -195,6 +199,7 @@ public class QpidBrokerTestCase extends QpidTestCase return QpidBrokerTestCase._logger; } + @Override public void runBare() throws Throwable { String qname = getClass().getName() + "." + getName(); @@ -243,14 +248,7 @@ public class QpidBrokerTestCase extends QpidTestCase } finally { - try - { - stopBroker(); - } - catch (Exception e) - { - _logger.error("exception stopping broker", e); - } + stopAllBrokers(); // reset properties used in the test revertSystemProperties(); @@ -634,12 +632,21 @@ public class QpidBrokerTestCase extends QpidTestCase } } - public void stopBroker() throws Exception + public void stopBroker() { stopBroker(0); } - public void stopBroker(int port) throws Exception + public void stopAllBrokers() + { + Set runningBrokerPorts = new HashSet(getBrokerPortNumbers()); + for (int brokerPortNumber : runningBrokerPorts) + { + stopBroker(brokerPortNumber); + } + } + + public void stopBroker(int port) { if (isBrokerPresent(port)) { @@ -651,12 +658,12 @@ public class QpidBrokerTestCase extends QpidTestCase } } - public void killBroker() throws Exception + public void killBroker() { killBroker(0); } - public void killBroker(int port) throws Exception + public void killBroker(int port) { if (isBrokerPresent(port)) { @@ -668,7 +675,7 @@ public class QpidBrokerTestCase extends QpidTestCase } } - public boolean isBrokerPresent(int port) throws Exception + public boolean isBrokerPresent(int port) { port = getPort(port); @@ -681,6 +688,11 @@ public class QpidBrokerTestCase extends QpidTestCase return _brokers.get(port); } + public Set getBrokerPortNumbers() + { + return new HashSet(_brokers.keySet()); + } + /** * Attempt to set the Java Broker to use the BDBMessageStore for persistence * Falling back to the DerbyMessageStore if @@ -693,22 +705,22 @@ public class QpidBrokerTestCase extends QpidTestCase protected void makeVirtualHostPersistent(String virtualhost) throws ConfigurationException, IOException { - Class storeClass = null; + Class storeFactoryClass = null; try { // Try and lookup the BDB class - storeClass = Class.forName("org.apache.qpid.server.store.berkeleydb.BDBMessageStore"); + storeFactoryClass = Class.forName("org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory"); } catch (ClassNotFoundException e) { // No BDB store, we'll use Derby instead. - storeClass = DerbyMessageStore.class; + storeFactoryClass = DerbyMessageStoreFactory.class; } - setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store.class", - storeClass.getName()); - setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store." + DerbyMessageStore.ENVIRONMENT_PATH_PROPERTY, + setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store.factoryclass", + storeFactoryClass.getName()); + setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, "${QPID_WORK}/" + virtualhost); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java index 50b1ea7cea..787fc164d5 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java @@ -114,7 +114,7 @@ public class SpawnedBrokerHolder implements BrokerHolder } catch (ReflectionUtilsException e) { - LOGGER.warn("Could not get pid for process, Broker process shutdown will be ungraceful"); + LOGGER.warn("Could not get pid for process, Broker process shutdown will be graceful"); } } return null; diff --git a/java/test-profiles/CPPExcludes b/java/test-profiles/CPPExcludes index 14671f97af..1943049a7b 100755 --- a/java/test-profiles/CPPExcludes +++ b/java/test-profiles/CPPExcludes @@ -24,7 +24,6 @@ org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testCreateEx org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testDeleteOptions org.apache.qpid.test.unit.client.channelclose.ChannelCloseTest#* -org.apache.qpid.client.ResetMessageListenerTest#* // Those tests are testing 0.8 specific semantics org.apache.qpid.test.client.ImmediateAndMandatoryPublishingTest#* @@ -92,6 +91,7 @@ org.apache.qpid.server.store.MessageStoreTest#testQueuePersistence org.apache.qpid.server.store.MessageStoreTest#testDurableQueueRemoval org.apache.qpid.server.store.MessageStoreTest#testExchangePersistence org.apache.qpid.server.store.MessageStoreTest#testDurableExchangeRemoval +org.apache.qpid.server.store.DurableConfigurationStoreTest#* // CPP Broker does not follow the same Logging convention as the Java broker org.apache.qpid.server.BrokerStartupTest#* @@ -169,3 +169,11 @@ org.apache.qpid.server.message.MessageProtocolConversionTest#* // passwd script is a Java Broker specific command line tool org.apache.qpid.scripts.QpidPasswdTest#* + +// QPID-3604: Immediate Prefetch no longer supported by 0-10 +org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessageListener + +// QPID-3936: Exclude Performance Test Framework tests +org.apache.qpid.systest.disttest.* +org.apache.qpid.disttest.* + diff --git a/java/test-profiles/CPPPrefetchExcludes b/java/test-profiles/CPPPrefetchExcludes index 7ef52f89c7..9b4d69cebd 100644 --- a/java/test-profiles/CPPPrefetchExcludes +++ b/java/test-profiles/CPPPrefetchExcludes @@ -18,6 +18,6 @@ // // those tests should be run with prefetch off -org.apache.qpid.client.MessageListenerMultiConsumerTest#testRecieveC2Only -org.apache.qpid.client.MessageListenerMultiConsumerTest#testRecieveBoth +org.apache.qpid.client.SynchReceiveTest#testTwoConsumersInterleaved +org.apache.qpid.client.SynchReceiveTest#testIdleSecondConsumer org.apache.qpid.test.unit.xa.TopicTest#testMigrateDurableSubscriber diff --git a/java/test-profiles/Excludes b/java/test-profiles/Excludes index 8cad91ef2d..c0532e0b97 100644 --- a/java/test-profiles/Excludes +++ b/java/test-profiles/Excludes @@ -29,7 +29,5 @@ org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClo // QPID-3424 : Test fails to start external broker due to Derby Exception. org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#* -// QPID-2418 : The queue backing the dur sub is not currently deleted at subscription change, so the test will fail. -org.apache.qpid.test.unit.ct.DurableSubscriberTest#testResubscribeWithChangedSelectorAndRestart - org.apache.qpid.client.ssl.SSLTest#testVerifyLocalHostLocalDomain + diff --git a/java/test-profiles/Java010Excludes b/java/test-profiles/Java010Excludes index ac6ac8ae1c..90df1cee81 100755 --- a/java/test-profiles/Java010Excludes +++ b/java/test-profiles/Java010Excludes @@ -54,3 +54,6 @@ org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testSessionC org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#* org.apache.qpid.test.client.timeouts.SyncWaitDelayTest#* +// QPID-3604: Immediate Prefetch no longer supported by 0-10 +org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessageListener + diff --git a/java/test-profiles/JavaBDBExcludes b/java/test-profiles/JavaBDBExcludes index 3fac01cb6d..0750beb339 100644 --- a/java/test-profiles/JavaBDBExcludes +++ b/java/test-profiles/JavaBDBExcludes @@ -20,3 +20,4 @@ //This test is subclassed within the bdbstore module to enable it to run and //also add some bdb-specific tests. It is excluded to prevent running twice. org.apache.qpid.server.store.MessageStoreTest#* +org.apache.qpid.server.store.DurableConfigurationStoreTest#* diff --git a/java/test-profiles/JavaDerbyExcludes b/java/test-profiles/JavaDerbyExcludes index 931a0b0ddb..7ea00680c1 100644 --- a/java/test-profiles/JavaDerbyExcludes +++ b/java/test-profiles/JavaDerbyExcludes @@ -17,6 +17,4 @@ // under the License. // -org.apache.qpid.server.store.berkeleydb.BDBMessageStoreTest#* -org.apache.qpid.server.store.berkeleydb.BDBUpgradeTest#* -org.apache.qpid.server.store.berkeleydb.BDBBackupTest#* +org.apache.qpid.server.store.berkeleydb.* diff --git a/java/test-profiles/JavaExcludes b/java/test-profiles/JavaExcludes index e123d02918..9741eed2e9 100644 --- a/java/test-profiles/JavaExcludes +++ b/java/test-profiles/JavaExcludes @@ -28,11 +28,9 @@ org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy //Moved from JavaStandaloneExcludes when it was removed /////////////////////////////////////////////////////// -//XA functionality is not fully implemented yet -org.apache.qpid.jms.xa.XAResourceTest#* - //The Java broker doesnt support client auth org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore //QPID-3605 Durable subscriber with no-local true receives messages on re-connection org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testNoLocalMessagesNotDeliveredAfterReconnection + diff --git a/java/test-profiles/JavaPre010Excludes b/java/test-profiles/JavaPre010Excludes index ada22638be..18320646ee 100644 --- a/java/test-profiles/JavaPre010Excludes +++ b/java/test-profiles/JavaPre010Excludes @@ -26,10 +26,6 @@ org.apache.qpid.test.client.message.JMSDestinationTest#testReceiveResend org.apache.qpid.server.message.MessageProtocolConversionTest#* org.apache.qpid.server.SupportedProtocolVersionsTest#* - -// QPID-2478 test fails when run against broker using 0-8/9 -org.apache.qpid.test.client.message.JMSDestinationTest#testGetDestinationWithCustomExchange - // The new addressing based syntax is not supported for AMQP 0-8/0-9 versions org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#* org.apache.qpid.test.client.destination.AddressBasedDestinationTest#* @@ -40,7 +36,7 @@ org.apache.qpid.server.queue.AddressBasedSortedQueueTest#* // Those tests are written against the 0.10 path org.apache.qpid.test.unit.message.UTF8Test#* -org.apache.qpid.client.MessageListenerTest#testSynchronousReceiveNoWait +org.apache.qpid.client.SynchReceiveTest#testReceiveNoWait // Tests 0.10 client feature org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnsupportedSASLMechanism @@ -61,3 +57,13 @@ org.apache.qpid.test.unit.client.temporaryqueue.TemporaryQueueTest#testTemporary // QPID-3604 This fix is applied only to the 0-10 code, hence this test does not work for pre 0-10. org.apache.qpid.client.prefetch.PrefetchBehaviourTest#testConnectionStop + +//XA functionality is not implemented in pre 0-10 +org.apache.qpid.jms.xa.XAResourceTest#* + +//Tests durable subscription selector verification behaviour that 0-8/0-9/0-9-1 cant provide +org.apache.qpid.test.unit.ct.DurableSubscriberTest#testResubscribeWithChangedSelectorAndRestart + +// JCA system tests require XA support (should look to see if we can reduce scope of excludes here) +org.apache.qpid.ra.QpidRAConnectionTest#* + diff --git a/java/test-profiles/JavaTransientExcludes b/java/test-profiles/JavaTransientExcludes index 7cc541c8b9..eb4c1f814d 100644 --- a/java/test-profiles/JavaTransientExcludes +++ b/java/test-profiles/JavaTransientExcludes @@ -24,6 +24,13 @@ org.apache.qpid.test.unit.ack.ClientAcknowledgeTest#testClientAckWithLargeFlushe org.apache.qpid.test.unit.ct.DurableSubscriberTest#* +org.apache.qpid.test.unit.xa.QueueTest#testRecover +org.apache.qpid.test.unit.xa.QueueTest#testSendAndRecover +org.apache.qpid.test.unit.xa.TopicTest#testMultiMessagesDurSubCrash +org.apache.qpid.test.unit.xa.TopicTest#testDurSubCrash +org.apache.qpid.test.unit.xa.TopicTest#testRecover + + org.apache.qpid.server.store.MessageStoreTest#testMessagePersistence org.apache.qpid.server.store.MessageStoreTest#testMessageRemoval org.apache.qpid.server.store.MessageStoreTest#testBindingPersistence @@ -33,6 +40,6 @@ org.apache.qpid.server.store.MessageStoreTest#testDurableQueueRemoval org.apache.qpid.server.store.MessageStoreTest#testExchangePersistence org.apache.qpid.server.store.MessageStoreTest#testDurableExchangeRemoval -org.apache.qpid.server.store.berkeleydb.BDBMessageStoreTest#* -org.apache.qpid.server.store.berkeleydb.BDBUpgradeTest#* -org.apache.qpid.server.store.berkeleydb.BDBBackupTest#* +org.apache.qpid.server.store.berkeleydb.* + +org.apache.qpid.server.store.DurableConfigurationStoreTest#* \ No newline at end of file diff --git a/java/test-profiles/java-bdb-spawn.0-10.testprofile b/java/test-profiles/java-bdb-spawn.0-10.testprofile index cba348b67f..2cef1fd53e 100644 --- a/java/test-profiles/java-bdb-spawn.0-10.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-10.testprofile @@ -23,7 +23,7 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test- broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-bdb-spawn.0-8.testprofile b/java/test-profiles/java-bdb-spawn.0-8.testprofile index f9837cc4f3..62c9385835 100644 --- a/java/test-profiles/java-bdb-spawn.0-8.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-8.testprofile @@ -23,11 +23,11 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore -profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT broker.version=v0_8 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile index b04fea21b6..cfc2a12dde 100644 --- a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile @@ -23,11 +23,11 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore -profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT broker.version=v0_9_1 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb-spawn.0-9.testprofile b/java/test-profiles/java-bdb-spawn.0-9.testprofile index 03082b6f19..9cfa25eb9a 100644 --- a/java/test-profiles/java-bdb-spawn.0-9.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-9.testprofile @@ -23,11 +23,11 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore -profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT broker.version=v0_9 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb.0-10.testprofile b/java/test-profiles/java-bdb.0-10.testprofile index 3ef93a68cb..4ac4c3baf2 100644 --- a/java/test-profiles/java-bdb.0-10.testprofile +++ b/java/test-profiles/java-bdb.0-10.testprofile @@ -24,7 +24,7 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test- broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-bdb.0-8.testprofile b/java/test-profiles/java-bdb.0-8.testprofile index ba6cc0fa80..76c3ea0b72 100644 --- a/java/test-profiles/java-bdb.0-8.testprofile +++ b/java/test-profiles/java-bdb.0-8.testprofile @@ -24,11 +24,11 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore -profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT broker.version=v0_8 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb.0-9-1.testprofile b/java/test-profiles/java-bdb.0-9-1.testprofile index 101d38f4b9..afc5f7bfd1 100644 --- a/java/test-profiles/java-bdb.0-9-1.testprofile +++ b/java/test-profiles/java-bdb.0-9-1.testprofile @@ -24,11 +24,11 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore -profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT broker.version=v0_9_1 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb.0-9.testprofile b/java/test-profiles/java-bdb.0-9.testprofile index daa61253bb..76bde0defc 100644 --- a/java/test-profiles/java-bdb.0-9.testprofile +++ b/java/test-profiles/java-bdb.0-9.testprofile @@ -24,11 +24,11 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore -profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes +messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT broker.version=v0_9 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-dby-spawn.0-10.testprofile b/java/test-profiles/java-dby-spawn.0-10.testprofile index 5bd6f330d5..3b57dca346 100644 --- a/java/test-profiles/java-dby-spawn.0-10.testprofile +++ b/java/test-profiles/java-dby-spawn.0-10.testprofile @@ -23,7 +23,7 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test- broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-dby-spawn.0-8.testprofile b/java/test-profiles/java-dby-spawn.0-8.testprofile index c186207f6a..9d421f706e 100644 --- a/java/test-profiles/java-dby-spawn.0-8.testprofile +++ b/java/test-profiles/java-dby-spawn.0-8.testprofile @@ -23,9 +23,9 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore -profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true # diff --git a/java/test-profiles/java-dby-spawn.0-9-1.testprofile b/java/test-profiles/java-dby-spawn.0-9-1.testprofile index e7212d30f8..3038dd324e 100644 --- a/java/test-profiles/java-dby-spawn.0-9-1.testprofile +++ b/java/test-profiles/java-dby-spawn.0-9-1.testprofile @@ -23,9 +23,9 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore -profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true # diff --git a/java/test-profiles/java-dby-spawn.0-9.testprofile b/java/test-profiles/java-dby-spawn.0-9.testprofile index bd5df9ee82..6007105097 100644 --- a/java/test-profiles/java-dby-spawn.0-9.testprofile +++ b/java/test-profiles/java-dby-spawn.0-9.testprofile @@ -23,9 +23,9 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore -profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true # diff --git a/java/test-profiles/java-dby.0-10.testprofile b/java/test-profiles/java-dby.0-10.testprofile index 9c23d18f45..51f6c4ca6f 100644 --- a/java/test-profiles/java-dby.0-10.testprofile +++ b/java/test-profiles/java-dby.0-10.testprofile @@ -24,7 +24,7 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test- broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-dby.0-8.testprofile b/java/test-profiles/java-dby.0-8.testprofile index e4e00c70c2..c841c69922 100644 --- a/java/test-profiles/java-dby.0-8.testprofile +++ b/java/test-profiles/java-dby.0-8.testprofile @@ -24,9 +24,9 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore -profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true # diff --git a/java/test-profiles/java-dby.0-9-1.testprofile b/java/test-profiles/java-dby.0-9-1.testprofile index 83f43d8dbf..fa01010d52 100644 --- a/java/test-profiles/java-dby.0-9-1.testprofile +++ b/java/test-profiles/java-dby.0-9-1.testprofile @@ -24,9 +24,9 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore -profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true # diff --git a/java/test-profiles/java-dby.0-9.testprofile b/java/test-profiles/java-dby.0-9.testprofile index b6d1840f9f..d343185591 100644 --- a/java/test-profiles/java-dby.0-9.testprofile +++ b/java/test-profiles/java-dby.0-9.testprofile @@ -24,9 +24,9 @@ broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FIL broker.ready=BRK-1004 broker.stopped=Exception broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT -messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore -profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true # diff --git a/java/test-profiles/java-mms-spawn.0-8.testprofile b/java/test-profiles/java-mms-spawn.0-8.testprofile index e46823c3f1..1b6b6f28a3 100644 --- a/java/test-profiles/java-mms-spawn.0-8.testprofile +++ b/java/test-profiles/java-mms-spawn.0-8.testprofile @@ -22,9 +22,9 @@ broker.type=spawned broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 -profile.excludes=JavaTransientExcludes JavaPre010Excludes +profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes diff --git a/java/test-profiles/java-mms-spawn.0-9-1.testprofile b/java/test-profiles/java-mms-spawn.0-9-1.testprofile index 05b1f89452..e87ae2b204 100644 --- a/java/test-profiles/java-mms-spawn.0-9-1.testprofile +++ b/java/test-profiles/java-mms-spawn.0-9-1.testprofile @@ -22,9 +22,9 @@ broker.type=spawned broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 -profile.excludes=JavaTransientExcludes JavaPre010Excludes +profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes diff --git a/java/test-profiles/java-mms-spawn.0-9.testprofile b/java/test-profiles/java-mms-spawn.0-9.testprofile index d53a9f42ad..2a9430242e 100644 --- a/java/test-profiles/java-mms-spawn.0-9.testprofile +++ b/java/test-profiles/java-mms-spawn.0-9.testprofile @@ -22,9 +22,9 @@ broker.type=spawned broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 -profile.excludes=JavaTransientExcludes JavaPre010Excludes +profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes diff --git a/java/test-profiles/java-mms.0-8.testprofile b/java/test-profiles/java-mms.0-8.testprofile index 02723ab180..1f02a49b28 100644 --- a/java/test-profiles/java-mms.0-8.testprofile +++ b/java/test-profiles/java-mms.0-8.testprofile @@ -23,9 +23,9 @@ broker.type=internal broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 -profile.excludes=JavaTransientExcludes JavaPre010Excludes +profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes diff --git a/java/test-profiles/java-mms.0-9-1.testprofile b/java/test-profiles/java-mms.0-9-1.testprofile index 37efa097bb..ae707f025d 100644 --- a/java/test-profiles/java-mms.0-9-1.testprofile +++ b/java/test-profiles/java-mms.0-9-1.testprofile @@ -23,9 +23,9 @@ broker.type=internal broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 -profile.excludes=JavaTransientExcludes JavaPre010Excludes +profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes diff --git a/java/test-profiles/java-mms.0-9.testprofile b/java/test-profiles/java-mms.0-9.testprofile index 36ee470e09..8f372299ea 100644 --- a/java/test-profiles/java-mms.0-9.testprofile +++ b/java/test-profiles/java-mms.0-9.testprofile @@ -23,9 +23,9 @@ broker.type=internal broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 -profile.excludes=JavaTransientExcludes JavaPre010Excludes +profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes diff --git a/java/test-profiles/python_tests/Java010PythonExcludes b/java/test-profiles/python_tests/Java010PythonExcludes index 52afb66890..13f9d5484e 100644 --- a/java/test-profiles/python_tests/Java010PythonExcludes +++ b/java/test-profiles/python_tests/Java010PythonExcludes @@ -19,15 +19,14 @@ ###### Feature not supported in Java Broker ###### -#The broker does not support DTX -qpid_tests.broker_0_10.dtx.* - -#The broker does not support message groups -qpid_tests.broker_0_10.msg_groups.* - #The broker does not have the appropriate QMF support qpid_tests.broker_0_10.management.* qpid_tests.broker_0_10.stats.BrokerStatsTests.* +qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_default_group_id +qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_move_* +qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_purge_* +qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_query +qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_reroute #The broker does not use the same threshold alerting system (or the QMF support needed for the tests) qpid_tests.broker_0_10.threshold.* @@ -51,14 +50,12 @@ qpid_tests.broker_0_10.message.MessageTests.test_ack qpid_tests.broker_0_10.message.MessageTests.test_acquire qpid_tests.broker_0_10.message.MessageTests.test_acquire_with_no_accept_and_credit_flow -#QPID-3588 Java broker sets expiration and doesnt pass TTL on to consumer -qpid.tests.messaging.message.MessageEchoTests.testProperties - -#QPID-3589 Difference in exception text message causes test to fail -qpid.tests.messaging.endpoints.AddressTests.testDeleteSpecial - -#QPID-3590 Java broker does not support null value for routing key -qpid.tests.messaging.endpoints.SessionTests.testDoubleCommit +qpid_tests.broker_0_10.dtx.DtxTests.test_forget_xid_on_completion +qpid_tests.broker_0_10.dtx.DtxTests.test_implicit_end +qpid_tests.broker_0_10.dtx.DtxTests.test_simple_commit +qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_commit +qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_rollback +qpid_tests.broker_0_10.dtx.DtxTests.test_simple_rollback ###### Java Broker defects ###### @@ -70,37 +67,3 @@ qpid_tests.broker_0_10.message.MessageTests.test_window_flow_bytes #QPID-3605 Durable subscriber with no-local true receives messages on re-connection qpid_tests.broker_0_10.message.MessageTests.test_no_local_awkward -#QPID-3594 exclusive queues problem -qpid_tests.broker_0_10.queue.QueueTests.test_declare_exclusive - -#QPID-3477: Java broker does not handle rejection code specified in test -qpid.tests.messaging.endpoints.SessionTests.testReject - -#QPID-3595 Alternate Exchanges support requires work to be spec compliant. -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_delete_while_used_by_queue -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_modify_existing_exchange_alternate -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_autodelete -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_delete -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_delete_loop -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_delete_no_match -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_reject_no_match -qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_add_alternate_to_exchange -qpid_tests.broker_0_10.new_api.GeneralTests.test_qpid_3481_acquired_to_alt_exchange - -#QPID-3596 Broker does not validate for reserved exchange names on create/bind. -qpid_tests.broker_0_10.exchange.DeclareMethodExchangeFieldReservedRuleTests.* - -#QPID-3597 Headers exchange issues -qpid_tests.broker_0_10.exchange.HeadersExchangeTests.* -qpid_tests.broker_0_10.queue.QueueTests.test_unbind_headers -qpid_tests.broker_0_10.exchange.RecommendedTypesRuleTests.testHeaders -qpid_tests.broker_0_10.exchange.RequiredInstancesRuleTests.testAmqMatch -qpid_tests.broker_0_10.query.QueryTests.test_exchange_bound_header - -#QPID-3598 Fanout exchange issues -qpid_tests.broker_0_10.query.QueryTests.test_exchange_bound_fanout - -#QPID-3599 Tests fail due to differences in expected message Redelivered status -qpid.tests.messaging.endpoints.SessionTests.testCommitAck -qpid.tests.messaging.endpoints.SessionTests.testRelease -qpid.tests.messaging.endpoints.SessionTests.testRollback diff --git a/java/test-profiles/testprofile.defaults b/java/test-profiles/testprofile.defaults index bd2faa7915..2c3c92e922 100644 --- a/java/test-profiles/testprofile.defaults +++ b/java/test-profiles/testprofile.defaults @@ -21,7 +21,7 @@ java.naming.provider.url=${test.profiles}/test-provider.properties broker.ready=Listening on TCP broker.config=build/etc/config-systests.xml -messagestore.class.name=org.apache.qpid.server.store.MemoryMessageStore +messagestorefactory.class.name=org.apache.qpid.server.store.MemoryMessageStoreFactory broker.protocol.excludes= broker.persistent=false @@ -47,7 +47,7 @@ test.port.alt.ssl=25671 test.exclude=true profile.excludes= -test.excludes=Excludes XAExcludes JavaExcludes ${profile}.excludes ${profile.excludes} +test.excludes=Excludes JavaExcludes ${profile}.excludes ${profile.excludes} test.mem=512M test=*Test haltonfailure=no diff --git a/java/testkit/README.txt b/java/testkit/README.txt deleted file mode 100644 index df7996f471..0000000000 --- a/java/testkit/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -Introduction -============ - -The Test kit for the JMS client is based on a multi-broker python framework. -So far it could only be used with the c++ broker. - diff --git a/java/testkit/bin/run_soak_client.sh b/java/testkit/bin/run_soak_client.sh deleted file mode 100644 index ea1721d988..0000000000 --- a/java/testkit/bin/run_soak_client.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# This is a sample script for a soak test on -# linux environment. -# This will start n of Producers processors and record their CPU and memory stats. -# Also the Producer out will be saved to a file as well. - -if [ "$JAR_PATH" = "" ] ; then - echo "ERROR: Please set JAR_PATH to point to the Qpid libraries ...." - exit 1 -fi - -#1 PID, $2 freq, $3 count -calc_stats(){ - -for (( i = 0 ; i <= $3; i++ )) - do - cpu=`ps auxw | grep $1 | grep -v 'grep' | awk '{print $3}'` - mem=`pmap $1 | grep total | grep -v 'grep' | awk '{print substr($2,0,length($2)-1)}'` - echo $i","$mem","$cpu - sleep $2 - cpu="0.0" - mem="0" - done - kill -9 $1 -} - -# Num of producer processors to start -num=$1 -# Log frequency in seconds -log_freq=$2 -# Num of iterations -log_iter=$3 - -class_name=$4 -log_file_name=`echo $class_name | cut -d. -f6` - -# The total time for the test is determined by the -# log_freq * log_iter. - -shift 4 -CLASSPATH=`find $JAR_PATH -name '*.jar' | tr '\n' ":"` - -JVM_ARGS="-Xmx1500M $@" -echo "Starting $log_file_name with the following params $JVM_ARGS" - -for (( c = 1 ; c <= $num; c++ )) -do - $JAVA_HOME/bin/java $JVM_ARGS -cp $CLASSPATH $class_name > ${log_file_name}_${c}.log & - pid=`jobs -l %% | awk '{print $2}'` - calc_stats $pid $log_freq $log_iter > ${log_file_name}_process_${c}.log & -done diff --git a/java/testkit/bin/soak_report.sh b/java/testkit/bin/soak_report.sh deleted file mode 100644 index 9da8bfa234..0000000000 --- a/java/testkit/bin/soak_report.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Sample script to run a soak test with MultiThreadedProducer/Consumer. -# You need to provide the log freq and no of iterations -# Ex to run 10 hours and collect 1 second samples -# soak_report.sh 1 36000 - -# This script assumes that a suitable broker instance is started. - -log_freq=$1 -log_iter=$2 -shift 2 -JVM_ARGS=$@ - -if [ "$QPID_TEST_HOME" = "" ] ; then - echo "ERROR: Please set QPID_TEST_HOME ...." - exit 1 -fi - -print_rates() -{ - cat $1 | awk '{ - FS = ","; - count = 0; - total_latency = 0; - min_latency = 9223372036854775807; - max_latency = 0; - - total_tp = 0; - min_tp = 50000; - max_tp = 0; - - while ((getline) == 1) - { - total_latency = total_latency + $3 - total_tp = total_tp + $2 - - if ($3 > 0) - { - min_latency = (($3 < min_latency) ? $3 : min_latency); - max_latency = (($3 > max_latency) ? $3 : max_latency); - } - if ($2 > 0) - { - min_tp = (($2 < min_tp) ? $2 : min_tp); - max_tp = (($2 > max_tp) ? $2 : max_tp); - } - - count = count + 1 - } - - print "Avg Latency (ms) : " total_latency/count - print "Max Latency (ms) : " max_latency - print "Min Latency (ms) : " min_latency - - print "" - print "Avg Throughput (msg/sec) : " total_tp/count - print "Max Throughput (msg/sec) : " max_tp - print "Min Throughput (msg/sec) : " min_tp - - print "" - print "Total Iteratons " count - - }' -} - -print_system_stats() -{ - cat $1 | awk '{ - FS = ","; - count = 0; - total_memory = 0; - min_memory = 9223372036854775807; - max_memory = 0; - - total_cp = 0; - min_cp = 50000; - max_cp = 0; - - while ((getline) == 1) - { - total_memory = total_memory + $2 - total_cp = total_cp + $3 - - if ($2 > 0) - { - min_memory = (($2 < min_memory) ? $2 : min_memory); - max_memory = (($2 > max_memory) ? $2 : max_memory); - } - if ($3 > 0) - { - min_cp = (($3 < min_cp) ? $3 : min_cp); - max_cp = (($3 > max_cp) ? $3 : max_cp); - } - - count = count + 1 - } - - print "Avg Memory (MB) : " total_memory/(count*1024) - print "Max Memory (MB) : " max_memory/1024 - print "Min Memory (MB) : " min_memory/1024 - - print "" - print "Avg CPU : " total_cp/count - print "Max CPU : " max_cp - print "Min CPU : " min_cp - - print "" - print "Total Iteratons " count - - }' -} - - -cleanup() -{ - kill -9 `ps aux | grep java | grep soak | awk '{ print $2 }'` -} - -print_results() -{ - printf "\n======================================================= \n" - print_rates MultiThreadedConsumer_1.log - printf "\nConsumer process stats " - printf "\n----------------------- \n" - print_system_stats MultiThreadedConsumer_process_1.log - printf "\nProducer process stats " - printf "\n----------------------- \n" - print_system_stats MultiThreadedProducer_process_1.log - printf "\n------------------------------------------------------- \n" -} - -trap cleanup EXIT - -# runs a single instance of the MultiThreadedConsumer and MultiThreadedProducer -sh $QPID_TEST_HOME/bin/run_soak_client.sh 1 $log_freq $log_iter org.apache.qpid.testkit.soak.MultiThreadedConsumer $JVM_ARGS -sh $QPID_TEST_HOME/bin/run_soak_client.sh 1 $log_freq $log_iter org.apache.qpid.testkit.soak.MultiThreadedProducer $JVM_ARGS - -sleep_time=$((log_freq * log_iter)) -echo "sleep time : " $sleep_time -sleep $((log_freq * log_iter)) - -print_results diff --git a/java/testkit/build.xml b/java/testkit/build.xml deleted file mode 100644 index 80a3373379..0000000000 --- a/java/testkit/build.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java deleted file mode 100644 index c240ecdf2e..0000000000 --- a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.testkit.soak; - - -import java.util.Random; - -import javax.jms.BytesMessage; -import javax.jms.Destination; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.BasicMessageConsumer; -import org.apache.qpid.client.BasicMessageProducer; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.testkit.TestLauncher; -import org.apache.qpid.thread.Threading; - -/** - * Test Description - * ================ - * This test will open x number of connections where each - * connection will create a session and a producer/consumer pair, - * and then a randomly selected set of connections (about 1/4th) - * will send a configurable no of messages and try to receive them. - * It will then sleep for configurable time interval and - * tear down the connections/sessions/consumers. - * It will then repeat the process again until the test is stopped. - * - * Purpose of the test - * =================== - * To find if the broker has leaks when cleaning resources. - * To find if the client has leaks with resources. - */ -public class ResourceLeakTest extends TestLauncher -{ - /* protected long connection_idle_time = 5000; - protected Random rand = new Random(); - - public ResourceLeakTest() - { - super(); - } - - public void test() - { - try - { - - AMQConnection[] cons = new AMQConnection[connection_count]; - Session[] sessions = new Session[connection_count]; - MessageConsumer[] msgCons = new MessageConsumer[connection_count]; - MessageProducer [] msgProds = new MessageProducer[connection_count]; - - while (true) - { - for (int i = 0; i < connection_count; i++) - { - AMQConnection con = new AMQConnection(url); - con.start(); - cons[i] = con; - Session ssn = con.createSession(false, Session.AUTO_ACKNOWLEDGE); - sessions[i] = ssn; - Destination dest = new AMQQueue(new AMQShortString(exchange_name), - new AMQShortString(routing_key + i), - new AMQShortString(queue_name + i), - true, //exclusive - true // auto delete - ); - MessageConsumer msgCon = ssn.createConsumer(dest); - msgCons[i] = msgCon; - MessageProducer msgProd = ssn.createProducer(dest); - msgProds[i] = msgProd; - } - - // Select some connections randomly and send/recv messages - // Exercise around quarter of the connections - for (int i=0; i < connection_count/4; i++) - { - int k = rand.nextInt(connection_count); - - BytesMessage msg = sessions[k].createBytesMessage(); - msg.writeBytes("Test Msg".getBytes()); - - for (int j = 0; j < msg_count;j++) - { - msgProds[k].send(msg); - } - - int j = 0; - while (j < msg_count) - { - msgCons[k].receive(); - j++; - } - } - System.out.println(df.format(System.currentTimeMillis())); - Thread.sleep(connection_idle_time); - - try - { - for (int i = 0; i < connection_count; i++) - { - if (!((BasicMessageConsumer)msgCons[i]).isClosed()) - { - msgCons[i].close(); - } - - if (!((BasicMessageProducer)msgProds[i]).isClosed()) - { - msgProds[i].close(); - } - - if (!((AMQSession)sessions[i]).isClosed()) - { - sessions[i].close(); - } - if (!((AMQConnection)cons[i]).isClosed()) - { - cons[i].close(); - } - } - } - catch (Exception e) - { - handleError(e,"Exception closing resources"); - } - } - } - catch (Exception e) - { - handleError(e,"Exception in setting up the test"); - } - - } - - public static void main(String[] args) - { - final ResourceLeakTest test = new ResourceLeakTest(); - Runnable r = new Runnable(){ - public void run() - { - test.test(); - } - }; - - Thread t; - try - { - t = Threading.getThreadFactory().createThread(r); - } - catch(Exception e) - { - throw new Error("Error creating test thread",e); - } - }*/ - -} diff --git a/java/tools/bin/controller b/java/tools/bin/controller deleted file mode 100644 index fab8614039..0000000000 --- a/java/tools/bin/controller +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# This starts the controller for coordinating perf tests/ - -. check-qpid-java-env - -PROGRAM_NAME=controller -CONSUMER_COUNT=1 -PRODUCER_COUNT=1 -DURATION=-1 -TEST_NAME="TEST_NAME" -EXTRA_JVM_ARGS="" - -TEMP=$(getopt -n $PROGRAM_NAME -o c:p:d:n:a:h --long consumers:,producers:,jvm-args:help -- "$@") - -usage() -{ - printf "\n%s\n" "Usage: controller [option].." - - printf "\n%31s\n%52s\n" "-c, --consumer-count=count" "No of consumers participating in the test" - - printf "\n%31s\n%52s\n" "-p, --producer-count=count" "No of producers participating in the test" - - printf "\n%24s\n%94s\n" "-d, --duration=mins" "The duration of the test in mins. If not specified, it will just run one iteration." - - printf "\n%27s\n%32s\n" "-n, --name=" "The name of the test." - - printf "\n%19s\n%50s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify" -} - -eval set -- "$TEMP" -while true; do - case $1 in - -c|--consumer-count) - CONSUMER_COUNT="$2"; shift; shift; continue - ;; - -p|--producer-count) - PRODUCER_COUNT="$2"; shift; shift; continue - ;; - -d|--duration) - DURATION="$2"; shift; shift; continue - ;; - -n|--name) - TEST_NAME="$2"; shift; shift; continue - ;; - -h|--help) - usage - exit 0 - ;; - -a|--jvm-args) - EXTRA_JVM_ARGS="$2"; shift; shift; continue - ;; - --) - # no more arguments to parse - break - ;; - *) - # no more arguments to parse - break - ;; - esac -done - -CONTROLLER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dprecision=mili -Dprod_count=$PRODUCER_COUNT -Dcons_count=$CONSUMER_COUNT -Dprint_std_dev=true -Dduration=${DURATION}" - - -waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; } -cleanup() -{ - pids=`ps aux | grep java | grep PerfTestController | awk '{print $2}'` - if [ "$pids" != "" ]; then - kill -3 $pids - kill -9 $pids >/dev/null 2>&1 - fi -} - -run_controller() -{ - TEST_ARGS="$LOG_CONFIG $JAVA_MEM $CONTROLLER_ARGS $EXTRA_JVM_ARGS" - echo "Running controller with : $TEST_ARGS" > test.out - $JAVA -cp $CLASSPATH $TEST_ARGS org.apache.qpid.tools.PerfTestController >> test.out & - waitfor test.out "Controller: Completed the test" - sleep 2 #give a grace period to shutdown - print_result $TEST_NAME -} - -print_result() -{ - prod_rate=`cat test.out | grep "Avg Producer rate" | awk '{print $5}'` - sys_rate=`cat test.out | grep "System Throughput" | awk '{print $4}'` - cons_rate=`cat test.out | grep "Avg Consumer rate" | awk '{print $5}'` - avg_latency=`cat test.out | grep "Avg System Latency" | awk '{print $5}'` - min_latency=`cat test.out | grep "Min System Latency" | awk '{print $5}'` - max_latency=`cat test.out | grep "Max System Latency" | awk '{print $5}'` - std_dev=`cat test.out | grep "Avg System Std Dev" | awk '{print $6}'` - - printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11.2f|%11.2f|%7.2f|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency $std_dev - echo "--------------------------------------------------------------------------------------------------------" -} - -trap cleanup EXIT - -rm -rf *.out - -if [ "$DURATION" = -1 ]; then - echo "Test report on " `date +%F` - echo "========================================================================================================" - echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|Std Dev|" - echo "--------------------------------------------------------------------------------------------------------" -else - echo "Test in progress....Tail stats-csv.log to see results being printed for each iteration." -fi - -run_controller diff --git a/java/tools/bin/jms-quick-perf-report b/java/tools/bin/jms-quick-perf-report new file mode 100755 index 0000000000..7de3f2b602 --- /dev/null +++ b/java/tools/bin/jms-quick-perf-report @@ -0,0 +1,137 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# This will run the following test cases defined below and produce +# a report in tabular format. + +QUEUE="queue;{create:always,node:{x-declare:{auto-delete:true}}}" +DURA_QUEUE="dqueue;{create:always,node:{durable:true,x-declare:{auto-delete:true}}}" +TOPIC="amq.topic/test" +DURA_TOPIC="amq.topic/test;{create:always,link:{durable:true}}" + +COMMON_CONFIG="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'" + +waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; } +cleanup() +{ + pids=`ps aux | grep java | grep Perf | awk '{print $2}'` + if [ "$pids" != "" ]; then + kill -3 $pids + kill -9 $pids >/dev/null 2>&1 + fi +} + +# $1 test name +# $2 consumer options +# $3 producer options +run_testcase() +{ + sh run-sub $COMMON_CONFIG $2 > sub.out & + sh run-pub $COMMON_CONFIG $3 > pub.out & + waitfor pub.out "Controller: Completed the test" + sleep 2 #give a grace period to shutdown + print_result $1 + mv pub.out $1.pub.out + mv sub.out $1.sub.out +} + +print_result() +{ + prod_rate=`cat pub.out | grep "Avg Producer rate" | awk '{print $5}'` + sys_rate=`cat pub.out | grep "System Throughput" | awk '{print $4}'` + cons_rate=`cat pub.out | grep "Avg Consumer rate" | awk '{print $5}'` + avg_latency=`cat pub.out | grep "Avg System Latency" | awk '{print $5}'` + min_latency=`cat pub.out | grep "Min System Latency" | awk '{print $5}'` + max_latency=`cat pub.out | grep "Max System Latency" | awk '{print $5}'` + + printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11.2f|%11.2f|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency + echo "------------------------------------------------------------------------------------------------" +} + +trap cleanup EXIT +rm -rf *.out #cleanup old files. + +echo "Test report on " `date +%F` +echo "================================================================================================" +echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|" +echo "------------------------------------------------------------------------------------------------" + +# The message counts and warmup counts are set to very low values for quick testing of the script. +# For a real performance run I recommend setting warmup count to 10k and message count in excess of 100k +# However for transactions, sync_publish and especially small durable transactions (which is quite slow) I recommend +# setting very low values to start with and experiment while increasing them slowly. + +# Test 1 Trans Queue +run_testcase "Trans_Queue" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dwarmup_count=1 -Dmsg_count=10" + +# Test 2 Dura Queue +run_testcase "Dura_Queue" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" + +# Test 3 Dura Queue Sync +run_testcase "Dura_Queue_Sync" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent" + +# Test 4 Dura Queue Sync Publish and Ack +run_testcase "Dura_SyncPubAck" "-Daddress=$DURA_QUEUE -Ddurable=true -Dsync_ack=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent" + +# Test 5 Topic +run_testcase "Topic" "-Daddress=$TOPIC" "-Daddress=$TOPIC -Dwarmup_count=1 -Dmsg_count=10" + +# Test 6 Durable Topic +run_testcase "Dura_Topic" "-Daddress=$DURA_TOPIC -Ddurable=true" "-Daddress=$DURA_TOPIC -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" + +# Test 7 Fanout +run_testcase "Fanout" "-Daddress=amq.fanout" "-Daddress=amq.fanout -Dwarmup_count=1 -Dmsg_count=10" + +# Test 8 Small TX +run_testcase "Small_Txs_2" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=1" \ + "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=1" + +# Test 9 Large TX +run_testcase "Large_Txs_1000" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=10" \ + "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=10" + +# Test 10 256 MSG +run_testcase "Msg_256b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=256 -Dwarmup_count=1 -Dmsg_count=10" + +# Test 11 512 MSG +run_testcase "Msg_512b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=512 -Dwarmup_count=1 -Dmsg_count=10" + +# Test 12 2048 MSG +run_testcase "Msg_2048b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=2048 -Dwarmup_count=1 -Dmsg_count=10" + +# Test 13 Random size MSG +run_testcase "Random_Msg_Size" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10" + +# Test 14 Random size MSG Durable +run_testcase "Rand_Msg_Dura" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10" + +# Test 15 64K MSG +run_testcase "Msg_64K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Dwarmup_count=1 -Dmsg_count=10" + +# Test 16 Durable 64K MSG +run_testcase "Msg_Durable_64K" "-Daddress=$DURA_QUEUE -Ddurable=true -Damqj.tcpNoDelay=true" \ + "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" + +# Test 17 500K MSG +run_testcase "Msg_500K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Dwarmup_count=1 -Dmsg_count=10" + +# Test 18 Durable 500K MSG +run_testcase "Msg_Dura_500K" "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Ddurable=true" \ + "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" diff --git a/java/tools/bin/mercury-controller b/java/tools/bin/mercury-controller new file mode 100644 index 0000000000..fab8614039 --- /dev/null +++ b/java/tools/bin/mercury-controller @@ -0,0 +1,132 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# This starts the controller for coordinating perf tests/ + +. check-qpid-java-env + +PROGRAM_NAME=controller +CONSUMER_COUNT=1 +PRODUCER_COUNT=1 +DURATION=-1 +TEST_NAME="TEST_NAME" +EXTRA_JVM_ARGS="" + +TEMP=$(getopt -n $PROGRAM_NAME -o c:p:d:n:a:h --long consumers:,producers:,jvm-args:help -- "$@") + +usage() +{ + printf "\n%s\n" "Usage: controller [option].." + + printf "\n%31s\n%52s\n" "-c, --consumer-count=count" "No of consumers participating in the test" + + printf "\n%31s\n%52s\n" "-p, --producer-count=count" "No of producers participating in the test" + + printf "\n%24s\n%94s\n" "-d, --duration=mins" "The duration of the test in mins. If not specified, it will just run one iteration." + + printf "\n%27s\n%32s\n" "-n, --name=" "The name of the test." + + printf "\n%19s\n%50s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify" +} + +eval set -- "$TEMP" +while true; do + case $1 in + -c|--consumer-count) + CONSUMER_COUNT="$2"; shift; shift; continue + ;; + -p|--producer-count) + PRODUCER_COUNT="$2"; shift; shift; continue + ;; + -d|--duration) + DURATION="$2"; shift; shift; continue + ;; + -n|--name) + TEST_NAME="$2"; shift; shift; continue + ;; + -h|--help) + usage + exit 0 + ;; + -a|--jvm-args) + EXTRA_JVM_ARGS="$2"; shift; shift; continue + ;; + --) + # no more arguments to parse + break + ;; + *) + # no more arguments to parse + break + ;; + esac +done + +CONTROLLER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dprecision=mili -Dprod_count=$PRODUCER_COUNT -Dcons_count=$CONSUMER_COUNT -Dprint_std_dev=true -Dduration=${DURATION}" + + +waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; } +cleanup() +{ + pids=`ps aux | grep java | grep PerfTestController | awk '{print $2}'` + if [ "$pids" != "" ]; then + kill -3 $pids + kill -9 $pids >/dev/null 2>&1 + fi +} + +run_controller() +{ + TEST_ARGS="$LOG_CONFIG $JAVA_MEM $CONTROLLER_ARGS $EXTRA_JVM_ARGS" + echo "Running controller with : $TEST_ARGS" > test.out + $JAVA -cp $CLASSPATH $TEST_ARGS org.apache.qpid.tools.PerfTestController >> test.out & + waitfor test.out "Controller: Completed the test" + sleep 2 #give a grace period to shutdown + print_result $TEST_NAME +} + +print_result() +{ + prod_rate=`cat test.out | grep "Avg Producer rate" | awk '{print $5}'` + sys_rate=`cat test.out | grep "System Throughput" | awk '{print $4}'` + cons_rate=`cat test.out | grep "Avg Consumer rate" | awk '{print $5}'` + avg_latency=`cat test.out | grep "Avg System Latency" | awk '{print $5}'` + min_latency=`cat test.out | grep "Min System Latency" | awk '{print $5}'` + max_latency=`cat test.out | grep "Max System Latency" | awk '{print $5}'` + std_dev=`cat test.out | grep "Avg System Std Dev" | awk '{print $6}'` + + printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11.2f|%11.2f|%7.2f|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency $std_dev + echo "--------------------------------------------------------------------------------------------------------" +} + +trap cleanup EXIT + +rm -rf *.out + +if [ "$DURATION" = -1 ]; then + echo "Test report on " `date +%F` + echo "========================================================================================================" + echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|Std Dev|" + echo "--------------------------------------------------------------------------------------------------------" +else + echo "Test in progress....Tail stats-csv.log to see results being printed for each iteration." +fi + +run_controller diff --git a/java/tools/bin/mercury-start-consumers b/java/tools/bin/mercury-start-consumers new file mode 100644 index 0000000000..c71fc0c21f --- /dev/null +++ b/java/tools/bin/mercury-start-consumers @@ -0,0 +1,119 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# This starts the controller for coordinating perf tests/ + +. check-qpid-java-env + +PROGRAM_NAME="start-consumers" +PROCESS_COUNT=1 +CON_COUNT=1 +MSG_COUNT=10000 +ADDRESS="queue;{create:always}" +UNIQUE_DEST="false" + +EXTRA_JVM_ARGS=" -Dmax_prefetch=500 " + +TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'` + +TEMP=$(getopt -n $PROGRAM_NAME -o C:P:uc:p:a:s:t:w:h\ + --long connection-count:,process-count:,create-unique-queues-topics,\ +jvm-args:,queue:,topic:,address:,\ +msg-count:,help -- "$@") + +usage() +{ + printf "\n%s\n" "Usage: start-producers [option].." + + printf "\n%32s\n%51s\n" "-C, --connection-count=count" "No of consumers participating in the test" + + printf "\n%29s\n%51s\n" "-P, --process-count=count" "No of producers participating in the test" + + printf "\n%37s\n%105s\n" "-u, --create-unique-queues-topics" "This will create unique queue names and topics based on what you specify for --queue or --topic" + + printf "\n%11s\n%55s\n" "--queue" "The Queue you want to publish to. Ex my-queue" + + printf "\n%11s\n%84s\n" "--topic" "The Topic you want to publish to in amq.topic exchange. Ex amq.topic/topic" + + printf "\n%13s\n%44s\n" "--address" "The address you want to publish to" + + printf "\n%25s\n%50s\n" "-c, --msg-count=count" "message count per test (default 500,000)" + + printf "\n%18s\n%49s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify" +} + +eval set -- "$TEMP" +while true; do + case $1 in + -C|--connection-count) + CON_COUNT="$2"; shift; shift; continue + ;; + -P|--process-count) + PROCESS_COUNT="$2"; shift; shift; continue + ;; + -u|--create-unique-queues-topics) + UNIQUE_DEST="true"; shift; continue + ;; + --queue) + ADDRESS="$2;{create: always}"; shift; shift; continue + ;; + --topic) + ADDRESS="amq.topic/$2"; shift; shift; continue + ;; + --address) + ADDRESS="$2"; shift; shift; continue + ;; + -h|--help) + usage + exit 0 + ;; + -a|--jvm-args) + EXTRA_JVM_ARGS="$2"; shift; shift; continue + ;; + -c|--msg-count) + MSG_COUNT="$2"; shift; shift; continue + ;; + --) + # no more arguments to parse + break + ;; + *) + # no more arguments to parse + break + ;; + esac +done + +CONSUMER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dprecision=mili -Dcon_count=$CON_COUNT -Dprint_std_dev=true" + +start_consumers() +{ + for ((i=0; i<$PROCESS_COUNT; i++)) + do + if [ "$UNIQUE_DEST" = "true" ]; then + sh run-sub "$CONSUMER_ARGS $@" "${TEST_ID}_$i" > ${TEST_ID}_$i.sub.out 2>&1 & + else + sh run-sub "$CONSUMER_ARGS $@" > ${TEST_ID}_$i.sub.out 2>&1 & + fi + done +} + +start_consumers "-Daddress=$ADDRESS -Duse_unique_dest=$UNIQUE_DEST -Dmsg_count=$MSG_COUNT -Dcon_count=$CON_COUNT $EXTRA_JVM_ARGS" + diff --git a/java/tools/bin/mercury-start-producers b/java/tools/bin/mercury-start-producers new file mode 100644 index 0000000000..7ba0286f7c --- /dev/null +++ b/java/tools/bin/mercury-start-producers @@ -0,0 +1,136 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# This starts the controller for coordinating perf tests/ + +. check-qpid-java-env + +PROGRAM_NAME="start-producers" +PROCESS_COUNT=1 +CON_COUNT=1 +MSG_TYPE="bytes" +WARMUP_MSG_COUNT=1000 +MSG_COUNT=10000 +MSG_SIZE=1024 +ADDRESS="queue;{create:always}" +UNIQUE_DEST="false" + +EXTRA_JVM_ARGS="" +TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'` + +TEMP=$(getopt -n $PROGRAM_NAME -o C:P:uc:p:a:s:t:w:h\ + --long connection-count:,process-count:,create-unique-queues-topics,\ +jvm-args:,queue:,topic:,address:,\ +msg-count:,msg-size:msg-type:,warmup-msg-count,help -- "$@") + +usage() +{ + printf "\n%s\n" "Usage: start-producers [option].." + + printf "\n%32s\n%51s\n" "-C, --connection-count=count" "No of consumers participating in the test" + + printf "\n%29s\n%51s\n" "-P, --process-count=count" "No of producers participating in the test" + + printf "\n%37s\n%105s\n" "-u, --create-unique-queues-topics" "This will create unique queue names and topics based on what you specify for --queue or --topic" + + printf "\n%11s\n%55s\n" "--queue" "The Queue you want to publish to. Ex my-queue" + + printf "\n%11s\n%84s\n" "--topic" "The Topic you want to publish to in amq.topic exchange. Ex amq.topic/topic" + + printf "\n%13s\n%44s\n" "--address" "The address you want to publish to" + + printf "\n%23s\n%37s\n" "-s, --msg-size=size" "message size (default 1024)" + + printf "\n%25s\n%50s\n" "-c, --msg-count=count" "message count per test (default 500,000)" + + printf "\n%18s\n%38s\n" "-t, --msg-type" "{bytes|text} (default bytes)" + + printf "\n%26s\n%49s\n" "-w, --warmup-msg-count" "warm up message count (default 100,000)" + + printf "\n%18s\n%49s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify" +} + +eval set -- "$TEMP" +while true; do + case $1 in + -C|--connection-count) + CON_COUNT="$2"; shift; shift; continue + ;; + -P|--process-count) + PROCESS_COUNT="$2"; shift; shift; continue + ;; + -u|--create-unique-queues-topics) + UNIQUE_DEST="true"; shift; continue + ;; + --queue) + ADDRESS="$2;{create: always}"; shift; shift; continue + ;; + --topic) + ADDRESS="amq.topic/$2"; shift; shift; continue + ;; + --address) + ADDRESS="$2"; shift; shift; continue + ;; + -h|--help) + usage + exit 0 + ;; + -a|--jvm-args) + EXTRA_JVM_ARGS="$2"; shift; shift; continue + ;; + -s|--msg-size) + MSG_SIZE="$2"; shift; shift; continue + ;; + -c|--msg-count) + MSG_COUNT="$2"; shift; shift; continue + ;; + -t|--msg_type) + MSG_TYPE="$2"; shift; shift; continue + ;; + -w|--warmup-msg-count) + WARMUP_MSG_COUNT="$2"; shift; shift; continue + ;; + --) + # no more arguments to parse + break + ;; + *) + # no more arguments to parse + break + ;; + esac +done + +PRODUCER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dext_controller=true -Dprecision=mili -Dcon_count=$CON_COUNT" + +start_producers() +{ + for ((i=0; i<$PROCESS_COUNT; i++)) + do + if [ "$UNIQUE_DEST" = "true" ]; then + sh run-pub "$PRODUCER_ARGS $@" "${TEST_ID}_$i" > ${TEST_ID}_$i.pub.out 2>&1 & + else + sh run-pub "$PRODUCER_ARGS $@" > ${TEST_ID}_$i.pub.out 2>&1 & + fi + done +} + +start_producers "-Daddress=$ADDRESS -Duse_unique_dest=$UNIQUE_DEST -Dmsg_count=$MSG_COUNT -Dmsg_size=$MSG_SIZE -Dwarmup_count=$WARMUP_MSG_COUNT -Dmsg_type=$MSG_TYPE -Dcon_count=$CON_COUNT $EXTRA_JVM_ARGS" + diff --git a/java/tools/bin/perf-report b/java/tools/bin/perf-report deleted file mode 100755 index 7de3f2b602..0000000000 --- a/java/tools/bin/perf-report +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# This will run the following test cases defined below and produce -# a report in tabular format. - -QUEUE="queue;{create:always,node:{x-declare:{auto-delete:true}}}" -DURA_QUEUE="dqueue;{create:always,node:{durable:true,x-declare:{auto-delete:true}}}" -TOPIC="amq.topic/test" -DURA_TOPIC="amq.topic/test;{create:always,link:{durable:true}}" - -COMMON_CONFIG="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'" - -waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; } -cleanup() -{ - pids=`ps aux | grep java | grep Perf | awk '{print $2}'` - if [ "$pids" != "" ]; then - kill -3 $pids - kill -9 $pids >/dev/null 2>&1 - fi -} - -# $1 test name -# $2 consumer options -# $3 producer options -run_testcase() -{ - sh run-sub $COMMON_CONFIG $2 > sub.out & - sh run-pub $COMMON_CONFIG $3 > pub.out & - waitfor pub.out "Controller: Completed the test" - sleep 2 #give a grace period to shutdown - print_result $1 - mv pub.out $1.pub.out - mv sub.out $1.sub.out -} - -print_result() -{ - prod_rate=`cat pub.out | grep "Avg Producer rate" | awk '{print $5}'` - sys_rate=`cat pub.out | grep "System Throughput" | awk '{print $4}'` - cons_rate=`cat pub.out | grep "Avg Consumer rate" | awk '{print $5}'` - avg_latency=`cat pub.out | grep "Avg System Latency" | awk '{print $5}'` - min_latency=`cat pub.out | grep "Min System Latency" | awk '{print $5}'` - max_latency=`cat pub.out | grep "Max System Latency" | awk '{print $5}'` - - printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11.2f|%11.2f|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency - echo "------------------------------------------------------------------------------------------------" -} - -trap cleanup EXIT -rm -rf *.out #cleanup old files. - -echo "Test report on " `date +%F` -echo "================================================================================================" -echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|" -echo "------------------------------------------------------------------------------------------------" - -# The message counts and warmup counts are set to very low values for quick testing of the script. -# For a real performance run I recommend setting warmup count to 10k and message count in excess of 100k -# However for transactions, sync_publish and especially small durable transactions (which is quite slow) I recommend -# setting very low values to start with and experiment while increasing them slowly. - -# Test 1 Trans Queue -run_testcase "Trans_Queue" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dwarmup_count=1 -Dmsg_count=10" - -# Test 2 Dura Queue -run_testcase "Dura_Queue" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" - -# Test 3 Dura Queue Sync -run_testcase "Dura_Queue_Sync" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent" - -# Test 4 Dura Queue Sync Publish and Ack -run_testcase "Dura_SyncPubAck" "-Daddress=$DURA_QUEUE -Ddurable=true -Dsync_ack=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent" - -# Test 5 Topic -run_testcase "Topic" "-Daddress=$TOPIC" "-Daddress=$TOPIC -Dwarmup_count=1 -Dmsg_count=10" - -# Test 6 Durable Topic -run_testcase "Dura_Topic" "-Daddress=$DURA_TOPIC -Ddurable=true" "-Daddress=$DURA_TOPIC -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" - -# Test 7 Fanout -run_testcase "Fanout" "-Daddress=amq.fanout" "-Daddress=amq.fanout -Dwarmup_count=1 -Dmsg_count=10" - -# Test 8 Small TX -run_testcase "Small_Txs_2" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=1" \ - "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=1" - -# Test 9 Large TX -run_testcase "Large_Txs_1000" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=10" \ - "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=10" - -# Test 10 256 MSG -run_testcase "Msg_256b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=256 -Dwarmup_count=1 -Dmsg_count=10" - -# Test 11 512 MSG -run_testcase "Msg_512b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=512 -Dwarmup_count=1 -Dmsg_count=10" - -# Test 12 2048 MSG -run_testcase "Msg_2048b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=2048 -Dwarmup_count=1 -Dmsg_count=10" - -# Test 13 Random size MSG -run_testcase "Random_Msg_Size" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10" - -# Test 14 Random size MSG Durable -run_testcase "Rand_Msg_Dura" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10" - -# Test 15 64K MSG -run_testcase "Msg_64K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Dwarmup_count=1 -Dmsg_count=10" - -# Test 16 Durable 64K MSG -run_testcase "Msg_Durable_64K" "-Daddress=$DURA_QUEUE -Ddurable=true -Damqj.tcpNoDelay=true" \ - "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" - -# Test 17 500K MSG -run_testcase "Msg_500K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Dwarmup_count=1 -Dmsg_count=10" - -# Test 18 Durable 500K MSG -run_testcase "Msg_Dura_500K" "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Ddurable=true" \ - "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10" diff --git a/java/tools/bin/start-consumers b/java/tools/bin/start-consumers deleted file mode 100644 index c71fc0c21f..0000000000 --- a/java/tools/bin/start-consumers +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# This starts the controller for coordinating perf tests/ - -. check-qpid-java-env - -PROGRAM_NAME="start-consumers" -PROCESS_COUNT=1 -CON_COUNT=1 -MSG_COUNT=10000 -ADDRESS="queue;{create:always}" -UNIQUE_DEST="false" - -EXTRA_JVM_ARGS=" -Dmax_prefetch=500 " - -TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'` - -TEMP=$(getopt -n $PROGRAM_NAME -o C:P:uc:p:a:s:t:w:h\ - --long connection-count:,process-count:,create-unique-queues-topics,\ -jvm-args:,queue:,topic:,address:,\ -msg-count:,help -- "$@") - -usage() -{ - printf "\n%s\n" "Usage: start-producers [option].." - - printf "\n%32s\n%51s\n" "-C, --connection-count=count" "No of consumers participating in the test" - - printf "\n%29s\n%51s\n" "-P, --process-count=count" "No of producers participating in the test" - - printf "\n%37s\n%105s\n" "-u, --create-unique-queues-topics" "This will create unique queue names and topics based on what you specify for --queue or --topic" - - printf "\n%11s\n%55s\n" "--queue" "The Queue you want to publish to. Ex my-queue" - - printf "\n%11s\n%84s\n" "--topic" "The Topic you want to publish to in amq.topic exchange. Ex amq.topic/topic" - - printf "\n%13s\n%44s\n" "--address" "The address you want to publish to" - - printf "\n%25s\n%50s\n" "-c, --msg-count=count" "message count per test (default 500,000)" - - printf "\n%18s\n%49s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify" -} - -eval set -- "$TEMP" -while true; do - case $1 in - -C|--connection-count) - CON_COUNT="$2"; shift; shift; continue - ;; - -P|--process-count) - PROCESS_COUNT="$2"; shift; shift; continue - ;; - -u|--create-unique-queues-topics) - UNIQUE_DEST="true"; shift; continue - ;; - --queue) - ADDRESS="$2;{create: always}"; shift; shift; continue - ;; - --topic) - ADDRESS="amq.topic/$2"; shift; shift; continue - ;; - --address) - ADDRESS="$2"; shift; shift; continue - ;; - -h|--help) - usage - exit 0 - ;; - -a|--jvm-args) - EXTRA_JVM_ARGS="$2"; shift; shift; continue - ;; - -c|--msg-count) - MSG_COUNT="$2"; shift; shift; continue - ;; - --) - # no more arguments to parse - break - ;; - *) - # no more arguments to parse - break - ;; - esac -done - -CONSUMER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dprecision=mili -Dcon_count=$CON_COUNT -Dprint_std_dev=true" - -start_consumers() -{ - for ((i=0; i<$PROCESS_COUNT; i++)) - do - if [ "$UNIQUE_DEST" = "true" ]; then - sh run-sub "$CONSUMER_ARGS $@" "${TEST_ID}_$i" > ${TEST_ID}_$i.sub.out 2>&1 & - else - sh run-sub "$CONSUMER_ARGS $@" > ${TEST_ID}_$i.sub.out 2>&1 & - fi - done -} - -start_consumers "-Daddress=$ADDRESS -Duse_unique_dest=$UNIQUE_DEST -Dmsg_count=$MSG_COUNT -Dcon_count=$CON_COUNT $EXTRA_JVM_ARGS" - diff --git a/java/tools/bin/start-producers b/java/tools/bin/start-producers deleted file mode 100644 index 7ba0286f7c..0000000000 --- a/java/tools/bin/start-producers +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# This starts the controller for coordinating perf tests/ - -. check-qpid-java-env - -PROGRAM_NAME="start-producers" -PROCESS_COUNT=1 -CON_COUNT=1 -MSG_TYPE="bytes" -WARMUP_MSG_COUNT=1000 -MSG_COUNT=10000 -MSG_SIZE=1024 -ADDRESS="queue;{create:always}" -UNIQUE_DEST="false" - -EXTRA_JVM_ARGS="" -TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'` - -TEMP=$(getopt -n $PROGRAM_NAME -o C:P:uc:p:a:s:t:w:h\ - --long connection-count:,process-count:,create-unique-queues-topics,\ -jvm-args:,queue:,topic:,address:,\ -msg-count:,msg-size:msg-type:,warmup-msg-count,help -- "$@") - -usage() -{ - printf "\n%s\n" "Usage: start-producers [option].." - - printf "\n%32s\n%51s\n" "-C, --connection-count=count" "No of consumers participating in the test" - - printf "\n%29s\n%51s\n" "-P, --process-count=count" "No of producers participating in the test" - - printf "\n%37s\n%105s\n" "-u, --create-unique-queues-topics" "This will create unique queue names and topics based on what you specify for --queue or --topic" - - printf "\n%11s\n%55s\n" "--queue" "The Queue you want to publish to. Ex my-queue" - - printf "\n%11s\n%84s\n" "--topic" "The Topic you want to publish to in amq.topic exchange. Ex amq.topic/topic" - - printf "\n%13s\n%44s\n" "--address" "The address you want to publish to" - - printf "\n%23s\n%37s\n" "-s, --msg-size=size" "message size (default 1024)" - - printf "\n%25s\n%50s\n" "-c, --msg-count=count" "message count per test (default 500,000)" - - printf "\n%18s\n%38s\n" "-t, --msg-type" "{bytes|text} (default bytes)" - - printf "\n%26s\n%49s\n" "-w, --warmup-msg-count" "warm up message count (default 100,000)" - - printf "\n%18s\n%49s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify" -} - -eval set -- "$TEMP" -while true; do - case $1 in - -C|--connection-count) - CON_COUNT="$2"; shift; shift; continue - ;; - -P|--process-count) - PROCESS_COUNT="$2"; shift; shift; continue - ;; - -u|--create-unique-queues-topics) - UNIQUE_DEST="true"; shift; continue - ;; - --queue) - ADDRESS="$2;{create: always}"; shift; shift; continue - ;; - --topic) - ADDRESS="amq.topic/$2"; shift; shift; continue - ;; - --address) - ADDRESS="$2"; shift; shift; continue - ;; - -h|--help) - usage - exit 0 - ;; - -a|--jvm-args) - EXTRA_JVM_ARGS="$2"; shift; shift; continue - ;; - -s|--msg-size) - MSG_SIZE="$2"; shift; shift; continue - ;; - -c|--msg-count) - MSG_COUNT="$2"; shift; shift; continue - ;; - -t|--msg_type) - MSG_TYPE="$2"; shift; shift; continue - ;; - -w|--warmup-msg-count) - WARMUP_MSG_COUNT="$2"; shift; shift; continue - ;; - --) - # no more arguments to parse - break - ;; - *) - # no more arguments to parse - break - ;; - esac -done - -PRODUCER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dext_controller=true -Dprecision=mili -Dcon_count=$CON_COUNT" - -start_producers() -{ - for ((i=0; i<$PROCESS_COUNT; i++)) - do - if [ "$UNIQUE_DEST" = "true" ]; then - sh run-pub "$PRODUCER_ARGS $@" "${TEST_ID}_$i" > ${TEST_ID}_$i.pub.out 2>&1 & - else - sh run-pub "$PRODUCER_ARGS $@" > ${TEST_ID}_$i.pub.out 2>&1 & - fi - done -} - -start_producers "-Daddress=$ADDRESS -Duse_unique_dest=$UNIQUE_DEST -Dmsg_count=$MSG_COUNT -Dmsg_size=$MSG_SIZE -Dwarmup_count=$WARMUP_MSG_COUNT -Dmsg_type=$MSG_TYPE -Dcon_count=$CON_COUNT $EXTRA_JVM_ARGS" - diff --git a/java/tools/src/main/java/org/apache/qpid/tools/Clock.java b/java/tools/src/main/java/org/apache/qpid/tools/Clock.java index 979d2ef76f..4e79dd62a8 100644 --- a/java/tools/src/main/java/org/apache/qpid/tools/Clock.java +++ b/java/tools/src/main/java/org/apache/qpid/tools/Clock.java @@ -27,6 +27,8 @@ package org.apache.qpid.tools; public class Clock { + public final static long SEC = 60000; + private static Precision precision; private static long offset = -1; // in nano secs diff --git a/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java b/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java new file mode 100644 index 0000000000..c6abdf6c84 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java @@ -0,0 +1,411 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.text.DecimalFormat; + +import javax.jms.Connection; +import javax.jms.Session; + +import org.apache.qpid.client.AMQConnection; + +public class JVMArgConfiguration implements TestConfiguration +{ + /* + * By default the connection URL is used. + * This allows a user to easily specify a fully fledged URL any given property. + * Ex. SSL parameters + * + * By providing a host & port allows a user to simply override the URL. + * This allows to create multiple clients in test scripts easily, + * without having to deal with the long URL format. + */ + private String url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'"; + + private String host = ""; + + private int port = -1; + + private String address = "queue; {create : always}"; + + private int msg_size = 1024; + + private int random_msg_size_start_from = 1; + + private boolean cacheMessage = false; + + private boolean disableMessageID = false; + + private boolean disableTimestamp = false; + + private boolean durable = false; + + private int transaction_size = 0; + + private int ack_mode = Session.AUTO_ACKNOWLEDGE; + + private int msg_count = 10; + + private int warmup_count = 1; + + private boolean random_msg_size = false; + + private String msgType = "bytes"; + + private boolean printStdDev = false; + + private int sendRate = 0; + + private boolean externalController = false; + + private boolean useUniqueDest = false; // useful when using multiple connections. + + private int ackFrequency = 100; + + private DecimalFormat df = new DecimalFormat("###.##"); + + private int reportEvery = 0; + + private boolean isReportTotal = false; + + private boolean isReportHeader = true; + + private boolean isReportLatency = false; + + private int sendEOS = 0; + + private int connectionCount = 1; + + private int rollbackFrequency = 0; + + private boolean printHeaders; + + public JVMArgConfiguration() + { + + url = System.getProperty("url",url); + host = System.getProperty("host",""); + port = Integer.getInteger("port", -1); + address = System.getProperty("address",address); + + msg_size = Integer.getInteger("msg-size", 1024); + cacheMessage = Boolean.getBoolean("cache-msg"); + disableMessageID = Boolean.getBoolean("disable-message-id"); + disableTimestamp = Boolean.getBoolean("disable-timestamp"); + durable = Boolean.getBoolean("durable"); + transaction_size = Integer.getInteger("tx",1000); + ack_mode = Integer.getInteger("ack-mode",Session.AUTO_ACKNOWLEDGE); + msg_count = Integer.getInteger("msg-count",msg_count); + warmup_count = Integer.getInteger("warmup-count",warmup_count); + random_msg_size = Boolean.getBoolean("random-msg-size"); + msgType = System.getProperty("msg-type","bytes"); + printStdDev = Boolean.getBoolean("print-std-dev"); + sendRate = Integer.getInteger("rate",0); + externalController = Boolean.getBoolean("ext-controller"); + useUniqueDest = Boolean.getBoolean("use-unique-dest"); + random_msg_size_start_from = Integer.getInteger("random-msg-size-start-from", 1); + reportEvery = Integer.getInteger("report-every"); + isReportTotal = Boolean.getBoolean("report-total"); + isReportHeader = (System.getProperty("report-header") == null) ? true : Boolean.getBoolean("report-header"); + isReportLatency = Boolean.getBoolean("report-latency"); + sendEOS = Integer.getInteger("send-eos"); + connectionCount = Integer.getInteger("con_count",1); + ackFrequency = Integer.getInteger("ack-frequency"); + rollbackFrequency = Integer.getInteger("rollback-frequency"); + printHeaders = Boolean.getBoolean("print-headers"); + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getUrl() + */ + @Override + public String getUrl() + { + return url; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getHost() + */ + @Override + public String getHost() + { + return host; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getPort() + */ + @Override + public int getPort() + { + return port; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getAddress() + */ + @Override + public String getAddress() + { + return address; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getAckMode() + */ + @Override + public int getAckMode() + { + return ack_mode; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getMsgCount() + */ + @Override + public int getMsgCount() + { + return msg_count; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getMsgSize() + */ + @Override + public int getMsgSize() + { + return msg_size; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getRandomMsgSizeStartFrom() + */ + @Override + public int getRandomMsgSizeStartFrom() + { + return random_msg_size_start_from; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isDurable() + */ + @Override + public boolean isDurable() + { + return durable; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isTransacted() + */ + @Override + public boolean isTransacted() + { + return transaction_size > 0; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getTransactionSize() + */ + @Override + public int getTransactionSize() + { + return transaction_size; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getWarmupCount() + */ + @Override + public int getWarmupCount() + { + return warmup_count; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isCacheMessage() + */ + @Override + public boolean isCacheMessage() + { + return cacheMessage; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isDisableMessageID() + */ + @Override + public boolean isDisableMessageID() + { + return disableMessageID; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isDisableTimestamp() + */ + @Override + public boolean isDisableTimestamp() + { + return disableTimestamp; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isRandomMsgSize() + */ + @Override + public boolean isRandomMsgSize() + { + return random_msg_size; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getMessageType() + */ + @Override + public String getMessageType() + { + return msgType; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isPrintStdDev() + */ + @Override + public boolean isPrintStdDev() + { + return printStdDev; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getSendRate() + */ + @Override + public int getSendRate() + { + return sendRate; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isExternalController() + */ + @Override + public boolean isExternalController() + { + return externalController; + } + + public void setAddress(String addr) + { + address = addr; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#isUseUniqueDests() + */ + @Override + public boolean isUseUniqueDests() + { + return useUniqueDest; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getAckFrequency() + */ + @Override + public int getAckFrequency() + { + return ackFrequency; + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#createConnection() + */ + @Override + public Connection createConnection() throws Exception + { + if (getHost().equals("") || getPort() == -1) + { + return new AMQConnection(getUrl()); + } + else + { + return new AMQConnection(getHost(),getPort(),"guest","guest","test","test"); + } + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.TestConfiguration#getDecimalFormat() + */ + @Override + public DecimalFormat getDecimalFormat() + { + return df; + } + + @Override + public int reportEvery() + { + return reportEvery; + } + + @Override + public boolean isReportTotal() + { + return isReportTotal; + } + + @Override + public boolean isReportHeader() + { + return isReportHeader; + } + + @Override + public boolean isReportLatency() + { + return isReportLatency; + } + + @Override + public int getSendEOS() + { + return sendEOS; + } + + @Override + public int getConnectionCount() + { + return connectionCount; + } + + @Override + public int getRollbackFrequency() + { + return rollbackFrequency; + } + + @Override + public boolean isPrintHeaders() + { + return printHeaders; + } +} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java b/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java deleted file mode 100644 index 16149d17c9..0000000000 --- a/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.tools; - -import java.io.FileOutputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import javax.jms.BytesMessage; -import javax.jms.DeliveryMode; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.TextMessage; - -import org.apache.qpid.thread.Threading; - -/** - * Latency test sends an x number of messages in warmup mode and wait for a confirmation - * from the consumer that it has successfully consumed them and ready to start the - * test. It will start sending y number of messages and each message will contain a time - * stamp. This will be used at the receiving end to measure the latency. - * - * It is important to have a sufficiently large number for the warmup count to - * ensure the system is in steady state before the test is started. - * - * If you plan to plot the latencies then msg_count should be a smaller number (ex 500 or 1000) - * You also need to specify a file name using -Dfile=/home/rajith/latency.log.1 - * - * The idea is to get a latency sample for the system once it achieves steady state. - * - */ - -public class LatencyTest extends PerfBase implements MessageListener -{ - private MessageProducer producer; - private MessageConsumer consumer; - private Message msg; - private byte[] payload; - private long maxLatency = 0; - private long minLatency = Long.MAX_VALUE; - private long totalLatency = 0; // to calculate avg latency. - private int rcvdMsgCount = 0; - private double stdDev = 0; - private double avgLatency = 0; - private boolean warmup_mode = true; - private boolean transacted = false; - private int transSize = 0; - - private final List latencies; - private final Lock lock = new ReentrantLock(); - private final Condition warmedUp; - private final Condition testCompleted; - - public LatencyTest() - { - super(""); - warmedUp = lock.newCondition(); - testCompleted = lock.newCondition(); - // Storing the following two for efficiency - transacted = params.isTransacted(); - transSize = params.getTransactionSize(); - latencies = new ArrayList (params.getMsgCount()); - } - - public void setUp() throws Exception - { - super.setUp(); - consumer = session.createConsumer(dest); - consumer.setMessageListener(this); - - // if message caching is enabled we pre create the message - // else we pre create the payload - if (params.isCacheMessage()) - { - msg = MessageFactory.createBytesMessage(session, params.getMsgSize()); - msg.setJMSDeliveryMode(params.isDurable()? - DeliveryMode.PERSISTENT : - DeliveryMode.NON_PERSISTENT - ); - } - else - { - payload = MessageFactory.createMessagePayload(params.getMsgSize()).getBytes(); - } - - producer = session.createProducer(dest); - producer.setDisableMessageID(params.isDisableMessageID()); - producer.setDisableMessageTimestamp(params.isDisableTimestamp()); - } - - protected Message getNextMessage() throws Exception - { - if (params.isCacheMessage()) - { - return msg; - } - else - { - msg = session.createBytesMessage(); - ((BytesMessage)msg).writeBytes(payload); - return msg; - } - } - - public void warmup()throws Exception - { - System.out.println("Warming up......"); - int count = params.getWarmupCount(); - for (int i=0; i < count; i++) - { - producer.send(getNextMessage()); - } - Message msg = session.createTextMessage("End"); - producer.send(msg); - - if (params.isTransacted()) - { - session.commit(); - } - - try - { - lock.lock(); - warmedUp.await(); - } - finally - { - lock.unlock(); - } - } - - public void onMessage(Message msg) - { - try - { - if (msg instanceof TextMessage && ((TextMessage)msg).getText().equals("End")) - { - if (warmup_mode) - { - warmup_mode = false; - try - { - lock.lock(); - warmedUp.signal(); - } - finally - { - lock.unlock(); - } - } - else - { - computeStats(); - } - } - else if (!warmup_mode) - { - long time = System.currentTimeMillis(); - rcvdMsgCount ++; - - if (transacted && (rcvdMsgCount % transSize == 0)) - { - session.commit(); - } - - long latency = time - msg.getJMSTimestamp(); - latencies.add(latency); - totalLatency = totalLatency + latency; - } - - } - catch(Exception e) - { - handleError(e,"Error when receiving messages"); - } - - } - - private void computeStats() - { - avgLatency = (double)totalLatency/(double)rcvdMsgCount; - double sigma = 0; - - for (long latency: latencies) - { - maxLatency = Math.max(maxLatency, latency); - minLatency = Math.min(minLatency, latency); - sigma = sigma + Math.pow(latency - avgLatency,2); - } - - stdDev = Math.sqrt(sigma/(rcvdMsgCount -1)); - - try - { - lock.lock(); - testCompleted.signal(); - } - finally - { - lock.unlock(); - } - } - - public void writeToFile() throws Exception - { - String fileName = System.getProperty("file"); - PrintWriter writer = new PrintWriter(new FileOutputStream(fileName)); - for (long latency: latencies) - { - writer.println(String.valueOf(latency)); - } - writer.flush(); - writer.close(); - } - - public void printToConsole() - { - System.out.println(new StringBuilder("Total Msgs Received : ").append(rcvdMsgCount).toString()); - System.out.println(new StringBuilder("Standard Deviation : "). - append(df.format(stdDev)). - append(" ms").toString()); - System.out.println(new StringBuilder("Avg Latency : "). - append(df.format(avgLatency)). - append(" ms").toString()); - System.out.println(new StringBuilder("Min Latency : "). - append(minLatency). - append(" ms").toString()); - System.out.println(new StringBuilder("Max Latency : "). - append(maxLatency). - append(" ms").toString()); - System.out.println("Completed the test......\n"); - } - - public void startTest() throws Exception - { - System.out.println("Starting test......"); - int count = params.getMsgCount(); - - for(int i=0; i < count; i++ ) - { - Message msg = getNextMessage(); - msg.setJMSTimestamp(System.currentTimeMillis()); - producer.send(msg); - if ( transacted && ((i+1) % transSize == 0)) - { - session.commit(); - } - } - Message msg = session.createTextMessage("End"); - producer.send(msg); - if (params.isTransacted()) - { - session.commit(); - } - } - - public void tearDown() throws Exception - { - try - { - lock.lock(); - testCompleted.await(); - } - finally - { - lock.unlock(); - } - - producer.close(); - consumer.close(); - session.close(); - con.close(); - } - - public void test() - { - try - { - setUp(); - warmup(); - startTest(); - tearDown(); - } - catch(Exception e) - { - handleError(e,"Error when running test"); - } - } - - - public static void main(String[] args) - { - final LatencyTest latencyTest = new LatencyTest(); - Runnable r = new Runnable() - { - public void run() - { - latencyTest.test(); - latencyTest.printToConsole(); - if (System.getProperty("file") != null) - { - try - { - latencyTest.writeToFile(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - } - }; - - Thread t; - try - { - t = Threading.getThreadFactory().createThread(r); - } - catch(Exception e) - { - throw new Error("Error creating latency test thread",e); - } - t.start(); - } -} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/MercuryBase.java b/java/tools/src/main/java/org/apache/qpid/tools/MercuryBase.java new file mode 100644 index 0000000000..097b021b3e --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/MercuryBase.java @@ -0,0 +1,191 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.net.InetAddress; +import java.util.UUID; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.MapMessage; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; + +import org.apache.qpid.client.AMQAnyDestination; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession_0_10; +import org.apache.qpid.messaging.Address; +import org.apache.qpid.tools.TestConfiguration.MessageType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MercuryBase +{ + private static final Logger _logger = LoggerFactory.getLogger(MercuryBase.class); + + public final static String CODE = "CODE"; + public final static String ID = "ID"; + public final static String REPLY_ADDR = "REPLY_ADDR"; + public final static String MAX_LATENCY = "MAX_LATENCY"; + public final static String MIN_LATENCY = "MIN_LATENCY"; + public final static String AVG_LATENCY = "AVG_LATENCY"; + public final static String STD_DEV = "STD_DEV"; + public final static String CONS_RATE = "CONS_RATE"; + public final static String PROD_RATE = "PROD_RATE"; + public final static String MSG_COUNT = "MSG_COUNT"; + public final static String TIMESTAMP = "Timestamp"; + + String CONTROLLER_ADDR = System.getProperty("CONT_ADDR","CONTROLLER;{create: always, node:{x-declare:{auto-delete:true}}}"); + + TestConfiguration config; + Connection con; + Session session; + Session controllerSession; + Destination dest; + Destination myControlQueue; + Destination controllerQueue; + String id; + String myControlQueueAddr; + + MessageProducer sendToController; + MessageConsumer receiveFromController; + String prefix = ""; + + enum OPCode + { + REGISTER_CONSUMER, REGISTER_PRODUCER, + PRODUCER_STARTWARMUP, CONSUMER_STARTWARMUP, + CONSUMER_READY, PRODUCER_READY, + PRODUCER_START, + RECEIVED_END_MSG, CONSUMER_STOP, + RECEIVED_PRODUCER_STATS, RECEIVED_CONSUMER_STATS, + CONTINUE_TEST, STOP_TEST + }; + + MessageType msgType = MessageType.BYTES; + + public MercuryBase(TestConfiguration config,String prefix) + { + this.config = config; + String host = ""; + try + { + host = InetAddress.getLocalHost().getHostName(); + } + catch (Exception e) + { + } + id = host + "-" + UUID.randomUUID().toString(); + this.prefix = prefix; + this.myControlQueueAddr = id + ";{create: always}"; + } + + public void setUp() throws Exception + { + con = config.createConnection(); + con.start(); + + controllerSession = con.createSession(false, Session.AUTO_ACKNOWLEDGE); + + dest = createDestination(); + controllerQueue = AMQDestination.createDestination(CONTROLLER_ADDR); + myControlQueue = session.createQueue(myControlQueueAddr); + msgType = MessageType.getType(config.getMessageType()); + _logger.debug("Using " + msgType + " messages"); + + sendToController = controllerSession.createProducer(controllerQueue); + receiveFromController = controllerSession.createConsumer(myControlQueue); + } + + private Destination createDestination() throws Exception + { + if (config.isUseUniqueDests()) + { + _logger.debug("Prefix : " + prefix); + Address addr = Address.parse(config.getAddress()); + AMQDestination temp = (AMQDestination) AMQDestination.createDestination(config.getAddress()); + int type = ((AMQSession_0_10)session).resolveAddressType(temp); + + if ( type == AMQDestination.TOPIC_TYPE) + { + addr = new Address(addr.getName(),addr.getSubject() + "." + prefix,addr.getOptions()); + System.out.println("Setting subject : " + addr); + } + else + { + addr = new Address(addr.getName() + "_" + prefix,addr.getSubject(),addr.getOptions()); + System.out.println("Setting name : " + addr); + } + + return AMQDestination.createDestination(addr.toString()); + } + else + { + return AMQDestination.createDestination(config.getAddress()); + } + } + + public synchronized void sendMessageToController(MapMessage m) throws Exception + { + m.setString(ID, id); + m.setString(REPLY_ADDR,myControlQueueAddr); + sendToController.send(m); + } + + public void receiveFromController(OPCode expected) throws Exception + { + MapMessage m = (MapMessage)receiveFromController.receive(); + OPCode code = OPCode.values()[m.getInt(CODE)]; + _logger.debug("Received Code : " + code); + if (expected != code) + { + throw new Exception("Expected OPCode : " + expected + " but received : " + code); + } + + } + + public boolean continueTest() throws Exception + { + MapMessage m = (MapMessage)receiveFromController.receive(); + OPCode code = OPCode.values()[m.getInt(CODE)]; + _logger.debug("Received Code : " + code); + return (code == OPCode.CONTINUE_TEST); + } + + public void tearDown() throws Exception + { + session.close(); + controllerSession.close(); + con.close(); + } + + public void handleError(Exception e,String msg) + { + StringBuilder sb = new StringBuilder(); + sb.append(msg); + sb.append(" "); + sb.append(e.getMessage()); + System.err.println(sb.toString()); + e.printStackTrace(); + } +} + diff --git a/java/tools/src/main/java/org/apache/qpid/tools/MercuryConsumerController.java b/java/tools/src/main/java/org/apache/qpid/tools/MercuryConsumerController.java new file mode 100644 index 0000000000..b35adc45d6 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/MercuryConsumerController.java @@ -0,0 +1,231 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.util.concurrent.CountDownLatch; + +import javax.jms.MapMessage; + +import org.apache.qpid.thread.Threading; +import org.apache.qpid.tools.report.MercuryReporter; +import org.apache.qpid.tools.report.MercuryReporter.MercuryThroughputAndLatency; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * PerfConsumer will receive x no of messages in warmup mode. + * Once it receives the Start message it will then signal the PerfProducer. + * It will start recording stats from the first message it receives after + * the warmup mode is done. + * + * The following calculations are done. + * The important numbers to look at is + * a) Avg Latency + * b) System throughput. + * + * Latency. + * ========= + * Currently this test is written with the assumption that either + * a) The Perf Producer and Consumer are on the same machine + * b) They are on separate machines that have their time synced via a Time Server + * + * In order to calculate latency the producer inserts a timestamp + * when the message is sent. The consumer will note the current time the message is + * received and will calculate the latency as follows + * latency = rcvdTime - msg.getJMSTimestamp() + * + * Through out the test it will keep track of the max and min latency to show the + * variance in latencies. + * + * Avg latency is measured by adding all latencies and dividing by the total msgs. + * + * Throughput + * =========== + * Consumer rate is calculated as + * rcvdMsgCount/(rcvdTime - startTime) + * + * Note that the testStartTime referes to when the producer sent the first message + * and startTime is when the consumer first received a message. + * + * rcvdTime keeps track of when the last message is received. + * + * All throughput rates are given as msg/sec so the rates are multiplied by 1000. + * + */ + +public class MercuryConsumerController extends MercuryBase +{ + private static final Logger _logger = LoggerFactory.getLogger(MercuryConsumerController.class); + MercuryReporter reporter; + TestConfiguration config; + QpidReceive receiver; + + public MercuryConsumerController(TestConfiguration config, MercuryReporter reporter, String prefix) + { + super(config,prefix); + this.reporter = reporter; + if (_logger.isInfoEnabled()) + { + _logger.info("Consumer ID : " + id); + } + } + + public void setUp() throws Exception + { + super.setUp(); + receiver = new QpidReceive(reporter,config, con,dest); + receiver.setUp(); + MapMessage m = controllerSession.createMapMessage(); + m.setInt(CODE, OPCode.REGISTER_CONSUMER.ordinal()); + sendMessageToController(m); + } + + public void warmup()throws Exception + { + receiveFromController(OPCode.CONSUMER_STARTWARMUP); + receiver.waitforCompletion(config.getWarmupCount()); + + // It's more realistic for the consumer to signal this. + MapMessage m1 = controllerSession.createMapMessage(); + m1.setInt(CODE, OPCode.PRODUCER_READY.ordinal()); + sendMessageToController(m1); + + MapMessage m2 = controllerSession.createMapMessage(); + m2.setInt(CODE, OPCode.CONSUMER_READY.ordinal()); + sendMessageToController(m2); + } + + public void runReceiver() throws Exception + { + if (_logger.isInfoEnabled()) + { + _logger.info("Consumer: " + id + " Starting iteration......" + "\n"); + } + resetCounters(); + receiver.waitforCompletion(config.getMsgCount()); + MapMessage m = controllerSession.createMapMessage(); + m.setInt(CODE, OPCode.RECEIVED_END_MSG.ordinal()); + sendMessageToController(m); + } + + public void resetCounters() + { + reporter.clear(); + } + + public void sendResults() throws Exception + { + receiveFromController(OPCode.CONSUMER_STOP); + reporter.report(); + + MapMessage m = controllerSession.createMapMessage(); + m.setInt(CODE, OPCode.RECEIVED_CONSUMER_STATS.ordinal()); + m.setDouble(AVG_LATENCY, reporter.getAvgLatency()); + m.setDouble(MIN_LATENCY, reporter.getMinLatency()); + m.setDouble(MAX_LATENCY, reporter.getMaxLatency()); + m.setDouble(STD_DEV, reporter.getStdDev()); + m.setDouble(CONS_RATE, reporter.getRate()); + m.setLong(MSG_COUNT, reporter.getSampleSize()); + sendMessageToController(m); + + reporter.log(new StringBuilder("Total Msgs Received : ").append(reporter.getSampleSize()).toString()); + reporter.log(new StringBuilder("Consumer rate : "). + append(config.getDecimalFormat().format(reporter.getRate())). + append(" msg/sec").toString()); + reporter.log(new StringBuilder("Avg Latency : "). + append(config.getDecimalFormat().format(reporter.getAvgLatency())). + append(" ms").toString()); + reporter.log(new StringBuilder("Min Latency : "). + append(config.getDecimalFormat().format(reporter.getMinLatency())). + append(" ms").toString()); + reporter.log(new StringBuilder("Max Latency : "). + append(config.getDecimalFormat().format(reporter.getMaxLatency())). + append(" ms").toString()); + if (config.isPrintStdDev()) + { + reporter.log(new StringBuilder("Std Dev : "). + append(reporter.getStdDev()).toString()); + } + } + + public void run() + { + try + { + setUp(); + warmup(); + boolean nextIteration = true; + while (nextIteration) + { + System.out.println("=========================================================\n"); + System.out.println("Consumer: " + id + " starting a new iteration ......\n"); + runReceiver(); + sendResults(); + nextIteration = continueTest(); + } + tearDown(); + } + catch(Exception e) + { + handleError(e,"Error when running test"); + } + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + } + + public static void main(String[] args) throws Exception + { + TestConfiguration config = new JVMArgConfiguration(); + MercuryReporter reporter= new MercuryReporter(MercuryThroughputAndLatency.class,System.out,10,true); + String scriptId = (args.length == 1) ? args[0] : ""; + int conCount = config.getConnectionCount(); + final CountDownLatch testCompleted = new CountDownLatch(conCount); + for (int i=0; i < conCount; i++) + { + final MercuryConsumerController cons = new MercuryConsumerController(config, reporter, scriptId + i); + Runnable r = new Runnable() + { + public void run() + { + cons.run(); + testCompleted.countDown(); + } + }; + + Thread t; + try + { + t = Threading.getThreadFactory().createThread(r); + } + catch(Exception e) + { + throw new Error("Error creating consumer thread",e); + } + t.start(); + } + testCompleted.await(); + reporter.log("Consumers have completed the test......\n"); + } +} \ No newline at end of file diff --git a/java/tools/src/main/java/org/apache/qpid/tools/MercuryProducerController.java b/java/tools/src/main/java/org/apache/qpid/tools/MercuryProducerController.java new file mode 100644 index 0000000000..02377bb853 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/MercuryProducerController.java @@ -0,0 +1,210 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.util.concurrent.CountDownLatch; + +import javax.jms.MapMessage; + +import org.apache.qpid.thread.Threading; +import org.apache.qpid.tools.report.MercuryReporter; +import org.apache.qpid.tools.report.MercuryReporter.MercuryThroughput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * PerfProducer sends an x no of messages in warmup mode and wait for a confirmation + * from the consumer that it has successfully consumed them and ready to start the + * test. It will start sending y no of messages and each message will contain a time + * stamp. This will be used at the receiving end to measure the latency. + * + * This is done with the assumption that both consumer and producer are running on + * the same machine or different machines which have time synced using a time server. + * + * This test also calculates the producer rate as follows. + * rate = msg_count/(time_before_sending_msgs - time_after_sending_msgs) + * + * All throughput rates are given as msg/sec so the rates are multiplied by 1000. + * + * Rajith - Producer rate is not an accurate perf metric IMO. + * It is heavily inlfuenced by any in memory buffering. + * System throughput and latencies calculated by the PerfConsumer are more realistic + * numbers. + * + * Answer by rajith : I agree about in memory buffering affecting rates. But Based on test runs + * I have done so far, it seems quite useful to compute the producer rate as it gives an + * indication of how the system behaves. For ex if there is a gap between producer and consumer rates + * you could clearly see the higher latencies and when producer and consumer rates are very close, + * latency is good. + * + */ +public class MercuryProducerController extends MercuryBase +{ + private static final Logger _logger = LoggerFactory.getLogger(MercuryProducerController.class); + MercuryReporter reporter; + QpidSend sender; + + public MercuryProducerController(TestConfiguration config, MercuryReporter reporter, String prefix) + { + super(config,prefix); + this.reporter = reporter; + System.out.println("Producer ID : " + id); + } + + public void setUp() throws Exception + { + super.setUp(); + sender = new QpidSend(reporter,config, con,dest); + sender.setUp(); + MapMessage m = controllerSession.createMapMessage(); + m.setInt(CODE, OPCode.REGISTER_PRODUCER.ordinal()); + sendMessageToController(m); + } + + public void warmup()throws Exception + { + receiveFromController(OPCode.PRODUCER_STARTWARMUP); + if (_logger.isInfoEnabled()) + { + _logger.info("Producer: " + id + " Warming up......"); + } + sender.send(config.getWarmupCount()); + sender.sendEndMessage(); + } + + public void runSender() throws Exception + { + resetCounters(); + receiveFromController(OPCode.PRODUCER_START); + sender.send(config.getMsgCount()); + } + + public void resetCounters() + { + sender.resetCounters(); + } + + public void sendResults() throws Exception + { + MapMessage msg = controllerSession.createMapMessage(); + msg.setInt(CODE, OPCode.RECEIVED_PRODUCER_STATS.ordinal()); + msg.setDouble(PROD_RATE, reporter.getRate()); + sendMessageToController(msg); + reporter.log(new StringBuilder("Producer rate: "). + append(config.getDecimalFormat().format(reporter.getRate())). + append(" msg/sec"). + toString()); + } + + @Override + public void tearDown() throws Exception + { + sender.tearDown(); + super.tearDown(); + } + + public void run() + { + try + { + setUp(); + warmup(); + boolean nextIteration = true; + while (nextIteration) + { + if(_logger.isInfoEnabled()) + { + _logger.info("=========================================================\n"); + _logger.info("Producer: " + id + " starting a new iteration ......\n"); + } + runSender(); + sendResults(); + nextIteration = continueTest(); + } + tearDown(); + } + catch(Exception e) + { + handleError(e,"Error when running test"); + } + } + + public void startControllerIfNeeded() + { + if (!config.isExternalController()) + { + final MercuryTestController controller = new MercuryTestController(config); + Runnable r = new Runnable() + { + public void run() + { + controller.run(); + } + }; + + Thread t; + try + { + t = Threading.getThreadFactory().createThread(r); + } + catch(Exception e) + { + throw new Error("Error creating controller thread",e); + } + t.start(); + } + } + + public static void main(String[] args) throws Exception + { + TestConfiguration config = new JVMArgConfiguration(); + MercuryReporter reporter= new MercuryReporter(MercuryThroughput.class,System.out,10,true); + String scriptId = (args.length == 1) ? args[0] : ""; + int conCount = config.getConnectionCount(); + final CountDownLatch testCompleted = new CountDownLatch(conCount); + for (int i=0; i < conCount; i++) + { + final MercuryProducerController prod = new MercuryProducerController(config, reporter, scriptId + i); + prod.startControllerIfNeeded(); + Runnable r = new Runnable() + { + public void run() + { + prod.run(); + testCompleted.countDown(); + } + }; + + Thread t; + try + { + t = Threading.getThreadFactory().createThread(r); + } + catch(Exception e) + { + throw new Error("Error creating producer thread",e); + } + t.start(); + } + testCompleted.await(); + reporter.log("Producers have completed the test......"); + } +} \ No newline at end of file diff --git a/java/tools/src/main/java/org/apache/qpid/tools/MercuryTestController.java b/java/tools/src/main/java/org/apache/qpid/tools/MercuryTestController.java new file mode 100644 index 0000000000..8c66a1e44d --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/MercuryTestController.java @@ -0,0 +1,450 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.io.FileWriter; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; + +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; + +import org.apache.qpid.client.message.AMQPEncodedMapMessage; +import org.apache.qpid.tools.report.Reporter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Controller coordinates a test run between a number + * of producers and consumers, configured via -Dprod_count and -Dcons_count. + * + * It waits till all the producers and consumers have registered and then + * conducts a warmup run. Once all consumers and producers have completed + * the warmup run and is ready, it will conduct the actual test run and + * collect all stats from the participants and calculates the system + * throughput, the avg/min/max for producer rates, consumer rates and latency. + * + * These stats are then printed to std out. + * The Controller also prints events to std out to give a running account + * of the test run in progress. Ex registering of participants, starting warmup ..etc. + * This allows a scripting tool to monitor the progress. + * + * The Controller can be run in two modes. + * 1. A single test run (default) where it just runs until the message count specified + * for the producers via -Dmsg_count is sent and received. + * + * 2. Time based, configured via -Dduration=x, where x is in mins. + * In this mode, the Controller repeatedly cycles through the tests (after an initial + * warmup run) until the desired time is reached. If a test run is in progress + * and the time is up, it will allow the run the complete. + * + * After each iteration, the stats will be printed out in csv format to a separate log file. + * System throughput is calculated as follows + * totalMsgCount/(totalTestTime) + */ +public class MercuryTestController extends MercuryBase implements MessageListener +{ + private static final Logger _logger = LoggerFactory.getLogger(MercuryProducerController.class); + + enum TestMode { SINGLE_RUN, TIME_BASED }; + + TestMode testMode = TestMode.SINGLE_RUN; + + long totalTestTime; + + private double avgSystemLatency = 0.0; + private double minSystemLatency = Double.MAX_VALUE; + private double maxSystemLatency = 0; + private double avgSystemLatencyStdDev = 0.0; + + private double avgSystemConsRate = 0.0; + private double maxSystemConsRate = 0.0; + private double minSystemConsRate = Double.MAX_VALUE; + + private double avgSystemProdRate = 0.0; + private double maxSystemProdRate = 0.0; + private double minSystemProdRate = Double.MAX_VALUE; + + private long totalMsgCount = 0; + private double totalSystemThroughput = 0.0; + + private int consumerCount = Integer.getInteger("cons_count", 1); + private int producerCount = Integer.getInteger("prod_count", 1); + private int duration = Integer.getInteger("duration", -1); // in mins + private Map consumers; + private Map producers; + + private CountDownLatch consRegistered; + private CountDownLatch prodRegistered; + private CountDownLatch consReady; + private CountDownLatch prodReady; + private CountDownLatch receivedEndMsg; + private CountDownLatch receivedConsStats; + private CountDownLatch receivedProdStats; + + private MessageConsumer consumer; + private boolean printStdDev = false; + private FileWriter writer; + private Reporter report; + + public MercuryTestController(TestConfiguration config) + { + super(config,""); + + consumers = new ConcurrentHashMap(consumerCount); + producers = new ConcurrentHashMap(producerCount); + + consRegistered = new CountDownLatch(consumerCount); + prodRegistered = new CountDownLatch(producerCount); + consReady = new CountDownLatch(consumerCount); + prodReady = new CountDownLatch(producerCount); + printStdDev = config.isPrintStdDev(); + testMode = (duration == -1) ? TestMode.SINGLE_RUN : TestMode.TIME_BASED; + } + + public void setUp() throws Exception + { + super.setUp(); + if (testMode == TestMode.TIME_BASED) + { + writer = new FileWriter("stats-csv.log"); + } + consumer = controllerSession.createConsumer(controllerQueue); + report.log("\nController: " + producerCount + " producers are expected"); + report.log("Controller: " + consumerCount + " consumers are expected \n"); + consumer.setMessageListener(this); + consRegistered.await(); + prodRegistered.await(); + report.log("\nController: All producers and consumers have registered......\n"); + } + + public void warmup() throws Exception + { + report.log("Controller initiating warm up sequence......"); + sendMessageToNodes(OPCode.CONSUMER_STARTWARMUP,consumers.values()); + sendMessageToNodes(OPCode.PRODUCER_STARTWARMUP,producers.values()); + prodReady.await(); + consReady.await(); + report.log("\nController : All producers and consumers are ready to start the test......\n"); + } + + public void startTest() throws Exception + { + resetCounters(); + report.log("\nController Starting test......"); + long start = Clock.getTime(); + sendMessageToNodes(OPCode.PRODUCER_START,producers.values()); + receivedEndMsg.await(); + totalTestTime = Clock.getTime() - start; + sendMessageToNodes(OPCode.CONSUMER_STOP,consumers.values()); + receivedProdStats.await(); + receivedConsStats.await(); + } + + public void resetCounters() + { + minSystemLatency = Double.MAX_VALUE; + maxSystemLatency = 0; + maxSystemConsRate = 0.0; + minSystemConsRate = Double.MAX_VALUE; + maxSystemProdRate = 0.0; + minSystemProdRate = Double.MAX_VALUE; + + totalMsgCount = 0; + + receivedConsStats = new CountDownLatch(consumerCount); + receivedProdStats = new CountDownLatch(producerCount); + receivedEndMsg = new CountDownLatch(producerCount); + } + + public void calcStats() throws Exception + { + double totLatency = 0.0; + double totStdDev = 0.0; + double totalConsRate = 0.0; + double totalProdRate = 0.0; + + MapMessage conStat = null; // for error handling + try + { + for (MapMessage m: consumers.values()) + { + conStat = m; + minSystemLatency = Math.min(minSystemLatency,m.getDouble(MIN_LATENCY)); + maxSystemLatency = Math.max(maxSystemLatency,m.getDouble(MAX_LATENCY)); + totLatency = totLatency + m.getDouble(AVG_LATENCY); + totStdDev = totStdDev + m.getDouble(STD_DEV); + + minSystemConsRate = Math.min(minSystemConsRate,m.getDouble(CONS_RATE)); + maxSystemConsRate = Math.max(maxSystemConsRate,m.getDouble(CONS_RATE)); + totalConsRate = totalConsRate + m.getDouble(CONS_RATE); + + totalMsgCount = totalMsgCount + m.getLong(MSG_COUNT); + } + } + catch(Exception e) + { + System.err.println("Error calculating stats from Consumer : " + conStat); + } + + + MapMessage prodStat = null; // for error handling + try + { + for (MapMessage m: producers.values()) + { + prodStat = m; + minSystemProdRate = Math.min(minSystemProdRate,m.getDouble(PROD_RATE)); + maxSystemProdRate = Math.max(maxSystemProdRate,m.getDouble(PROD_RATE)); + totalProdRate = totalProdRate + m.getDouble(PROD_RATE); + } + } + catch(Exception e) + { + System.err.println("Error calculating stats from Producer : " + conStat); + } + + avgSystemLatency = totLatency/consumers.size(); + avgSystemLatencyStdDev = totStdDev/consumers.size(); + avgSystemConsRate = totalConsRate/consumers.size(); + avgSystemProdRate = totalProdRate/producers.size(); + + report.log("Total test time : " + totalTestTime + " in " + Clock.getPrecision()); + + totalSystemThroughput = (totalMsgCount*Clock.convertToSecs()/totalTestTime); + } + + public void printResults() throws Exception + { + report.log(new StringBuilder("Total Msgs Received : ").append(totalMsgCount).toString()); + report.log(new StringBuilder("System Throughput : "). + append(config.getDecimalFormat().format(totalSystemThroughput)). + append(" msg/sec").toString()); + report.log(new StringBuilder("Avg Consumer rate : "). + append(config.getDecimalFormat().format(avgSystemConsRate)). + append(" msg/sec").toString()); + report.log(new StringBuilder("Min Consumer rate : "). + append(config.getDecimalFormat().format(minSystemConsRate)). + append(" msg/sec").toString()); + report.log(new StringBuilder("Max Consumer rate : "). + append(config.getDecimalFormat().format(maxSystemConsRate)). + append(" msg/sec").toString()); + + report.log(new StringBuilder("Avg Producer rate : "). + append(config.getDecimalFormat().format(avgSystemProdRate)). + append(" msg/sec").toString()); + report.log(new StringBuilder("Min Producer rate : "). + append(config.getDecimalFormat().format(minSystemProdRate)). + append(" msg/sec").toString()); + report.log(new StringBuilder("Max Producer rate : "). + append(config.getDecimalFormat().format(maxSystemProdRate)). + append(" msg/sec").toString()); + + report.log(new StringBuilder("Avg System Latency : "). + append(config.getDecimalFormat().format(avgSystemLatency)). + append(" ms").toString()); + report.log(new StringBuilder("Min System Latency : "). + append(config.getDecimalFormat().format(minSystemLatency)). + append(" ms").toString()); + report.log(new StringBuilder("Max System Latency : "). + append(config.getDecimalFormat().format(maxSystemLatency)). + append(" ms").toString()); + if (printStdDev) + { + report.log(new StringBuilder("Avg System Std Dev : "). + append(avgSystemLatencyStdDev).toString()); + } + } + + private synchronized void sendMessageToNodes(OPCode code,Collection nodes) throws Exception + { + report.log("\nController: Sending code " + code); + MessageProducer tmpProd = controllerSession.createProducer(null); + MapMessage msg = controllerSession.createMapMessage(); + msg.setInt(CODE, code.ordinal()); + for (MapMessage node : nodes) + { + if (node.getString(REPLY_ADDR) == null) + { + report.log("REPLY_ADDR is null " + node); + } + else + { + report.log("Controller: Sending " + code + " to " + node.getString(REPLY_ADDR)); + } + tmpProd.send(controllerSession.createQueue(node.getString(REPLY_ADDR)), msg); + } + } + + public void onMessage(Message msg) + { + try + { + MapMessage m = (MapMessage)msg; + OPCode code = OPCode.values()[m.getInt(CODE)]; + + report.log("\n---------Controller Received Code : " + code); + report.log("---------Data : " + ((AMQPEncodedMapMessage)m).getMap()); + + switch (code) + { + case REGISTER_CONSUMER : + if (consRegistered.getCount() == 0) + { + report.log("Warning : Expected number of consumers have already registered," + + "ignoring extra consumer"); + break; + } + consumers.put(m.getString(ID),m); + consRegistered.countDown(); + break; + + case REGISTER_PRODUCER : + if (prodRegistered.getCount() == 0) + { + report.log("Warning : Expected number of producers have already registered," + + "ignoring extra producer"); + break; + } + producers.put(m.getString(ID),m); + prodRegistered.countDown(); + break; + + case CONSUMER_READY : + consReady.countDown(); + break; + + case PRODUCER_READY : + prodReady.countDown(); + break; + + case RECEIVED_END_MSG : + receivedEndMsg.countDown(); + break; + + case RECEIVED_CONSUMER_STATS : + consumers.put(m.getString(ID),m); + receivedConsStats.countDown(); + break; + + case RECEIVED_PRODUCER_STATS : + producers.put(m.getString(ID),m); + receivedProdStats.countDown(); + break; + + default: + throw new Exception("Invalid OPCode " + code); + } + } + catch (Exception e) + { + handleError(e,"Error when receiving messages " + msg); + } + } + + public void run() + { + try + { + setUp(); + warmup(); + if (testMode == TestMode.SINGLE_RUN) + { + startTest(); + calcStats(); + printResults(); + } + else + { + long startTime = Clock.getTime(); + long timeLimit = duration * 60 * 1000; // duration is in mins. + boolean nextIteration = true; + while (nextIteration) + { + startTest(); + calcStats(); + writeStatsToFile(); + if (Clock.getTime() - startTime < timeLimit) + { + sendMessageToNodes(OPCode.CONTINUE_TEST,consumers.values()); + sendMessageToNodes(OPCode.CONTINUE_TEST,producers.values()); + nextIteration = true; + } + else + { + nextIteration = false; + } + } + } + tearDown(); + + } + catch(Exception e) + { + handleError(e,"Error when running test"); + } + } + + @Override + public void tearDown() throws Exception { + report.log("Controller: Completed the test......\n"); + if (testMode == TestMode.TIME_BASED) + { + writer.close(); + } + sendMessageToNodes(OPCode.STOP_TEST,consumers.values()); + sendMessageToNodes(OPCode.STOP_TEST,producers.values()); + super.tearDown(); + } + + public void writeStatsToFile() throws Exception + { + writer.append(String.valueOf(totalMsgCount)).append(","); + writer.append(config.getDecimalFormat().format(totalSystemThroughput)).append(","); + writer.append(config.getDecimalFormat().format(avgSystemConsRate)).append(","); + writer.append(config.getDecimalFormat().format(minSystemConsRate)).append(","); + writer.append(config.getDecimalFormat().format(maxSystemConsRate)).append(","); + writer.append(config.getDecimalFormat().format(avgSystemProdRate)).append(","); + writer.append(config.getDecimalFormat().format(minSystemProdRate)).append(","); + writer.append(config.getDecimalFormat().format(maxSystemProdRate)).append(","); + writer.append(config.getDecimalFormat().format(avgSystemLatency)).append(","); + writer.append(config.getDecimalFormat().format(minSystemLatency)).append(","); + writer.append(config.getDecimalFormat().format(maxSystemLatency)); + if (printStdDev) + { + writer.append(",").append(String.valueOf(avgSystemLatencyStdDev)); + } + writer.append("\n"); + writer.flush(); + } + + public static void main(String[] args) + { + TestConfiguration config = new JVMArgConfiguration(); + MercuryTestController controller = new MercuryTestController(config); + controller.run(); + } +} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java deleted file mode 100644 index 121e94cea1..0000000000 --- a/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.tools; - -import java.net.InetAddress; -import java.text.DecimalFormat; -import java.util.UUID; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.MapMessage; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -import org.apache.qpid.client.AMQAnyDestination; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession_0_10; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.messaging.Address; - -public class PerfBase -{ - public final static String CODE = "CODE"; - public final static String ID = "ID"; - public final static String REPLY_ADDR = "REPLY_ADDR"; - public final static String MAX_LATENCY = "MAX_LATENCY"; - public final static String MIN_LATENCY = "MIN_LATENCY"; - public final static String AVG_LATENCY = "AVG_LATENCY"; - public final static String STD_DEV = "STD_DEV"; - public final static String CONS_RATE = "CONS_RATE"; - public final static String PROD_RATE = "PROD_RATE"; - public final static String MSG_COUNT = "MSG_COUNT"; - public final static String TIMESTAMP = "Timestamp"; - - String CONTROLLER_ADDR = System.getProperty("CONT_ADDR","CONTROLLER;{create: always, node:{x-declare:{auto-delete:true}}}"); - - TestParams params; - Connection con; - Session session; - Session controllerSession; - Destination dest; - Destination myControlQueue; - Destination controllerQueue; - DecimalFormat df = new DecimalFormat("###.##"); - String id; - String myControlQueueAddr; - - MessageProducer sendToController; - MessageConsumer receiveFromController; - String prefix = ""; - - enum OPCode { - REGISTER_CONSUMER, REGISTER_PRODUCER, - PRODUCER_STARTWARMUP, CONSUMER_STARTWARMUP, - CONSUMER_READY, PRODUCER_READY, - PRODUCER_START, - RECEIVED_END_MSG, CONSUMER_STOP, - RECEIVED_PRODUCER_STATS, RECEIVED_CONSUMER_STATS, - CONTINUE_TEST, STOP_TEST - }; - - enum MessageType { - BYTES, TEXT, MAP, OBJECT; - - public static MessageType getType(String s) throws Exception - { - if ("text".equalsIgnoreCase(s)) - { - return TEXT; - } - else if ("bytes".equalsIgnoreCase(s)) - { - return BYTES; - } - /*else if ("map".equalsIgnoreCase(s)) - { - return MAP; - } - else if ("object".equalsIgnoreCase(s)) - { - return OBJECT; - }*/ - else - { - throw new Exception("Unsupported message type"); - } - } - }; - - MessageType msgType = MessageType.BYTES; - - public PerfBase(String prefix) - { - params = new TestParams(); - String host = ""; - try - { - host = InetAddress.getLocalHost().getHostName(); - } - catch (Exception e) - { - } - id = host + "-" + UUID.randomUUID().toString(); - this.prefix = prefix; - this.myControlQueueAddr = id + ";{create: always}"; - } - - public void setUp() throws Exception - { - if (params.getHost().equals("") || params.getPort() == -1) - { - con = new AMQConnection(params.getUrl()); - } - else - { - con = new AMQConnection(params.getHost(),params.getPort(),"guest","guest","test","test"); - } - con.start(); - session = con.createSession(params.isTransacted(), - params.isTransacted()? Session.SESSION_TRANSACTED:params.getAckMode()); - - controllerSession = con.createSession(false, Session.AUTO_ACKNOWLEDGE); - - dest = createDestination(); - controllerQueue = new AMQAnyDestination(CONTROLLER_ADDR); - myControlQueue = session.createQueue(myControlQueueAddr); - msgType = MessageType.getType(params.getMessageType()); - System.out.println("Using " + msgType + " messages"); - - sendToController = controllerSession.createProducer(controllerQueue); - receiveFromController = controllerSession.createConsumer(myControlQueue); - } - - private Destination createDestination() throws Exception - { - if (params.isUseUniqueDests()) - { - System.out.println("Prefix : " + prefix); - Address addr = Address.parse(params.getAddress()); - AMQAnyDestination temp = new AMQAnyDestination(params.getAddress()); - int type = ((AMQSession_0_10)session).resolveAddressType(temp); - - if ( type == AMQDestination.TOPIC_TYPE) - { - addr = new Address(addr.getName(),addr.getSubject() + "." + prefix,addr.getOptions()); - System.out.println("Setting subject : " + addr); - } - else - { - addr = new Address(addr.getName() + "_" + prefix,addr.getSubject(),addr.getOptions()); - System.out.println("Setting name : " + addr); - } - - return new AMQAnyDestination(addr); - } - else - { - return new AMQAnyDestination(params.getAddress()); - } - } - - public synchronized void sendMessageToController(MapMessage m) throws Exception - { - m.setString(ID, id); - m.setString(REPLY_ADDR,myControlQueueAddr); - sendToController.send(m); - } - - public void receiveFromController(OPCode expected) throws Exception - { - MapMessage m = (MapMessage)receiveFromController.receive(); - OPCode code = OPCode.values()[m.getInt(CODE)]; - System.out.println("Received Code : " + code); - if (expected != code) - { - throw new Exception("Expected OPCode : " + expected + " but received : " + code); - } - - } - - public boolean continueTest() throws Exception - { - MapMessage m = (MapMessage)receiveFromController.receive(); - OPCode code = OPCode.values()[m.getInt(CODE)]; - System.out.println("Received Code : " + code); - return (code == OPCode.CONTINUE_TEST); - } - - public void tearDown() throws Exception - { - session.close(); - controllerSession.close(); - con.close(); - } - - public void handleError(Exception e,String msg) - { - StringBuilder sb = new StringBuilder(); - sb.append(msg); - sb.append(" "); - sb.append(e.getMessage()); - System.err.println(sb.toString()); - e.printStackTrace(); - } -} - diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java deleted file mode 100644 index b63892bb51..0000000000 --- a/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.tools; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import javax.jms.MapMessage; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.TextMessage; - -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.thread.Threading; - -/** - * PerfConsumer will receive x no of messages in warmup mode. - * Once it receives the Start message it will then signal the PerfProducer. - * It will start recording stats from the first message it receives after - * the warmup mode is done. - * - * The following calculations are done. - * The important numbers to look at is - * a) Avg Latency - * b) System throughput. - * - * Latency. - * ========= - * Currently this test is written with the assumption that either - * a) The Perf Producer and Consumer are on the same machine - * b) They are on separate machines that have their time synced via a Time Server - * - * In order to calculate latency the producer inserts a timestamp - * when the message is sent. The consumer will note the current time the message is - * received and will calculate the latency as follows - * latency = rcvdTime - msg.getJMSTimestamp() - * - * Through out the test it will keep track of the max and min latency to show the - * variance in latencies. - * - * Avg latency is measured by adding all latencies and dividing by the total msgs. - * - * Throughput - * =========== - * Consumer rate is calculated as - * rcvdMsgCount/(rcvdTime - startTime) - * - * Note that the testStartTime referes to when the producer sent the first message - * and startTime is when the consumer first received a message. - * - * rcvdTime keeps track of when the last message is received. - * - * All throughput rates are given as msg/sec so the rates are multiplied by 1000. - * - */ - -public class PerfConsumer extends PerfBase implements MessageListener -{ - MessageConsumer consumer; - long maxLatency = 0; - long minLatency = Long.MAX_VALUE; - long totalLatency = 0; // to calculate avg latency. - int rcvdMsgCount = 0; - long startTime = 0; // to measure consumer throughput - long rcvdTime = 0; - boolean transacted = false; - int transSize = 0; - - boolean printStdDev = false; - List sample; - - final Object lock = new Object(); - - public PerfConsumer(String prefix) - { - super(prefix); - System.out.println("Consumer ID : " + id); - } - - public void setUp() throws Exception - { - super.setUp(); - consumer = session.createConsumer(dest); - System.out.println("Consumer: " + id + " Receiving messages from : " + ((AMQDestination)dest).getQueueName() + "\n"); - - // Storing the following two for efficiency - transacted = params.isTransacted(); - transSize = params.getTransactionSize(); - printStdDev = params.isPrintStdDev(); - MapMessage m = controllerSession.createMapMessage(); - m.setInt(CODE, OPCode.REGISTER_CONSUMER.ordinal()); - sendMessageToController(m); - } - - public void warmup()throws Exception - { - receiveFromController(OPCode.CONSUMER_STARTWARMUP); - Message msg = consumer.receive(); - // This is to ensure we drain the queue before we start the actual test. - while ( msg != null) - { - if (msg.getBooleanProperty("End") == true) - { - // It's more realistic for the consumer to signal this. - MapMessage m = controllerSession.createMapMessage(); - m.setInt(CODE, OPCode.PRODUCER_READY.ordinal()); - sendMessageToController(m); - } - msg = consumer.receive(1000); - } - - if (params.isTransacted()) - { - session.commit(); - } - - MapMessage m = controllerSession.createMapMessage(); - m.setInt(CODE, OPCode.CONSUMER_READY.ordinal()); - sendMessageToController(m); - consumer.setMessageListener(this); - } - - public void startTest() throws Exception - { - System.out.println("Consumer: " + id + " Starting test......" + "\n"); - resetCounters(); - } - - public void resetCounters() - { - rcvdMsgCount = 0; - maxLatency = 0; - minLatency = Long.MAX_VALUE; - totalLatency = 0; - if (printStdDev) - { - sample = null; - sample = new ArrayList(params.getMsgCount()); - } - } - - public void sendResults() throws Exception - { - receiveFromController(OPCode.CONSUMER_STOP); - - double avgLatency = (double)totalLatency/(double)rcvdMsgCount; - double consRate = (double)rcvdMsgCount*Clock.convertToSecs()/(double)(rcvdTime - startTime); - double stdDev = 0.0; - if (printStdDev) - { - stdDev = calculateStdDev(avgLatency); - } - MapMessage m = controllerSession.createMapMessage(); - m.setInt(CODE, OPCode.RECEIVED_CONSUMER_STATS.ordinal()); - m.setDouble(AVG_LATENCY, avgLatency/Clock.convertToMiliSecs()); - m.setDouble(MIN_LATENCY,minLatency/Clock.convertToMiliSecs()); - m.setDouble(MAX_LATENCY,maxLatency/Clock.convertToMiliSecs()); - m.setDouble(STD_DEV, stdDev/Clock.convertToMiliSecs()); - m.setDouble(CONS_RATE, consRate); - m.setLong(MSG_COUNT, rcvdMsgCount); - sendMessageToController(m); - - System.out.println(new StringBuilder("Total Msgs Received : ").append(rcvdMsgCount).toString()); - System.out.println(new StringBuilder("Consumer rate : "). - append(df.format(consRate)). - append(" msg/sec").toString()); - System.out.println(new StringBuilder("Avg Latency : "). - append(df.format(avgLatency/Clock.convertToMiliSecs())). - append(" ms").toString()); - System.out.println(new StringBuilder("Min Latency : "). - append(df.format(minLatency/Clock.convertToMiliSecs())). - append(" ms").toString()); - System.out.println(new StringBuilder("Max Latency : "). - append(df.format(maxLatency/Clock.convertToMiliSecs())). - append(" ms").toString()); - if (printStdDev) - { - System.out.println(new StringBuilder("Std Dev : "). - append(stdDev/Clock.convertToMiliSecs()).toString()); - } - } - - public double calculateStdDev(double mean) - { - double v = 0; - for (double latency: sample) - { - v = v + Math.pow((latency-mean), 2); - } - v = v/sample.size(); - return Math.round(Math.sqrt(v)); - } - - public void onMessage(Message msg) - { - try - { - // To figure out the decoding overhead of text - if (msgType == MessageType.TEXT) - { - ((TextMessage)msg).getText(); - } - - if (msg.getBooleanProperty("End")) - { - MapMessage m = controllerSession.createMapMessage(); - m.setInt(CODE, OPCode.RECEIVED_END_MSG.ordinal()); - sendMessageToController(m); - } - else - { - rcvdTime = Clock.getTime(); - rcvdMsgCount ++; - - if (rcvdMsgCount == 1) - { - startTime = rcvdTime; - } - - if (transacted && (rcvdMsgCount % transSize == 0)) - { - session.commit(); - } - - long latency = rcvdTime - msg.getLongProperty(TIMESTAMP); - maxLatency = Math.max(maxLatency, latency); - minLatency = Math.min(minLatency, latency); - totalLatency = totalLatency + latency; - if (printStdDev) - { - sample.add(latency); - } - } - - } - catch(Exception e) - { - handleError(e,"Error when receiving messages"); - } - - } - - public void run() - { - try - { - setUp(); - warmup(); - boolean nextIteration = true; - while (nextIteration) - { - System.out.println("=========================================================\n"); - System.out.println("Consumer: " + id + " starting a new iteration ......\n"); - startTest(); - sendResults(); - nextIteration = continueTest(); - } - tearDown(); - } - catch(Exception e) - { - handleError(e,"Error when running test"); - } - } - - @Override - public void tearDown() throws Exception - { - super.tearDown(); - } - - public static void main(String[] args) throws InterruptedException - { - String scriptId = (args.length == 1) ? args[0] : ""; - int conCount = Integer.getInteger("con_count",1); - final CountDownLatch testCompleted = new CountDownLatch(conCount); - for (int i=0; i < conCount; i++) - { - - final PerfConsumer cons = new PerfConsumer(scriptId + i); - Runnable r = new Runnable() - { - public void run() - { - cons.run(); - testCompleted.countDown(); - } - }; - - Thread t; - try - { - t = Threading.getThreadFactory().createThread(r); - } - catch(Exception e) - { - throw new Error("Error creating consumer thread",e); - } - t.start(); - - } - testCompleted.await(); - System.out.println("Consumers have completed the test......\n"); - } -} \ No newline at end of file diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java deleted file mode 100644 index ac6129ab68..0000000000 --- a/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.tools; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.CountDownLatch; - -import javax.jms.BytesMessage; -import javax.jms.DeliveryMode; -import javax.jms.MapMessage; -import javax.jms.Message; -import javax.jms.MessageProducer; - -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.thread.Threading; - -/** - * PerfProducer sends an x no of messages in warmup mode and wait for a confirmation - * from the consumer that it has successfully consumed them and ready to start the - * test. It will start sending y no of messages and each message will contain a time - * stamp. This will be used at the receiving end to measure the latency. - * - * This is done with the assumption that both consumer and producer are running on - * the same machine or different machines which have time synced using a time server. - * - * This test also calculates the producer rate as follows. - * rate = msg_count/(time_before_sending_msgs - time_after_sending_msgs) - * - * All throughput rates are given as msg/sec so the rates are multiplied by 1000. - * - * Rajith - Producer rate is not an accurate perf metric IMO. - * It is heavily inlfuenced by any in memory buffering. - * System throughput and latencies calculated by the PerfConsumer are more realistic - * numbers. - * - * Answer by rajith : I agree about in memory buffering affecting rates. But Based on test runs - * I have done so far, it seems quite useful to compute the producer rate as it gives an - * indication of how the system behaves. For ex if there is a gap between producer and consumer rates - * you could clearly see the higher latencies and when producer and consumer rates are very close, - * latency is good. - * - */ -public class PerfProducer extends PerfBase -{ - private static long SEC = 60000; - - MessageProducer producer; - Message msg; - Object payload; - List payloads; - boolean cacheMsg = false; - boolean randomMsgSize = false; - boolean durable = false; - Random random; - int msgSizeRange = 1024; - boolean rateLimitProducer = false; - double rateFactor = 0.4; - double rate = 0.0; - - public PerfProducer(String prefix) - { - super(prefix); - System.out.println("Producer ID : " + id); - } - - public void setUp() throws Exception - { - super.setUp(); - durable = params.isDurable(); - rateLimitProducer = params.getRate() > 0 ? true : false; - if (rateLimitProducer) - { - System.out.println("The test will attempt to limit the producer to " + params.getRate() + " msg/sec"); - } - - // if message caching is enabled we pre create the message - // else we pre create the payload - if (params.isCacheMessage()) - { - cacheMsg = true; - msg = createMessage(createPayload(params.getMsgSize())); - msg.setJMSDeliveryMode(durable? - DeliveryMode.PERSISTENT : - DeliveryMode.NON_PERSISTENT - ); - } - else if (params.isRandomMsgSize()) - { - random = new Random(20080921); - randomMsgSize = true; - msgSizeRange = params.getMsgSize(); - payloads = new ArrayList(msgSizeRange); - - for (int i=0; i < msgSizeRange; i++) - { - payloads.add(createPayload(i)); - } - } - else - { - payload = createPayload(params.getMsgSize()); - } - - producer = session.createProducer(dest); - System.out.println("Producer: " + id + " Sending messages to: " + ((AMQDestination)dest).getQueueName()); - producer.setDisableMessageID(params.isDisableMessageID()); - producer.setDisableMessageTimestamp(params.isDisableTimestamp()); - - MapMessage m = controllerSession.createMapMessage(); - m.setInt(CODE, OPCode.REGISTER_PRODUCER.ordinal()); - sendMessageToController(m); - } - - Object createPayload(int size) - { - if (msgType == MessageType.TEXT) - { - return MessageFactory.createMessagePayload(size); - } - else - { - return MessageFactory.createMessagePayload(size).getBytes(); - } - } - - Message createMessage(Object payload) throws Exception - { - if (msgType == MessageType.TEXT) - { - return session.createTextMessage((String)payload); - } - else - { - BytesMessage m = session.createBytesMessage(); - m.writeBytes((byte[])payload); - return m; - } - } - - protected Message getNextMessage() throws Exception - { - if (cacheMsg) - { - return msg; - } - else - { - Message m; - - if (!randomMsgSize) - { - m = createMessage(payload); - } - else - { - m = createMessage(payloads.get(random.nextInt(msgSizeRange))); - } - m.setJMSDeliveryMode(durable? - DeliveryMode.PERSISTENT : - DeliveryMode.NON_PERSISTENT - ); - return m; - } - } - - public void warmup()throws Exception - { - receiveFromController(OPCode.PRODUCER_STARTWARMUP); - System.out.println("Producer: " + id + " Warming up......"); - - for (int i=0; i < params.getWarmupCount() -1; i++) - { - producer.send(getNextMessage()); - } - sendEndMessage(); - - if (params.isTransacted()) - { - session.commit(); - } - } - - public void startTest() throws Exception - { - resetCounters(); - receiveFromController(OPCode.PRODUCER_START); - int count = params.getMsgCount(); - boolean transacted = params.isTransacted(); - int tranSize = params.getTransactionSize(); - - long limit = (long)(params.getRate() * rateFactor); // in msecs - long timeLimit = (long)(SEC * rateFactor); // in msecs - - long start = Clock.getTime(); // defaults to nano secs - long interval = start; - for(int i=0; i < count; i++ ) - { - Message msg = getNextMessage(); - msg.setLongProperty(TIMESTAMP, Clock.getTime()); - producer.send(msg); - if ( transacted && ((i+1) % tranSize == 0)) - { - session.commit(); - } - - if (rateLimitProducer && i%limit == 0) - { - long elapsed = (Clock.getTime() - interval)*Clock.convertToMiliSecs(); // in msecs - if (elapsed < timeLimit) - { - Thread.sleep(elapsed); - } - interval = Clock.getTime(); - - } - } - sendEndMessage(); - if ( transacted) - { - session.commit(); - } - long time = Clock.getTime() - start; - rate = (double)count*Clock.convertToSecs()/(double)time; - System.out.println(new StringBuilder("Producer rate: "). - append(df.format(rate)). - append(" msg/sec"). - toString()); - } - - public void resetCounters() - { - - } - - public void sendEndMessage() throws Exception - { - Message msg = session.createMessage(); - msg.setBooleanProperty("End", true); - producer.send(msg); - } - - public void sendResults() throws Exception - { - MapMessage msg = controllerSession.createMapMessage(); - msg.setInt(CODE, OPCode.RECEIVED_PRODUCER_STATS.ordinal()); - msg.setDouble(PROD_RATE, rate); - sendMessageToController(msg); - } - - @Override - public void tearDown() throws Exception - { - super.tearDown(); - } - - public void run() - { - try - { - setUp(); - warmup(); - boolean nextIteration = true; - while (nextIteration) - { - System.out.println("=========================================================\n"); - System.out.println("Producer: " + id + " starting a new iteration ......\n"); - startTest(); - sendResults(); - nextIteration = continueTest(); - } - tearDown(); - } - catch(Exception e) - { - handleError(e,"Error when running test"); - } - } - - public void startControllerIfNeeded() - { - if (!params.isExternalController()) - { - final PerfTestController controller = new PerfTestController(); - Runnable r = new Runnable() - { - public void run() - { - controller.run(); - } - }; - - Thread t; - try - { - t = Threading.getThreadFactory().createThread(r); - } - catch(Exception e) - { - throw new Error("Error creating controller thread",e); - } - t.start(); - } - } - - - public static void main(String[] args) throws InterruptedException - { - String scriptId = (args.length == 1) ? args[0] : ""; - int conCount = Integer.getInteger("con_count",1); - final CountDownLatch testCompleted = new CountDownLatch(conCount); - for (int i=0; i < conCount; i++) - { - final PerfProducer prod = new PerfProducer(scriptId + i); - prod.startControllerIfNeeded(); - Runnable r = new Runnable() - { - public void run() - { - prod.run(); - testCompleted.countDown(); - } - }; - - Thread t; - try - { - t = Threading.getThreadFactory().createThread(r); - } - catch(Exception e) - { - throw new Error("Error creating producer thread",e); - } - t.start(); - } - testCompleted.await(); - System.out.println("Producers have completed the test......"); - } -} \ No newline at end of file diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java deleted file mode 100644 index 5fca1fa4bd..0000000000 --- a/java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.tools; - -import java.io.FileWriter; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; - -import javax.jms.MapMessage; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; - -import org.apache.qpid.client.message.AMQPEncodedMapMessage; - -/** - * The Controller coordinates a test run between a number - * of producers and consumers, configured via -Dprod_count and -Dcons_count. - * - * It waits till all the producers and consumers have registered and then - * conducts a warmup run. Once all consumers and producers have completed - * the warmup run and is ready, it will conduct the actual test run and - * collect all stats from the participants and calculates the system - * throughput, the avg/min/max for producer rates, consumer rates and latency. - * - * These stats are then printed to std out. - * The Controller also prints events to std out to give a running account - * of the test run in progress. Ex registering of participants, starting warmup ..etc. - * This allows a scripting tool to monitor the progress. - * - * The Controller can be run in two modes. - * 1. A single test run (default) where it just runs until the message count specified - * for the producers via -Dmsg_count is sent and received. - * - * 2. Time based, configured via -Dduration=x, where x is in mins. - * In this mode, the Controller repeatedly cycles through the tests (after an initial - * warmup run) until the desired time is reached. If a test run is in progress - * and the time is up, it will allow the run the complete. - * - * After each iteration, the stats will be printed out in csv format to a separate log file. - * System throughput is calculated as follows - * totalMsgCount/(totalTestTime) - */ -public class PerfTestController extends PerfBase implements MessageListener -{ - enum TestMode { SINGLE_RUN, TIME_BASED }; - - TestMode testMode = TestMode.SINGLE_RUN; - - long totalTestTime; - - private double avgSystemLatency = 0.0; - private double minSystemLatency = Double.MAX_VALUE; - private double maxSystemLatency = 0; - private double avgSystemLatencyStdDev = 0.0; - - private double avgSystemConsRate = 0.0; - private double maxSystemConsRate = 0.0; - private double minSystemConsRate = Double.MAX_VALUE; - - private double avgSystemProdRate = 0.0; - private double maxSystemProdRate = 0.0; - private double minSystemProdRate = Double.MAX_VALUE; - - private long totalMsgCount = 0; - private double totalSystemThroughput = 0.0; - - private int consumerCount = Integer.getInteger("cons_count", 1); - private int producerCount = Integer.getInteger("prod_count", 1); - private int duration = Integer.getInteger("duration", -1); // in mins - private Map consumers; - private Map producers; - - private CountDownLatch consRegistered; - private CountDownLatch prodRegistered; - private CountDownLatch consReady; - private CountDownLatch prodReady; - private CountDownLatch receivedEndMsg; - private CountDownLatch receivedConsStats; - private CountDownLatch receivedProdStats; - - private MessageConsumer consumer; - private boolean printStdDev = false; - FileWriter writer; - - public PerfTestController() - { - super(""); - consumers = new ConcurrentHashMap(consumerCount); - producers = new ConcurrentHashMap(producerCount); - - consRegistered = new CountDownLatch(consumerCount); - prodRegistered = new CountDownLatch(producerCount); - consReady = new CountDownLatch(consumerCount); - prodReady = new CountDownLatch(producerCount); - printStdDev = params.isPrintStdDev(); - testMode = (duration == -1) ? TestMode.SINGLE_RUN : TestMode.TIME_BASED; - } - - public void setUp() throws Exception - { - super.setUp(); - if (testMode == TestMode.TIME_BASED) - { - writer = new FileWriter("stats-csv.log"); - } - consumer = controllerSession.createConsumer(controllerQueue); - System.out.println("\nController: " + producerCount + " producers are expected"); - System.out.println("Controller: " + consumerCount + " consumers are expected \n"); - consumer.setMessageListener(this); - consRegistered.await(); - prodRegistered.await(); - System.out.println("\nController: All producers and consumers have registered......\n"); - } - - public void warmup() throws Exception - { - System.out.println("Controller initiating warm up sequence......"); - sendMessageToNodes(OPCode.CONSUMER_STARTWARMUP,consumers.values()); - sendMessageToNodes(OPCode.PRODUCER_STARTWARMUP,producers.values()); - prodReady.await(); - consReady.await(); - System.out.println("\nController : All producers and consumers are ready to start the test......\n"); - } - - public void startTest() throws Exception - { - resetCounters(); - System.out.println("\nController Starting test......"); - long start = Clock.getTime(); - sendMessageToNodes(OPCode.PRODUCER_START,producers.values()); - receivedEndMsg.await(); - totalTestTime = Clock.getTime() - start; - sendMessageToNodes(OPCode.CONSUMER_STOP,consumers.values()); - receivedProdStats.await(); - receivedConsStats.await(); - } - - public void resetCounters() - { - minSystemLatency = Double.MAX_VALUE; - maxSystemLatency = 0; - maxSystemConsRate = 0.0; - minSystemConsRate = Double.MAX_VALUE; - maxSystemProdRate = 0.0; - minSystemProdRate = Double.MAX_VALUE; - - totalMsgCount = 0; - - receivedConsStats = new CountDownLatch(consumerCount); - receivedProdStats = new CountDownLatch(producerCount); - receivedEndMsg = new CountDownLatch(producerCount); - } - - public void calcStats() throws Exception - { - double totLatency = 0.0; - double totStdDev = 0.0; - double totalConsRate = 0.0; - double totalProdRate = 0.0; - - MapMessage conStat = null; // for error handling - try - { - for (MapMessage m: consumers.values()) - { - conStat = m; - minSystemLatency = Math.min(minSystemLatency,m.getDouble(MIN_LATENCY)); - maxSystemLatency = Math.max(maxSystemLatency,m.getDouble(MAX_LATENCY)); - totLatency = totLatency + m.getDouble(AVG_LATENCY); - totStdDev = totStdDev + m.getDouble(STD_DEV); - - minSystemConsRate = Math.min(minSystemConsRate,m.getDouble(CONS_RATE)); - maxSystemConsRate = Math.max(maxSystemConsRate,m.getDouble(CONS_RATE)); - totalConsRate = totalConsRate + m.getDouble(CONS_RATE); - - totalMsgCount = totalMsgCount + m.getLong(MSG_COUNT); - } - } - catch(Exception e) - { - System.out.println("Error calculating stats from Consumer : " + conStat); - } - - - MapMessage prodStat = null; // for error handling - try - { - for (MapMessage m: producers.values()) - { - prodStat = m; - minSystemProdRate = Math.min(minSystemProdRate,m.getDouble(PROD_RATE)); - maxSystemProdRate = Math.max(maxSystemProdRate,m.getDouble(PROD_RATE)); - totalProdRate = totalProdRate + m.getDouble(PROD_RATE); - } - } - catch(Exception e) - { - System.out.println("Error calculating stats from Producer : " + conStat); - } - - avgSystemLatency = totLatency/consumers.size(); - avgSystemLatencyStdDev = totStdDev/consumers.size(); - avgSystemConsRate = totalConsRate/consumers.size(); - avgSystemProdRate = totalProdRate/producers.size(); - - System.out.println("Total test time : " + totalTestTime + " in " + Clock.getPrecision()); - - totalSystemThroughput = (totalMsgCount*Clock.convertToSecs()/totalTestTime); - } - - public void printResults() throws Exception - { - System.out.println(new StringBuilder("Total Msgs Received : ").append(totalMsgCount).toString()); - System.out.println(new StringBuilder("System Throughput : "). - append(df.format(totalSystemThroughput)). - append(" msg/sec").toString()); - System.out.println(new StringBuilder("Avg Consumer rate : "). - append(df.format(avgSystemConsRate)). - append(" msg/sec").toString()); - System.out.println(new StringBuilder("Min Consumer rate : "). - append(df.format(minSystemConsRate)). - append(" msg/sec").toString()); - System.out.println(new StringBuilder("Max Consumer rate : "). - append(df.format(maxSystemConsRate)). - append(" msg/sec").toString()); - - System.out.println(new StringBuilder("Avg Producer rate : "). - append(df.format(avgSystemProdRate)). - append(" msg/sec").toString()); - System.out.println(new StringBuilder("Min Producer rate : "). - append(df.format(minSystemProdRate)). - append(" msg/sec").toString()); - System.out.println(new StringBuilder("Max Producer rate : "). - append(df.format(maxSystemProdRate)). - append(" msg/sec").toString()); - - System.out.println(new StringBuilder("Avg System Latency : "). - append(df.format(avgSystemLatency)). - append(" ms").toString()); - System.out.println(new StringBuilder("Min System Latency : "). - append(df.format(minSystemLatency)). - append(" ms").toString()); - System.out.println(new StringBuilder("Max System Latency : "). - append(df.format(maxSystemLatency)). - append(" ms").toString()); - if (printStdDev) - { - System.out.println(new StringBuilder("Avg System Std Dev : "). - append(avgSystemLatencyStdDev)); - } - } - - private synchronized void sendMessageToNodes(OPCode code,Collection nodes) throws Exception - { - System.out.println("\nController: Sending code " + code); - MessageProducer tmpProd = controllerSession.createProducer(null); - MapMessage msg = controllerSession.createMapMessage(); - msg.setInt(CODE, code.ordinal()); - for (MapMessage node : nodes) - { - if (node.getString(REPLY_ADDR) == null) - { - System.out.println("REPLY_ADDR is null " + node); - } - else - { - System.out.println("Controller: Sending " + code + " to " + node.getString(REPLY_ADDR)); - } - tmpProd.send(controllerSession.createQueue(node.getString(REPLY_ADDR)), msg); - } - } - - public void onMessage(Message msg) - { - try - { - MapMessage m = (MapMessage)msg; - OPCode code = OPCode.values()[m.getInt(CODE)]; - - System.out.println("\n---------Controller Received Code : " + code); - System.out.println("---------Data : " + ((AMQPEncodedMapMessage)m).getMap()); - - switch (code) - { - case REGISTER_CONSUMER : - if (consRegistered.getCount() == 0) - { - System.out.println("Warning : Expected number of consumers have already registered," + - "ignoring extra consumer"); - break; - } - consumers.put(m.getString(ID),m); - consRegistered.countDown(); - break; - - case REGISTER_PRODUCER : - if (prodRegistered.getCount() == 0) - { - System.out.println("Warning : Expected number of producers have already registered," + - "ignoring extra producer"); - break; - } - producers.put(m.getString(ID),m); - prodRegistered.countDown(); - break; - - case CONSUMER_READY : - consReady.countDown(); - break; - - case PRODUCER_READY : - prodReady.countDown(); - break; - - case RECEIVED_END_MSG : - receivedEndMsg.countDown(); - break; - - case RECEIVED_CONSUMER_STATS : - consumers.put(m.getString(ID),m); - receivedConsStats.countDown(); - break; - - case RECEIVED_PRODUCER_STATS : - producers.put(m.getString(ID),m); - receivedProdStats.countDown(); - break; - - default: - throw new Exception("Invalid OPCode " + code); - } - } - catch (Exception e) - { - handleError(e,"Error when receiving messages " + msg); - } - } - - public void run() - { - try - { - setUp(); - warmup(); - if (testMode == TestMode.SINGLE_RUN) - { - startTest(); - calcStats(); - printResults(); - } - else - { - long startTime = Clock.getTime(); - long timeLimit = duration * 60 * 1000; // duration is in mins. - boolean nextIteration = true; - while (nextIteration) - { - startTest(); - calcStats(); - writeStatsToFile(); - if (Clock.getTime() - startTime < timeLimit) - { - sendMessageToNodes(OPCode.CONTINUE_TEST,consumers.values()); - sendMessageToNodes(OPCode.CONTINUE_TEST,producers.values()); - nextIteration = true; - } - else - { - nextIteration = false; - } - } - } - tearDown(); - - } - catch(Exception e) - { - handleError(e,"Error when running test"); - } - } - - @Override - public void tearDown() throws Exception { - System.out.println("Controller: Completed the test......\n"); - if (testMode == TestMode.TIME_BASED) - { - writer.close(); - } - sendMessageToNodes(OPCode.STOP_TEST,consumers.values()); - sendMessageToNodes(OPCode.STOP_TEST,producers.values()); - super.tearDown(); - } - - public void writeStatsToFile() throws Exception - { - writer.append(String.valueOf(totalMsgCount)).append(","); - writer.append(df.format(totalSystemThroughput)).append(","); - writer.append(df.format(avgSystemConsRate)).append(","); - writer.append(df.format(minSystemConsRate)).append(","); - writer.append(df.format(maxSystemConsRate)).append(","); - writer.append(df.format(avgSystemProdRate)).append(","); - writer.append(df.format(minSystemProdRate)).append(","); - writer.append(df.format(maxSystemProdRate)).append(","); - writer.append(df.format(avgSystemLatency)).append(","); - writer.append(df.format(minSystemLatency)).append(","); - writer.append(df.format(maxSystemLatency)); - if (printStdDev) - { - writer.append(",").append(String.valueOf(avgSystemLatencyStdDev)); - } - writer.append("\n"); - writer.flush(); - } - - public static void main(String[] args) - { - PerfTestController controller = new PerfTestController(); - controller.run(); - } -} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java b/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java new file mode 100644 index 0000000000..02f011f1b9 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java @@ -0,0 +1,181 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.util.UUID; +import java.util.concurrent.CountDownLatch; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.tools.TestConfiguration.MessageType; +import org.apache.qpid.tools.report.BasicReporter; +import org.apache.qpid.tools.report.Reporter; +import org.apache.qpid.tools.report.Statistics.Throughput; +import org.apache.qpid.tools.report.Statistics.ThroughputAndLatency; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QpidReceive implements MessageListener +{ + private static final Logger _logger = LoggerFactory.getLogger(QpidSend.class); + private final CountDownLatch testCompleted = new CountDownLatch(1); + + private Connection con; + private Session session; + private Destination dest; + private MessageConsumer consumer; + private boolean transacted = false; + private boolean isRollback = false; + private int txSize = 0; + private int rollbackFrequency = 0; + private int ackFrequency = 0; + private int expected = 0; + private int received = 0; + private Reporter report; + private TestConfiguration config; + + public QpidReceive(Reporter report, TestConfiguration config, Connection con, Destination dest) + { + this(report,config, con, dest, UUID.randomUUID().toString()); + } + + public QpidReceive(Reporter report, TestConfiguration config, Connection con, Destination dest, String prefix) + { + //System.out.println("Producer ID : " + id); + this.report = report; + this.config = config; + this.con = con; + this.dest = dest; + } + + public void setUp() throws Exception + { + if (config.isTransacted()) + { + session = con.createSession(true, Session.SESSION_TRANSACTED); + } + else if (config.getAckFrequency() > 0) + { + session = con.createSession(false, Session.DUPS_OK_ACKNOWLEDGE); + } + else + { + session = con.createSession(false, Session.AUTO_ACKNOWLEDGE); + } + consumer = session.createConsumer(dest); + consumer.setMessageListener(this); + System.out.println("Consumer: " + /*id +*/ " Receiving messages from : " + ((AMQDestination)dest).getAddressName() + "\n"); + + transacted = config.isTransacted(); + txSize = config.getTransactionSize(); + isRollback = config.getRollbackFrequency() > 0; + rollbackFrequency = config.getRollbackFrequency(); + ackFrequency = config.getAckFrequency(); + } + + public void resetCounters() + { + received = 0; + expected = 0; + report.clear(); + } + + public void onMessage(Message msg) + { + try + { + if (msg instanceof TextMessage && + TestConfiguration.EOS.equals(((TextMessage)msg).getText())) + { + testCompleted.countDown(); + return; + } + + received++; + report.message(msg); + + if (transacted && (received % txSize == 0)) + { + if (isRollback && (received % rollbackFrequency == 0)) + { + session.rollback(); + } + else + { + session.commit(); + } + } + else if (ackFrequency > 0) + { + msg.acknowledge(); + } + + if (expected >= received) + { + testCompleted.countDown(); + } + + } + catch(Exception e) + { + _logger.error("Error when receiving messages",e); + } + + } + + public void waitforCompletion(int expected) throws Exception + { + this.expected = expected; + testCompleted.await(); + } + + public void tearDown() throws Exception + { + session.close(); + } + + public static void main(String[] args) throws Exception + { + TestConfiguration config = new JVMArgConfiguration(); + Reporter reporter = new BasicReporter(config.isReportLatency()? ThroughputAndLatency.class : Throughput.class, + System.out, + config.reportEvery(), + config.isReportHeader() + ); + Destination dest = AMQDestination.createDestination(config.getAddress()); + QpidReceive receiver = new QpidReceive(reporter,config, config.createConnection(),dest); + receiver.setUp(); + receiver.waitforCompletion(config.getMsgCount()); + if (config.isReportTotal()) + { + reporter.report(); + } + receiver.tearDown(); + } + +} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java b/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java new file mode 100644 index 0000000000..c058b83d41 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java @@ -0,0 +1,291 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +import javax.jms.BytesMessage; +import javax.jms.Connection; +import javax.jms.DeliveryMode; +import javax.jms.Destination; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.Session; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.tools.TestConfiguration.MessageType; +import org.apache.qpid.tools.report.BasicReporter; +import org.apache.qpid.tools.report.Reporter; +import org.apache.qpid.tools.report.Statistics.Throughput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QpidSend +{ + private Connection con; + private Session session; + private Destination dest; + private MessageProducer producer; + private MessageType msgType; + private Message msg; + private Object payload; + private List payloads; + private boolean cacheMsg = false; + private boolean randomMsgSize = false; + private boolean durable = false; + private Random random; + private int msgSizeRange = 1024; + private int totalMsgCount = 0; + private boolean rateLimitProducer = false; + private boolean transacted = false; + private int txSize = 0; + + private static final Logger _logger = LoggerFactory.getLogger(QpidSend.class); + Reporter report; + TestConfiguration config; + + public QpidSend(Reporter report, TestConfiguration config, Connection con, Destination dest) + { + this(report,config, con, dest, UUID.randomUUID().toString()); + } + + public QpidSend(Reporter report, TestConfiguration config, Connection con, Destination dest, String prefix) + { + //System.out.println("Producer ID : " + id); + this.report = report; + this.config = config; + this.con = con; + this.dest = dest; + } + + public void setUp() throws Exception + { + if (config.isTransacted()) + { + session = con.createSession(true, Session.SESSION_TRANSACTED); + } + else + { + session = con.createSession(false, Session.AUTO_ACKNOWLEDGE); + } + + durable = config.isDurable(); + rateLimitProducer = config.getSendRate() > 0 ? true : false; + if (_logger.isDebugEnabled() && rateLimitProducer) + { + System.out.println("The test will attempt to limit the producer to " + config.getSendRate() + " msg/sec"); + } + + transacted = config.isTransacted(); + txSize = config.getTransactionSize(); + + msgType = MessageType.getType(config.getMessageType()); + // if message caching is enabled we pre create the message + // else we pre create the payload + if (config.isCacheMessage()) + { + cacheMsg = true; + msg = createMessage(createPayload(config.getMsgSize())); + msg.setJMSDeliveryMode(durable? + DeliveryMode.PERSISTENT : + DeliveryMode.NON_PERSISTENT + ); + } + else if (config.isRandomMsgSize()) + { + random = new Random(20080921); + randomMsgSize = true; + msgSizeRange = config.getMsgSize(); + payloads = new ArrayList(msgSizeRange); + + for (int i=0; i < msgSizeRange; i++) + { + payloads.add(createPayload(i)); + } + } + else + { + payload = createPayload(config.getMsgSize()); + } + + producer = session.createProducer(dest); + if (_logger.isDebugEnabled()) + { + System.out.println("Producer: " + /*id +*/ " Sending messages to: " + ((AMQDestination)dest).getAddressName()); + } + producer.setDisableMessageID(config.isDisableMessageID()); + producer.setDisableMessageTimestamp(config.isDisableTimestamp()); + } + + Object createPayload(int size) + { + if (msgType == MessageType.TEXT) + { + return MessageFactory.createMessagePayload(size); + } + else + { + return MessageFactory.createMessagePayload(size).getBytes(); + } + } + + Message createMessage(Object payload) throws Exception + { + if (msgType == MessageType.TEXT) + { + return session.createTextMessage((String)payload); + } + else + { + BytesMessage m = session.createBytesMessage(); + m.writeBytes((byte[])payload); + return m; + } + } + + protected Message getNextMessage() throws Exception + { + if (cacheMsg) + { + return msg; + } + else + { + Message m; + + if (!randomMsgSize) + { + m = createMessage(payload); + } + else + { + m = createMessage(payloads.get(random.nextInt(msgSizeRange))); + } + m.setJMSDeliveryMode(durable? + DeliveryMode.PERSISTENT : + DeliveryMode.NON_PERSISTENT + ); + return m; + } + } + + public void commit() throws Exception + { + session.commit(); + } + + public void send() throws Exception + { + send(config.getMsgCount()); + } + + public void send(int count) throws Exception + { + int sendRate = config.getSendRate(); + if (rateLimitProducer) + { + int iterations = count/sendRate; + int remainder = count%sendRate; + for (int i=0; i < iterations; i++) + { + long iterationStart = Clock.getTime(); + sendMessages(sendRate); + long elapsed = (Clock.getTime() - iterationStart)*Clock.convertToMiliSecs(); + long diff = Clock.SEC - elapsed; + if (diff > 0) + { + // We have sent more messages in a sec than specified by the rate. + Thread.sleep(diff); + } + } + sendMessages(remainder); + } + else + { + sendMessages(count); + } + } + + private void sendMessages(int count) throws Exception + { + boolean isTimestamp = config.isReportLatency(); + for(int i=0; i < count; i++ ) + { + Message msg = getNextMessage(); + if (isTimestamp) + { + msg.setLongProperty(TestConfiguration.TIMESTAMP, Clock.getTime()); + } + producer.send(msg); + report.message(msg); + totalMsgCount++; + + if ( transacted && ((totalMsgCount) % txSize == 0)) + { + session.commit(); + } + } + } + + public void resetCounters() + { + totalMsgCount = 0; + report.clear(); + } + + public void sendEndMessage() throws Exception + { + Message msg = session.createMessage(); + msg.setBooleanProperty(TestConfiguration.EOS, true); + producer.send(msg); + } + + public void tearDown() throws Exception + { + session.close(); + } + + public static void main(String[] args) throws Exception + { + TestConfiguration config = new JVMArgConfiguration(); + Reporter reporter = new BasicReporter(Throughput.class, + System.out, + config.reportEvery(), + config.isReportHeader() + ); + Destination dest = AMQDestination.createDestination(config.getAddress()); + QpidSend sender = new QpidSend(reporter,config, config.createConnection(),dest); + sender.setUp(); + sender.send(); + if (config.getSendEOS() > 0) + { + sender.sendEndMessage(); + } + if (config.isReportTotal()) + { + reporter.report(); + } + sender.tearDown(); + } +} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java b/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java new file mode 100644 index 0000000000..7f7df0e5e6 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java @@ -0,0 +1,126 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools; + +import java.text.DecimalFormat; + +import javax.jms.Connection; + +public interface TestConfiguration +{ + enum MessageType { + BYTES, TEXT, MAP, OBJECT; + + public static MessageType getType(String s) throws Exception + { + if ("text".equalsIgnoreCase(s)) + { + return TEXT; + } + else if ("bytes".equalsIgnoreCase(s)) + { + return BYTES; + } + /*else if ("map".equalsIgnoreCase(s)) + { + return MAP; + } + else if ("object".equalsIgnoreCase(s)) + { + return OBJECT; + }*/ + else + { + throw new Exception("Unsupported message type"); + } + } + }; + + public final static String TIMESTAMP = "ts"; + + public final static String EOS = "eos"; + + public final static String SEQUENCE_NUMBER = "sn"; + + public String getUrl(); + + public String getHost(); + + public int getPort(); + + public String getAddress(); + + public int getAckMode(); + + public int getMsgCount(); + + public int getMsgSize(); + + public int getRandomMsgSizeStartFrom(); + + public boolean isDurable(); + + public boolean isTransacted(); + + public int getTransactionSize(); + + public int getWarmupCount(); + + public boolean isCacheMessage(); + + public boolean isDisableMessageID(); + + public boolean isDisableTimestamp(); + + public boolean isRandomMsgSize(); + + public String getMessageType(); + + public boolean isPrintStdDev(); + + public int getSendRate(); + + public boolean isExternalController(); + + public boolean isUseUniqueDests(); + + public int getAckFrequency(); + + public Connection createConnection() throws Exception; + + public DecimalFormat getDecimalFormat(); + + public int reportEvery(); + + public boolean isReportTotal(); + + public boolean isReportHeader(); + + public boolean isReportLatency(); + + public int getSendEOS(); + + public int getConnectionCount(); + + public int getRollbackFrequency(); + + public boolean isPrintHeaders(); +} \ No newline at end of file diff --git a/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java b/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java deleted file mode 100644 index d73be0181b..0000000000 --- a/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.tools; - -import javax.jms.Session; - -public class TestParams -{ - /* - * By default the connection URL is used. - * This allows a user to easily specify a fully fledged URL any given property. - * Ex. SSL parameters - * - * By providing a host & port allows a user to simply override the URL. - * This allows to create multiple clients in test scripts easily, - * without having to deal with the long URL format. - */ - private String url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'"; - - private String host = ""; - - private int port = -1; - - private String address = "queue; {create : always}"; - - private int msg_size = 1024; - - private int random_msg_size_start_from = 1; - - private boolean cacheMessage = false; - - private boolean disableMessageID = false; - - private boolean disableTimestamp = false; - - private boolean durable = false; - - private boolean transacted = false; - - private int transaction_size = 1000; - - private int ack_mode = Session.AUTO_ACKNOWLEDGE; - - private int msg_count = 10; - - private int warmup_count = 1; - - private boolean random_msg_size = false; - - private String msgType = "bytes"; - - private boolean printStdDev = false; - - private long rate = -1; - - private boolean externalController = false; - - private boolean useUniqueDest = false; // useful when using multiple connections. - - public TestParams() - { - - url = System.getProperty("url",url); - host = System.getProperty("host",""); - port = Integer.getInteger("port", -1); - address = System.getProperty("address",address); - - msg_size = Integer.getInteger("msg_size", 1024); - cacheMessage = Boolean.getBoolean("cache_msg"); - disableMessageID = Boolean.getBoolean("disableMessageID"); - disableTimestamp = Boolean.getBoolean("disableTimestamp"); - durable = Boolean.getBoolean("durable"); - transacted = Boolean.getBoolean("transacted"); - transaction_size = Integer.getInteger("trans_size",1000); - ack_mode = Integer.getInteger("ack_mode",Session.AUTO_ACKNOWLEDGE); - msg_count = Integer.getInteger("msg_count",msg_count); - warmup_count = Integer.getInteger("warmup_count",warmup_count); - random_msg_size = Boolean.getBoolean("random_msg_size"); - msgType = System.getProperty("msg_type","bytes"); - printStdDev = Boolean.getBoolean("print_std_dev"); - rate = Long.getLong("rate",-1); - externalController = Boolean.getBoolean("ext_controller"); - useUniqueDest = Boolean.getBoolean("use_unique_dest"); - random_msg_size_start_from = Integer.getInteger("random_msg_size_start_from", 1); - } - - public String getUrl() - { - return url; - } - - public String getHost() - { - return host; - } - - public int getPort() - { - return port; - } - - public String getAddress() - { - return address; - } - - public int getAckMode() - { - return ack_mode; - } - - public int getMsgCount() - { - return msg_count; - } - - public int getMsgSize() - { - return msg_size; - } - - public int getRandomMsgSizeStartFrom() - { - return random_msg_size_start_from; - } - - public boolean isDurable() - { - return durable; - } - - public boolean isTransacted() - { - return transacted; - } - - public int getTransactionSize() - { - return transaction_size; - } - - public int getWarmupCount() - { - return warmup_count; - } - - public boolean isCacheMessage() - { - return cacheMessage; - } - - public boolean isDisableMessageID() - { - return disableMessageID; - } - - public boolean isDisableTimestamp() - { - return disableTimestamp; - } - - public boolean isRandomMsgSize() - { - return random_msg_size; - } - - public String getMessageType() - { - return msgType; - } - - public boolean isPrintStdDev() - { - return printStdDev; - } - - public long getRate() - { - return rate; - } - - public boolean isExternalController() - { - return externalController; - } - - public void setAddress(String addr) - { - address = addr; - } - - public boolean isUseUniqueDests() - { - return useUniqueDest; - } -} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/report/BasicReporter.java b/java/tools/src/main/java/org/apache/qpid/tools/report/BasicReporter.java new file mode 100644 index 0000000000..a9896c1d4e --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/report/BasicReporter.java @@ -0,0 +1,113 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools.report; + +import java.io.PrintStream; +import java.lang.reflect.Constructor; + +import javax.jms.Message; + +public class BasicReporter implements Reporter +{ + PrintStream out; + int batchSize = 0; + int batchCount = 0; + boolean headerPrinted = false; + protected Statistics overall; + Statistics batch; + Constructor statCtor; + + public BasicReporter(Class clazz, PrintStream out, + int batchSize, boolean printHeader) throws Exception + { + this.out = out; + this.batchSize = batchSize; + this.headerPrinted = !printHeader; + statCtor = clazz.getConstructor(); + overall = statCtor.newInstance(); + if (batchSize > 0) + { + batch = statCtor.newInstance(); + } + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.report.Reporter#message(javax.jms.Message) + */ + @Override + public void message(Message msg) + { + overall.message(msg); + if (batchSize > 0) + { + batch.message(msg); + if (++batchCount == batchSize) + { + if (!headerPrinted) + { + header(); + } + batch.report(out); + batch.clear(); + batchCount = 0; + } + } + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.report.Reporter#report() + */ + @Override + public void report() + { + if (!headerPrinted) + { + header(); + } + overall.report(out); + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.report.Reporter#header() + */ + @Override + public void header() + { + headerPrinted = true; + overall.header(out); + } + + /* (non-Javadoc) + * @see org.apache.qpid.tools.report.Reporter#log() + */ + @Override + public void log(String s) + { + // NOOP + } + + @Override + public void clear() + { + batch.clear(); + overall.clear(); + } +} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/report/MercuryReporter.java b/java/tools/src/main/java/org/apache/qpid/tools/report/MercuryReporter.java new file mode 100644 index 0000000000..e9bf7100c1 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/report/MercuryReporter.java @@ -0,0 +1,167 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools.report; + +import java.io.PrintStream; + +import org.apache.qpid.tools.report.Statistics.Throughput; +import org.apache.qpid.tools.report.Statistics.ThroughputAndLatency; + +public class MercuryReporter extends BasicReporter +{ + MercuryStatistics stats; + + public MercuryReporter(Class clazz, PrintStream out, + int batchSize, boolean printHeader) throws Exception + { + super(clazz, out, batchSize, printHeader); + stats = (MercuryStatistics)overall; + } + + public double getRate() + { + return stats.getRate(); + } + + public double getAvgLatency() + { + return stats.getAvgLatency(); + } + + public double getStdDev() + { + return stats.getStdDev(); + } + + public double getMinLatency() + { + return stats.getMinLatency(); + } + + public double getMaxLatency() + { + return stats.getMaxLatency(); + } + + public int getSampleSize() + { + return stats.getSampleSize(); + } + + public interface MercuryStatistics extends Statistics + { + public double getRate(); + public long getMinLatency(); + public long getMaxLatency(); + public double getAvgLatency(); + public double getStdDev(); + public int getSampleSize(); + } + + public static class MercuryThroughput extends Throughput implements MercuryStatistics + { + double rate = 0; + + @Override + public void report(PrintStream out) + { + long elapsed = System.currentTimeMillis() - start; + rate = (double)messages/(double)elapsed; + } + + @Override + public void clear() + { + super.clear(); + rate = 0; + } + + public double getRate() + { + return rate; + } + + public int getSampleSize() + { + return messages; + } + + public long getMinLatency() { return 0; } + public long getMaxLatency() { return 0; } + public double getAvgLatency(){ return 0; } + public double getStdDev(){ return 0; } + + } + + public static class MercuryThroughputAndLatency extends ThroughputAndLatency implements MercuryStatistics + { + double rate = 0; + double avgLatency = 0; + double stdDev; + + @Override + public void report(PrintStream out) + { + long elapsed = System.currentTimeMillis() - start; + rate = (double)messages/(double)elapsed; + avgLatency = totalLatency/(double)sampleCount; + } + + @Override + public void clear() + { + super.clear(); + rate = 0; + avgLatency = 0; + } + + public double getRate() + { + return rate; + } + + public long getMinLatency() + { + return minLatency; + } + + public long getMaxLatency() + { + return maxLatency; + } + + public double getAvgLatency() + { + return avgLatency; + } + + public double getStdDev() + { + return stdDev; + } + + public int getSampleSize() + { + return messages; + } + } + +} diff --git a/java/tools/src/main/java/org/apache/qpid/tools/report/Reporter.java b/java/tools/src/main/java/org/apache/qpid/tools/report/Reporter.java new file mode 100644 index 0000000000..5e481458be --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/report/Reporter.java @@ -0,0 +1,40 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools.report; + +import javax.jms.Message; + +public interface Reporter +{ + + public void message(Message msg); + + public void report(); + + public void header(); + + // Will be used by some reporters to print statements which are greped by + // scripts. Example see java/tools/bin/perf-report + public void log(String s); + + public void clear(); + +} \ No newline at end of file diff --git a/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java b/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java new file mode 100644 index 0000000000..73efd1f1e0 --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java @@ -0,0 +1,139 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.tools.report; + +import java.io.PrintStream; +import java.text.DecimalFormat; + +import javax.jms.Message; + +public interface Statistics +{ + public void message(Message msg); + public void report(PrintStream out); + public void header(PrintStream out); + public void clear(); + + static class Throughput implements Statistics + { + DecimalFormat df = new DecimalFormat("###.##"); + int messages = 0; + long start = 0; + boolean started = false; + + @Override + public void message(Message msg) + { + ++messages; + if (!started) + { + start = System.currentTimeMillis(); + started = true; + } + } + + @Override + public void report(PrintStream out) + { + long elapsed = System.currentTimeMillis() - start; + out.print(df.format((double)messages/(double)elapsed)); + } + + @Override + public void header(PrintStream out) + { + out.print("tp(m/s)"); + } + + public void clear() + { + messages = 0; + start = 0; + started = false; + } + } + + static class ThroughputAndLatency extends Throughput + { + long minLatency = Long.MAX_VALUE; + long maxLatency = Long.MIN_VALUE; + double totalLatency = 0; + int sampleCount = 0; + + @Override + public void message(Message msg) + { + super.message(msg); + try + { + long ts = msg.getLongProperty("ts"); + long latency = System.currentTimeMillis() - ts; + minLatency = Math.min(latency, minLatency); + maxLatency = Math.min(latency, maxLatency); + totalLatency = totalLatency + latency; + sampleCount++; + } + catch(Exception e) + { + System.out.println("Error calculating latency"); + } + } + + @Override + public void report(PrintStream out) + { + super.report(out); + double avgLatency = totalLatency/(double)sampleCount; + out.append('\t') + .append(String.valueOf(minLatency)) + .append('\t') + .append(String.valueOf(maxLatency)) + .append('\t') + .append(df.format(avgLatency)); + + out.flush(); + } + + @Override + public void header(PrintStream out) + { + super.header(out); + out.append('\t') + .append("l-min") + .append('\t') + .append("l-max") + .append('\t') + .append("l-avg"); + + out.flush(); + } + + public void clear() + { + super.clear(); + minLatency = 0; + maxLatency = 0; + totalLatency = 0; + sampleCount = 0; + } + } + +} diff --git a/packaging/windows/INSTALL_NOTES.html b/packaging/windows/INSTALL_NOTES.html index ad57eb8a36..9442b5a5c0 100644 --- a/packaging/windows/INSTALL_NOTES.html +++ b/packaging/windows/INSTALL_NOTES.html @@ -1,11 +1,11 @@ -Apache Qpid C++ 0.15 Installation Notes +Apache Qpid C++ 0.17 Installation Notes -

Apache Qpid C++ 0.15 Installation Notes

+

Apache Qpid C++ 0.17 Installation Notes

-

Thank you for installing Apache Qpid version 0.15 for Windows. +

Thank you for installing Apache Qpid version 0.17 for Windows. If the requisite features were installed, you can now run a broker, use the example programs, and design your own messaging programs while reading the Qpid C++ API reference documentation.

@@ -83,7 +83,7 @@ default; therefore, to gain support for durable items the persistence plugin must be loaded into the broker. This can be done using the --load-module option to load the needed plugins. For example:
-cd "C:\Program Files\Apache\qpidc-0.15"
+cd "C:\Program Files\Apache\qpidc-0.17"
 qpidd.exe --load-module plugins\broker\store.dll --load-module plugins\broker\msclfs_store.dll
 
The --load-module option can also take a full path. The option diff --git a/packaging/windows/installer.proj b/packaging/windows/installer.proj index 5a3f1e0201..699981cea0 100644 --- a/packaging/windows/installer.proj +++ b/packaging/windows/installer.proj @@ -32,7 +32,7 @@ $(MSBuildProjectDirectory)\..\.. $(MSBuildProjectDirectory)\stage 32 - 0.14 + 0.17 qpidc Package C:\Program Files (x86)\Windows Installer XML v3.5\bin diff --git a/python/qpid/connection.py b/python/qpid/connection.py index f2c83d113c..66e1cb49be 100644 --- a/python/qpid/connection.py +++ b/python/qpid/connection.py @@ -170,6 +170,10 @@ class Connection(Framer): if not status: self.detach_all() break + # When we do not use SSL transport, we get periodic + # spurious timeout events on the socket. When using SSL, + # these events show up as timeout *errors*. Both should be + # ignored unless we have aborted. except socket.timeout: if self.aborted(): self.close_code = (None, "connection timed out") @@ -178,9 +182,12 @@ class Connection(Framer): else: continue except socket.error, e: - self.close_code = (None, str(e)) - self.detach_all() - break + if self.aborted() or str(e) != "The read operation timed out": + self.close_code = (None, str(e)) + self.detach_all() + break + else: + continue frame_dec.write(data) seg_dec.write(*frame_dec.read()) op_dec.write(*seg_dec.read()) diff --git a/python/qpid/messaging/driver.py b/python/qpid/messaging/driver.py index 0358659111..3cb62d75c9 100644 --- a/python/qpid/messaging/driver.py +++ b/python/qpid/messaging/driver.py @@ -226,7 +226,11 @@ class LinkIn: def do_link(self, sst, rcv, _rcv, type, subtype, action): link_opts = _rcv.options.get("link", {}) - reliability = link_opts.get("reliability", "at-least-once") + if type == "topic": + default_reliability = "unreliable" + else: + default_reliability = "at-least-once" + reliability = link_opts.get("reliability", default_reliability) declare = link_opts.get("x-declare", {}) subscribe = link_opts.get("x-subscribe", {}) acq_mode = acquire_mode.pre_acquired diff --git a/python/qpid/testlib.py b/python/qpid/testlib.py index 1da53b3378..f9796982f5 100644 --- a/python/qpid/testlib.py +++ b/python/qpid/testlib.py @@ -29,6 +29,9 @@ from qpid.message import Message from qpid.harness import Skipped from qpid.exceptions import VersionError +import qpid.messaging +from qpidtoollibs import BrokerAgent + class TestBase(unittest.TestCase): """Base class for Qpid test cases. @@ -193,6 +196,15 @@ class TestBase010(unittest.TestCase): self.qmf = qmf.console.Session(handler) self.qmf_broker = self.qmf.addBroker(str(self.broker)) + def startBrokerAccess(self): + """ + New-style management access to the broker. Can be used in lieu of startQmf. + """ + if 'broker_conn' not in self.__dict__: + self.broker_conn = qpid.messaging.Connection(str(self.broker)) + self.broker_conn.open() + self.broker_access = BrokerAgent(self.broker_conn) + def connect(self, host=None, port=None): url = self.broker if url.scheme == URL.AMQPS: diff --git a/python/qpid/tests/messaging/endpoints.py b/python/qpid/tests/messaging/endpoints.py index db5ec03df2..62deacd0bd 100644 --- a/python/qpid/tests/messaging/endpoints.py +++ b/python/qpid/tests/messaging/endpoints.py @@ -524,7 +524,7 @@ class SessionTests(Base): self.ssn.acknowledge(echos[0]) self.ssn.acknowledge(echos[1], Disposition(REJECTED)) self.ssn.acknowledge(echos[2], - Disposition(REJECTED, code=3, text="test-reject")) + Disposition(REJECTED, code=0, text="test-reject")) self.drain(rej, expected=msgs[1:]) self.ssn.acknowledge() @@ -632,9 +632,9 @@ class SessionTests(Base): def testDoubleCommit(self): ssn = self.conn.session(transactional=True) - snd = ssn.sender("amq.direct") - rcv = ssn.receiver("amq.direct") - msgs = [self.message("testDoubleCommit", i) for i in range(3)] + snd = ssn.sender("amq.direct/doubleCommit") + rcv = ssn.receiver("amq.direct/doubleCommit") + msgs = [self.message("testDoubleCommit", i, subject="doubleCommit") for i in range(3)] for m in msgs: snd.send(m) ssn.commit() @@ -1038,7 +1038,7 @@ class AddressTests(Base): snd.close() assert False, "successfully deleted amq.topic" except SessionError, e: - assert "Cannot delete default exchange" in str(e) + assert e.code == 530 # XXX: need to figure out close after error self.conn._remove_session(self.ssn) diff --git a/python/setup.py b/python/setup.py index a0717ece1b..225ee44b91 100755 --- a/python/setup.py +++ b/python/setup.py @@ -298,7 +298,7 @@ class install_lib(_install_lib): return outfiles + extra setup(name="qpid-python", - version="0.15", + version="0.17", author="Apache Qpid", author_email="dev@qpid.apache.org", packages=["mllib", "qpid", "qpid.messaging", "qpid.tests", diff --git a/specs/amqp.xsl b/specs/amqp.xsl new file mode 100644 index 0000000000..afe3bd5e65 --- /dev/null +++ b/specs/amqp.xsl @@ -0,0 +1,534 @@ + + + + + + + + + + AMQP <xsl:call-template name="initCap"><xsl:with-param name="input" select="@name"/></xsl:call-template> + + + +

AMQP

+ + + + + +
+ + + + +

Table of Contents

+
+ + +
+
+
+ + + + + + + + #section- + +

      
            
+ +
:
+ mandatory + optional + []
anchorchoice--
+
<type name="" class="" source="" provides=""/> + +</type> + +
+ + + + + <descriptor name="" code=""/> + + + + + <choice =""/> + + + + + <field =""/> + + </field> + + + + + <error =""/> + + + + + + code : + fixed-width, byte value + variable-width, byte size + + + + + + + + + + + + +
#type-
+
+ + + + + + + + + + + + + + + + + +
TypeEncodingCodeCategoryDescription
#type-/
+
+ + + + + + + + + + + + + + + + +
error:
+
+ + + + +

definition-

+ + signature + + : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + + .. + + + . + + + + + + + * + + #type- + + + .xml + #type- + + + + + + + + + + + #choice-- + + + .xml + + #choice-- + + + + + + + + + + + + + + + + + + + + + + + diff --git a/specs/apache-filters.xml b/specs/apache-filters.xml new file mode 100644 index 0000000000..24e1d521e2 --- /dev/null +++ b/specs/apache-filters.xml @@ -0,0 +1,228 @@ + + + + + +
+ +

+ Versions of AMQP prior to 1.0 prescribed a model of Exchanges and Queues, where Queues were + bound to Exchanges with a binding key whose meaning depended upon the type of the Exchange. + In order to allow a consistent mechanism for addressing legacy AMQP Exchanges over AMQP 1.0 + the following filter types are defined. Use of an Exchange as an address for a Source thus + can be seen as equivalent to constructing exclusive queues bound to an Exchange in legacy + AMQP versions. +

+

+ Containers which support the filters that are defined in this section should advertise the + capability APACHE.ORG:LEGACY_AMQP_EXCHANGE_FILTERS in their connection + capabilities when sending the open performative, and MUST provide this capability on + sources supporting these filter types. +

+
+ + + +

+ The legacy-amqp-direct-binding filter consists of a described string value. The filter + matches a message if and only if the described string value exactly matches the subject + field of the Properties section of the message being evaluated. If the message has no + Properties section, or if the subject field of the Properties section is not set, then + the legacy-amqp-direct-binding filter does not match. +

+
+
+ + + + +

+ The legacy-amqp-topic-binding filter consists of a described string value. The value + value described by the type is interpreted as a pattern to match against the subject + field of the Properties section of the message being evaluated. +

+
    +
  • The pattern is formed using zero or more tokens, with each token delimited by the + "." character. The tokens "#" and "*" have special meanings.
  • +
  • The token consisting of the single character "*" matches a single word in the + subject field.
  • +
  • The token consisting of the single character "#" matches zero or more words in the + subject field.
  • +
+

+ Thus the filter value "*.stock.#" would match the subjects "usd.stock" and + "eur.stock.db" but not "stock.nasdaq". +

+

+ If the message has no Properties section, or if the subject field of the Properties + section is not set, then the legacy-amqp-topic-binding filter matches only if the value + of the filter is a single "#". +

+
+
+ + + + +

+ The legacy-amqp-headers-binding filter consists of a described map value. The map + value described by the type is interpreted as a pattern to match against the + application-properties section of the message being evaluated. The map has the same + restriction as the application-properties section, namely that the keys of this are + restricted to be of type string (which excludes the possibility of a null key) and the + values are restricted to be of simple types only, that is, excluding map, list, and + array types. +

+

+ The key "x-match" in the described map has special meaning. This key MUST map to the + symbolic value "any" or the symbolic value "all" within the described map. All other + keys which begin "x-" MUST be ignored by the source when evaluating. If the value for + "x-match" is "all" then all other valid key-value pairs in the map MUST match with an + entry with the same key in the application-properties section. If the value for + "x-match" is "any" then the filter will accept the message if at least one key-value + pair matches the equivalent key value pair in the application-properties section. +

+

+ A key-value pair in the filter's map matches a key-value pair in the + application-properties section if the keys are identical (including the same type), or + if the value in the filter map for the key is null. +

+
+
+
+
+ + +

+ The Java Message Service defines two types of filtering of messages: firstly the ability to + exclude from a subscription messages sent by the same connection, secondly a more general + filtering syntax known as "selectors" based on an SQL like syntax. +

+

+ AMQP filter extensions through which these two types of + filtering may be achieved are defined below. Their use, though + motivated by support for JMS, is not restricted to JMS. +

+
+ + + + +

+ A message will be accepted by the simple-no-local-filter if and only if the message + was originally sent to the container of the source on a separate connection from that + which is currently receiving from the source. +

+

+ Containers which support this filter should advertise the + capability APACHE.ORG:NO_LOCAL in their + connection capabilities when sending the open + performative, and MUST provide this capability on sources + supporting these filter types. +

+
+
+ + + + +

+ The Java Message Service "selector" defines an SQL like + syntax for filtering messages. The selector filters based + on the values of "headers" and "properties". The + selector-filter uses the selector as defined by JMS but + with the names of JMS headers translated into their AMQP + equivalents. The defined JMS headers can be mapped to + equivalent fields within the AMQP message sections: +

+ +JMS Header Name | AMQP 1.0 Field +==================|==================================================== +JMSCorrelationID | correlation-id field of properties section +JMSDeliveryMode | durable field of header section +JMSDestination | to field of the properties section +JMSExpiration | absolute-expiry-time of properties section +JMSMessageID | message-id of properties section +JMSPriority | priority field of header section +JMSRedelivered | delivery-count > 0 in header section +JMSReplyTo | reply-to in properties section +JMSTimestamp | creation-time of properties section +JMSType | annotation jms-type in message-annotations section + +

+ When encoding the selector string on the wire, these JMS + header names should be translated to amqp.field_name + where field_name is the appropriate AMQP 1.0 field + named in the table above, with the hyphen replaced by an + underscore. For example, the selector: "JMSCorrelationID = + ’abc’ AND color = ’blue’ AND weight > 2500" would be + transferred over the wire as: "amqp.correlation_id = ’abc’ + AND color = ’blue’ AND weight > 2500" +

+

+ The "properties" of the JMS message are equivalent to the AMQP application-properties + section. Thus a reference to a property Foo in a message selector would be evaluated + as the value associated with the key "Foo" (if present) in the application-properties + section. +

+

+ The operands of the JMS selector are defined in terms of the types available within JMS, + When evaluated against the application properties section, the values within that section + MUST be evaluated according to the following type mapping. +

+ +AMQP Type | JMS Selector Type +==================|=================== +null | null +boolean | boolean +ubyte | short +ushort | int +uint | long +ulong | long +byte | byte +short | short +int | int +long | long +float | float +double | double +decimal32 | double +decimal64 | double +decimal128 | double +char | char +timestamp | long +uuid | byte[16] +binary | byte[] +string | String +symbol | String + +

+ Containers which support this filter should advertise the + capability APACHE.ORG:SELECTOR in their + connection capabilities when sending the open + performative, and MUST provide this capability on sources + supporting these filter types. +

+
+
+
+
diff --git a/specs/management-schema.xml b/specs/management-schema.xml index c8d2b9cdcb..66e122b049 100644 --- a/specs/management-schema.xml +++ b/specs/management-schema.xml @@ -84,6 +84,7 @@ + @@ -124,8 +125,8 @@ - - + + @@ -142,7 +143,7 @@ - + @@ -271,14 +272,14 @@ - + - + diff --git a/tests/setup.py b/tests/setup.py index b8e952998d..36e7a0531a 100755 --- a/tests/setup.py +++ b/tests/setup.py @@ -20,7 +20,7 @@ from distutils.core import setup setup(name="qpid-tests", - version="0.15", + version="0.17", author="Apache Qpid", author_email="dev@qpid.apache.org", packages=["qpid_tests", "qpid_tests.broker_0_10", "qpid_tests.broker_0_9", diff --git a/tests/src/py/qpid_tests/broker_0_10/management.py b/tests/src/py/qpid_tests/broker_0_10/management.py index 867210b11d..2dd2291b2e 100644 --- a/tests/src/py/qpid_tests/broker_0_10/management.py +++ b/tests/src/py/qpid_tests/broker_0_10/management.py @@ -24,8 +24,17 @@ from threading import Condition from time import sleep import qmf.console import qpid.messaging +from qpidtoollibs import BrokerAgent class ManagementTest (TestBase010): + + def setup_access(self): + if 'broker_agent' not in self.__dict__: + self.conn2 = qpid.messaging.Connection(self.broker) + self.conn2.open() + self.broker_agent = BrokerAgent(self.conn2) + return self.broker_agent + """ Tests for the management hooks """ @@ -376,6 +385,30 @@ class ManagementTest (TestBase010): # Cleanup for e in ["A", "B"]: session.exchange_delete(exchange=e) + def test_reroute_invalid_alt_exchange(self): + """ + Test that an error is returned for an attempt to reroute to + alternate exchange on a queue for which no such exchange has + been defined. + """ + self.startQmf() + session = self.session + # create queue with no alt-exchange, and send a message to it + session.queue_declare(queue="q", exclusive=True, auto_delete=True) + props = session.delivery_properties(routing_key="q") + session.message_transfer(message=Message(props, "don't reroute me!")) + + # attempt to reroute the message to alt-exchange + q = self.qmf.getObjects(_class="queue", name="q")[0] + result = q.reroute(1, True, "", {}) + # verify the attempt fails... + self.assertEqual(result.status, 4) #invalid parameter + + # ...and message is still on the queue + self.subscribe(destination="d", queue="q") + self.assertEqual("don't reroute me!", session.incoming("d").get(timeout=1).body) + + def test_methods_async (self): """ """ @@ -559,12 +592,18 @@ class ManagementTest (TestBase010): """ Test message in/out stats for connection """ - self.startQmf() + agent = self.setup_access() conn = self.connect() session = conn.session("stats-session") #using qmf find named session and the corresponding connection: - conn_qmf = self.qmf.getObjects(_class="session", name="stats-session")[0]._connectionRef_ + conn_qmf = None + sessions = agent.getAllSessions() + for s in sessions: + if s.name == "stats-session": + conn_qmf = agent.getConnection(s.connectionRef) + + assert(conn_qmf) #send a message to a queue session.queue_declare(queue="stats-q", exclusive=True, auto_delete=True) diff --git a/tests/src/py/qpid_tests/broker_0_10/msg_groups.py b/tests/src/py/qpid_tests/broker_0_10/msg_groups.py index 938d3b3ee2..ace7611a2f 100644 --- a/tests/src/py/qpid_tests/broker_0_10/msg_groups.py +++ b/tests/src/py/qpid_tests/broker_0_10/msg_groups.py @@ -193,6 +193,10 @@ class MultiConsumerMsgGroupTests(Base): s2 = self.setup_session() b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0}) + m2 = b1.fetch(0); + assert m2.properties['THE-GROUP'] == 'A' + assert m2.content['index'] == 0 + # C1 should acquire A-0 m1 = c1.fetch(0); @@ -202,10 +206,6 @@ class MultiConsumerMsgGroupTests(Base): ## Queue = A-0, B-1, A-2, b-3, C-4 ## Owners= ^C1, ---, +C1, ---, --- - m2 = b1.fetch(0); - assert m2.properties['THE-GROUP'] == 'A' - assert m2.content['index'] == 0 - m2 = b1.fetch(0) assert m2.properties['THE-GROUP'] == 'B' assert m2.content['index'] == 1 @@ -1122,6 +1122,70 @@ class MultiConsumerMsgGroupTests(Base): snd.close() + def test_ttl_expire(self): + """ Verify that expired (TTL) group messages are skipped correctly + """ + snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," + + " node: {x-declare: {arguments:" + + " {'qpid.group_header_key':'THE-GROUP'," + + "'qpid.shared_msg_group':1}}}}") + + groups = ["A","B","C","A","B","C"] + messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups] + index = 0 + for m in messages: + m.content['index'] = index + index += 1 + if m.properties['THE-GROUP'] == 'B': + m.ttl = 1; + snd.send(m) + + sleep(2) # let all B's expire + + # create consumers on separate sessions: C1,C2 + s1 = self.setup_session() + c1 = s1.receiver("msg-group-q", options={"capacity":0}) + s2 = self.setup_session() + c2 = s2.receiver("msg-group-q", options={"capacity":0}) + + # C1 should acquire A-0, then C2 should acquire C-2, Group B should + # expire and never be fetched + + m1 = c1.fetch(0); + assert m1.properties['THE-GROUP'] == 'A' + assert m1.content['index'] == 0 + + m2 = c2.fetch(0); + assert m2.properties['THE-GROUP'] == 'C' + assert m2.content['index'] == 2 + + m1 = c1.fetch(0); + assert m1.properties['THE-GROUP'] == 'A' + assert m1.content['index'] == 3 + + m2 = c2.fetch(0); + assert m2.properties['THE-GROUP'] == 'C' + assert m2.content['index'] == 5 + + # there should be no more left for either consumer + try: + mx = c1.fetch(0) + assert False # should never get here + except Empty: + pass + try: + mx = c2.fetch(0) + assert False # should never get here + except Empty: + pass + + c1.session.acknowledge() + c2.session.acknowledge() + c1.close() + c2.close() + snd.close() + + class StickyConsumerMsgGroupTests(Base): """ Tests for the behavior of sticky-consumer message groups. These tests diff --git a/tests/src/py/qpid_tests/broker_0_10/new_api.py b/tests/src/py/qpid_tests/broker_0_10/new_api.py index 0bbcf342bc..05c4815e57 100644 --- a/tests/src/py/qpid_tests/broker_0_10/new_api.py +++ b/tests/src/py/qpid_tests/broker_0_10/new_api.py @@ -57,7 +57,7 @@ class GeneralTests(Base): sess2 = self.setup_session() tx = sess1.sender("amq.direct/key") - rx_main = sess1.receiver("amq.direct/key;{link:{x-declare:{alternate-exchange:'amq.fanout'}}}") + rx_main = sess1.receiver("amq.direct/key;{link:{reliability:at-least-once,x-declare:{alternate-exchange:'amq.fanout'}}}") rx_alt = sess2.receiver("amq.fanout") rx_alt.capacity = 10 @@ -74,7 +74,7 @@ class GeneralTests(Base): self.assertEqual(rx_alt.available(), 0, "No messages should have been routed to the alt_exchange") sess1.close() - + sleep(1) self.assertEqual(rx_alt.available(), 5, "All 5 messages should have been routed to the alt_exchange") sess2.close() @@ -108,6 +108,7 @@ class GeneralTests(Base): # Close sess1; This will cause the queue to be deleted sess1.close() + sleep(1) self.assertEqual(rx_alt.available(), 2, "2 of the messages should have been routed to the alt_exchange") # Close sess2; This will cause the acquired messages to be requeued and routed to the alternate diff --git a/tools/setup.py b/tools/setup.py index 925c20bee9..302c25502f 100755 --- a/tools/setup.py +++ b/tools/setup.py @@ -20,20 +20,21 @@ from distutils.core import setup setup(name="qpid-tools", - version="0.15", + version="0.17", author="Apache Qpid", author_email="dev@qpid.apache.org", + package_dir={'' : 'src/py'}, packages=["qpidtoollibs"], - scripts=["qpid-cluster", - "qpid-cluster-store", - "qpid-config", - "qpid-ha-status", - "qpid-printevents", - "qpid-queue-stats", - "qpid-route", - "qpid-stat", - "qpid-tool", - "qmf-tool"], + scripts=["src/py/qpid-cluster", + "src/py/qpid-cluster-store", + "src/py/qpid-config", + "src/py/qpid-ha", + "src/py/qpid-printevents", + "src/py/qpid-queue-stats", + "src/py/qpid-route", + "src/py/qpid-stat", + "src/py/qpid-tool", + "src/py/qmf-tool"], url="http://qpid.apache.org/", license="Apache Software License", description="Diagnostic and management tools for Apache Qpid brokers.") diff --git a/tools/src/py/qmf-tool b/tools/src/py/qmf-tool index 8413ca2ca0..db51c96796 100755 --- a/tools/src/py/qmf-tool +++ b/tools/src/py/qmf-tool @@ -266,7 +266,7 @@ class QmfData: self.conn_options = conn_options self.qmf_options = qmf_options self.agent_filter = '[]' - self.connection = cqpid.Connection(self.url, self.conn_options) + self.connection = cqpid.Connection(self.url, **self.conn_options) self.connection.open() self.session = qmf2.ConsoleSession(self.connection, self.qmf_options) self.session.setAgentFilter(self.agent_filter) diff --git a/tools/src/py/qpid-config b/tools/src/py/qpid-config index 0110c60aa2..1308df765d 100755 --- a/tools/src/py/qpid-config +++ b/tools/src/py/qpid-config @@ -18,12 +18,18 @@ # specific language governing permissions and limitations # under the License. # +import pdb import os from optparse import OptionParser, OptionGroup, IndentedHelpFormatter import sys import locale -from qmf.console import Session + +home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools")) +sys.path.append(os.path.join(home, "python")) + +from qpid.messaging import Connection +from qpidtoollibs import BrokerAgent usage = """ Usage: qpid-config [OPTIONS] @@ -36,15 +42,16 @@ Usage: qpid-config [OPTIONS] qpid-config [OPTIONS] bind [binding-key] [-f -|filename] [all|any] k1=v1 [, k2=v2...] - qpid-config [OPTIONS] unbind [binding-key]""" + qpid-config [OPTIONS] unbind [binding-key] + qpid-config [OPTIONS] reload-acl""" description = """ Examples: $ qpid-config add queue q $ qpid-config add exchange direct d -a localhost:5672 -$ qpid-config exchanges -a 10.1.1.7:10000 -$ qpid-config queues -a guest/guest@broker-host:10000 +$ qpid-config exchanges -b 10.1.1.7:10000 +$ qpid-config queues -b guest/guest@broker-host:10000 Add Exchange values: @@ -55,7 +62,7 @@ Add Exchange values: xml XML Exchange - allows content filtering using an XQuery -Queue Limit Actions +Queue Limit Actions: none (default) - Use broker's default policy reject - Reject enqueued messages @@ -63,12 +70,14 @@ Queue Limit Actions ring - Replace oldest unacquired message with new ring-strict - Replace oldest message, reject if oldest is acquired -Queue Ordering Policies +Replication levels: - fifo (default) - First in, first out - lvq - Last Value Queue ordering, allows queue browsing - lvq-no-browse - Last Value Queue ordering, browsing clients may lose data""" + none - no replication + configuration - replicate queue and exchange existence and bindings, but not messages. + all - replicate configuration and messages +""" +REPLICATE_LEVELS= ["none", "configuration", "all"] class Config: def __init__(self): @@ -77,8 +86,9 @@ class Config: self._connTimeout = 10 self._ignoreDefault = False self._altern_ex = None - self._passive = False self._durable = False + self._replicate = None + self._ha_admin = False self._clusterDurable = False self._if_empty = True self._if_unused = True @@ -87,8 +97,8 @@ class Config: self._maxQueueSize = None self._maxQueueCount = None self._limitPolicy = None - self._order = None self._msgSequence = False + self._lvq_key = None self._ive = False self._eventGeneration = None self._file = None @@ -100,6 +110,7 @@ class Config: self._msgGroupHeader = None self._sharedMsgGroup = False self._extra_arguments = [] + self._start_replica = None self._returnCode = 0 config = Config() @@ -110,8 +121,7 @@ MAX_QUEUE_SIZE = "qpid.max_size" MAX_QUEUE_COUNT = "qpid.max_count" POLICY_TYPE = "qpid.policy_type" CLUSTER_DURABLE = "qpid.persist_last_node" -LVQ = "qpid.last_value_queue" -LVQNB = "qpid.last_value_queue_no_browse" +LVQ_KEY = "qpid.last_value_queue_key" MSG_SEQUENCE = "qpid.msg_sequence" IVE = "qpid.ive" QUEUE_EVENT_GENERATION = "qpid.queue_event_generation" @@ -121,14 +131,18 @@ FLOW_STOP_SIZE = "qpid.flow_stop_size" FLOW_RESUME_SIZE = "qpid.flow_resume_size" MSG_GROUP_HDR_KEY = "qpid.group_header_key" SHARED_MSG_GROUP = "qpid.shared_msg_group" +REPLICATE = "qpid.replicate" #There are various arguments to declare that have specific program #options in this utility. However there is now a generic mechanism for #passing arguments as well. The SPECIAL_ARGS list contains the #arguments for which there are specific program options defined #i.e. the arguments for which there is special processing on add and #list -SPECIAL_ARGS=[FILECOUNT,FILESIZE,MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,CLUSTER_DURABLE,LVQ,LVQNB,MSG_SEQUENCE,IVE,QUEUE_EVENT_GENERATION,FLOW_STOP_COUNT,FLOW_STOP_SIZE,FLOW_RESUME_SIZE, - MSG_GROUP_HDR_KEY,SHARED_MSG_GROUP] +SPECIAL_ARGS=[ + FILECOUNT,FILESIZE,MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,CLUSTER_DURABLE, + LVQ_KEY,MSG_SEQUENCE,IVE,QUEUE_EVENT_GENERATION, + FLOW_STOP_COUNT,FLOW_STOP_SIZE,FLOW_RESUME_SIZE, + MSG_GROUP_HDR_KEY,SHARED_MSG_GROUP,REPLICATE] class JHelpFormatter(IndentedHelpFormatter): """Format usage and description without stripping newlines from usage strings @@ -146,7 +160,7 @@ class JHelpFormatter(IndentedHelpFormatter): def Usage(): print usage - exit(-1) + sys.exit(-1) def OptionsAndArguments(argv): """ Set global variables for options, return arguments """ @@ -160,8 +174,8 @@ def OptionsAndArguments(argv): group1 = OptionGroup(parser, "General Options") group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="", help="Maximum time to wait for broker connection (in seconds)") - group1.add_option("-b", "--bindings", action="store_true", help="Show bindings in queue or exchange list") - group1.add_option("-a", "--broker-addr", action="store", type="string", default="localhost:5672", metavar="
", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:]") + group1.add_option("-r", "--recursive", action="store_true", help="Show bindings in queue or exchange list") + group1.add_option("-b", "--broker", action="store", type="string", default="localhost:5672", metavar="
", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:]") group1.add_option("--sasl-mechanism", action="store", type="string", metavar="", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.") parser.add_option_group(group1) @@ -171,8 +185,9 @@ def OptionsAndArguments(argv): group2 = OptionGroup(parser, "Options for Adding Exchanges and Queues") group2.add_option("--alternate-exchange", action="store", type="string", metavar="", help="Name of the alternate-exchange for the new queue or exchange. Exchanges route messages to the alternate exchange if they are unable to route them elsewhere. Queues route messages to the alternate exchange if they are rejected by a subscriber or orphaned by queue deletion.") - group2.add_option("--passive", "--dry-run", action="store_true", help="Do not actually add the exchange or queue, ensure that all parameters and permissions are correct and would allow it to be created.") group2.add_option("--durable", action="store_true", help="The new queue or exchange is durable.") + group2.add_option("--replicate", action="store", metavar="", help="Enable automatic replication in a HA cluster. is 'none', 'configuration' or 'all').") + group2.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.") parser.add_option_group(group2) group3 = OptionGroup(parser, "Options for Adding Queues") @@ -182,7 +197,7 @@ def OptionsAndArguments(argv): group3.add_option("--max-queue-size", action="store", type="int", metavar="", help="Maximum in-memory queue size as bytes") group3.add_option("--max-queue-count", action="store", type="int", metavar="", help="Maximum in-memory queue size as a number of messages") group3.add_option("--limit-policy", action="store", choices=["none", "reject", "flow-to-disk", "ring", "ring-strict"], metavar="", help="Action to take when queue limit is reached") - group3.add_option("--order", action="store", choices=["fifo", "lvq", "lvq-no-browse"], metavar="", help="Queue ordering policy") + group3.add_option("--lvq-key", action="store", metavar="", help="Last Value Queue key") group3.add_option("--generate-queue-events", action="store", type="int", metavar="", help="If set to 1, every enqueue will generate an event that can be processed by registered listeners (e.g. for replication). If set to 2, events will be generated for enqueues and dequeues.") group3.add_option("--flow-stop-size", action="store", type="int", metavar="", help="Turn on sender flow control when the number of queued bytes exceeds this value.") @@ -198,6 +213,7 @@ def OptionsAndArguments(argv): help="Allow message group consumption across multiple consumers.") group3.add_option("--argument", dest="extra_arguments", action="append", default=[], metavar="", help="Specify a key-value pair to add to queue arguments") + group3.add_option("--start-replica", metavar="", help="Start replication from the same-named queue at ") # no option for declaring an exclusive queue - which can only be used by the session that creates it. parser.add_option_group(group3) @@ -224,10 +240,10 @@ def OptionsAndArguments(argv): except: args = encArgs - if opts.bindings: + if opts.recursive: config._recursive = True - if opts.broker_addr: - config._host = opts.broker_addr + if opts.broker: + config._host = opts.broker if opts.timeout is not None: config._connTimeout = opts.timeout if config._connTimeout == 0: @@ -236,10 +252,13 @@ def OptionsAndArguments(argv): config._ignoreDefault = True if opts.alternate_exchange: config._altern_ex = opts.alternate_exchange - if opts.passive: - config._passive = True if opts.durable: config._durable = True + if opts.replicate: + if not opts.replicate in REPLICATE_LEVELS: + raise Exception("Invalid replication level '%s', should be one of: %s" % (opts.replicate, ", ".join(REPLICATE_LEVELS))) + config._replicate = opts.replicate + if opts.ha_admin: config._ha_admin = True if opts.cluster_durable: config._clusterDurable = True if opts.file: @@ -254,10 +273,10 @@ def OptionsAndArguments(argv): config._maxQueueCount = opts.max_queue_count if opts.limit_policy: config._limitPolicy = opts.limit_policy - if opts.order: - config._order = opts.order if opts.sequence: config._msgSequence = True + if opts.lvq_key: + config._lvq_key = opts.lvq_key if opts.ive: config._ive = True if opts.generate_queue_events: @@ -285,6 +304,8 @@ def OptionsAndArguments(argv): config._sharedMsgGroup = True if opts.extra_arguments: config._extra_arguments = opts.extra_arguments + if opts.start_replica: + config._start_replica = opts.start_replica return args @@ -331,27 +352,24 @@ def snarf_header_args(args): class BrokerManager: def __init__(self): self.brokerName = None - self.qmf = None + self.conn = None self.broker = None - self.mechanism = None def SetBroker(self, brokerUrl, mechanism): self.url = brokerUrl - self.qmf = Session() - self.broker = self.qmf.addBroker(brokerUrl, config._connTimeout, mechanism) - agents = self.qmf.getAgents() - for a in agents: - if a.getAgentBank() == '0': - self.brokerAgent = a + client_properties={} + if config._ha_admin: client_properties["qpid.ha-admin"] = 1 + self.conn = Connection.establish(self.url, sasl_mechanisms=mechanism, client_properties=client_properties) + self.broker = BrokerAgent(self.conn) def Disconnect(self): - if self.broker: - self.qmf.delBroker(self.broker) + if self.conn: + self.conn.close() def Overview(self): - exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent) - queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent) - print "Total Exchanges: %d" % len (exchanges) + exchanges = self.broker.getAllExchanges() + queues = self.broker.getAllQueues() + print "Total Exchanges: %d" % len(exchanges) etype = {} for ex in exchanges: if ex.type not in etype: @@ -362,16 +380,16 @@ class BrokerManager: print "%15s: %d" % (typ, etype[typ]) print - print " Total Queues: %d" % len (queues) + print " Total Queues: %d" % len(queues) durable = 0 for queue in queues: if queue.durable: durable = durable + 1 print " durable: %d" % durable - print " non-durable: %d" % (len (queues) - durable) + print " non-durable: %d" % (len(queues) - durable) def ExchangeList(self, filter): - exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent) + exchanges = self.broker.getAllExchanges() caption1 = "Type " caption2 = "Exchange Name" maxNameLen = len(caption2) @@ -398,22 +416,23 @@ class BrokerManager: args = ex.arguments if not args: args = {} if ex.durable: print "--durable", + if REPLICATE in args: print "--replicate=%s" % args[REPLICATE], if MSG_SEQUENCE in args and args[MSG_SEQUENCE] == 1: print "--sequence", if IVE in args and args[IVE] == 1: print "--ive", if ex.altExchange: - print "--alternate-exchange=%s" % ex._altExchange_.name, + print "--alternate-exchange=%s" % ex.altExchange, print def ExchangeListRecurse(self, filter): - exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent) - bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent) - queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent) + exchanges = self.broker.getAllExchanges() + bindings = self.broker.getAllBindings() + queues = self.broker.getAllQueues() for ex in exchanges: if config._ignoreDefault and not ex.name: continue if self.match(ex.name, filter): print "Exchange '%s' (%s)" % (ex.name, ex.type) for bind in bindings: - if bind.exchangeRef == ex.getObjectId(): + if bind.exchangeRef == ex.name: qname = "" queue = self.findById(queues, bind.queueRef) if queue != None: @@ -425,7 +444,7 @@ class BrokerManager: def QueueList(self, filter): - queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent) + queues = self.broker.getAllQueues() caption = "Queue Name" maxNameLen = len(caption) found = False @@ -450,6 +469,7 @@ class BrokerManager: args = q.arguments if not args: args = {} if q.durable: print "--durable", + if REPLICATE in args: print "--replicate=%s" % args[REPLICATE], if CLUSTER_DURABLE in args and args[CLUSTER_DURABLE] == 1: print "--cluster-durable", if q.autoDelete: print "auto-del", if q.exclusive: print "excl", @@ -458,11 +478,10 @@ class BrokerManager: if MAX_QUEUE_SIZE in args: print "--max-queue-size=%s" % args[MAX_QUEUE_SIZE], if MAX_QUEUE_COUNT in args: print "--max-queue-count=%s" % args[MAX_QUEUE_COUNT], if POLICY_TYPE in args: print "--limit-policy=%s" % args[POLICY_TYPE].replace("_", "-"), - if LVQ in args and args[LVQ] == 1: print "--order lvq", - if LVQNB in args and args[LVQNB] == 1: print "--order lvq-no-browse", + if LVQ_KEY in args: print "--lvq-key=%s" % args[LVQ_KEY], if QUEUE_EVENT_GENERATION in args: print "--generate-queue-events=%s" % args[QUEUE_EVENT_GENERATION], if q.altExchange: - print "--alternate-exchange=%s" % q._altExchange_.name, + print "--alternate-exchange=%s" % q.altExchange, if FLOW_STOP_SIZE in args: print "--flow-stop-size=%s" % args[FLOW_STOP_SIZE], if FLOW_RESUME_SIZE in args: print "--flow-resume-size=%s" % args[FLOW_RESUME_SIZE], if FLOW_STOP_COUNT in args: print "--flow-stop-count=%s" % args[FLOW_STOP_COUNT], @@ -472,14 +491,14 @@ class BrokerManager: print " ".join(["--argument %s=%s" % (k, v) for k,v in args.iteritems() if not k in SPECIAL_ARGS]) def QueueListRecurse(self, filter): - exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent) - bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent) - queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent) + exchanges = self.broker.getAllExchanges() + bindings = self.broker.getAllBindings() + queues = self.broker.getAllQueues() for queue in queues: if self.match(queue.name, filter): print "Queue '%s'" % queue.name for bind in bindings: - if bind.queueRef == queue.getObjectId(): + if bind.queueRef == queue.name: ename = "" ex = self.findById(exchanges, bind.exchangeRef) if ex != None: @@ -508,16 +527,21 @@ class BrokerManager: declArgs[MSG_SEQUENCE] = 1 if config._ive: declArgs[IVE] = 1 - if config._altern_ex != None: - self.broker.getAmqpSession().exchange_declare(exchange=ename, type=etype, alternate_exchange=config._altern_ex, passive=config._passive, durable=config._durable, arguments=declArgs) - else: - self.broker.getAmqpSession().exchange_declare(exchange=ename, type=etype, passive=config._passive, durable=config._durable, arguments=declArgs) + if config._altern_ex: + declArgs['alternate-exchange'] = config._altern_ex + if config._durable: + declArgs['durable'] = 1 + if config._replicate: + declArgs[REPLICATE] = config._replicate + self.broker.addExchange(etype, ename, declArgs) + def DelExchange(self, args): if len(args) < 1: Usage() ename = args[0] - self.broker.getAmqpSession().exchange_delete(exchange=ename) + self.broker.delExchange(ename) + def AddQueue(self, args): if len(args) < 1: @@ -550,15 +574,10 @@ class BrokerManager: elif config._limitPolicy == "ring-strict": declArgs[POLICY_TYPE] = "ring_strict" - if config._clusterDurable: + if config._clusterDurable: declArgs[CLUSTER_DURABLE] = 1 - if config._order: - if config._order == "fifo": - pass - elif config._order == "lvq": - declArgs[LVQ] = 1 - elif config._order == "lvq-no-browse": - declArgs[LVQNB] = 1 + if config._lvq_key: + declArgs[LVQ_KEY] = config._lvq_key if config._eventGeneration: declArgs[QUEUE_EVENT_GENERATION] = config._eventGeneration @@ -576,17 +595,21 @@ class BrokerManager: if config._sharedMsgGroup: declArgs[SHARED_MSG_GROUP] = 1 - if config._altern_ex != None: - self.broker.getAmqpSession().queue_declare(queue=qname, alternate_exchange=config._altern_ex, passive=config._passive, durable=config._durable, arguments=declArgs) - else: - self.broker.getAmqpSession().queue_declare(queue=qname, passive=config._passive, durable=config._durable, arguments=declArgs) - + if config._altern_ex: + declArgs['alternate-exchange'] = config._altern_ex + if config._durable: + declArgs['durable'] = 1 + if config._replicate: + declArgs[REPLICATE] = config._replicate + self.broker.addQueue(qname, declArgs) + if config._start_replica: # Start replication + self.broker._method("replicate", {"broker":config._start_replica, "queue":qname}, "org.apache.qpid.ha:habroker:ha-broker") def DelQueue(self, args): if len(args) < 1: Usage() qname = args[0] - self.broker.getAmqpSession().queue_delete(queue=qname, if_empty=config._if_empty, if_unused=config._if_unused) + self.broker.delQueue(qname) def Bind(self, args): @@ -599,7 +622,7 @@ class BrokerManager: key = args[2] # query the exchange to determine its type. - res = self.broker.getAmqpSession().exchange_query(ename) + res = self.broker.getExchange(ename) # type of the xchg determines the processing of the rest of # argv. if it's an xml xchg, we want to find a file @@ -608,7 +631,7 @@ class BrokerManager: # map containing key/value pairs. if neither of those, extra # args are ignored. ok = True - _args = None + _args = {} if res.type == "xml": # this checks/imports the -f arg [ok, xquery] = snarf_xquery_args() @@ -622,10 +645,7 @@ class BrokerManager: if not ok: sys.exit(1) - self.broker.getAmqpSession().exchange_bind(queue=qname, - exchange=ename, - binding_key=key, - arguments=_args) + self.broker.bind(ename, qname, key, _args) def Unbind(self, args): if len(args) < 2: @@ -635,11 +655,20 @@ class BrokerManager: key = "" if len(args) > 2: key = args[2] - self.broker.getAmqpSession().exchange_unbind(queue=qname, exchange=ename, binding_key=key) + self.broker.unbind(ename, qname, key) + + def ReloadAcl(self): + try: + self.broker.reloadAclFile() + except Exception, e: + if str(e).find('No object found') != -1: + print "Failed: ACL Module Not Loaded in Broker" + else: + raise def findById(self, items, id): for item in items: - if item.getObjectId() == id: + if item.name == id: return item return None @@ -697,6 +726,8 @@ def main(argv=None): bm.Bind(args[1:]) elif cmd == "unbind": bm.Unbind(args[1:]) + elif cmd == "reload-acl": + bm.ReloadAcl() else: Usage() except KeyboardInterrupt: @@ -725,9 +756,9 @@ def main(argv=None): if e.__class__.__name__ != "Timeout": print "Failed: %s: %s" % (e.__class__.__name__, e) return 1 - return config._returnCode + if __name__ == "__main__": sys.exit(main()) diff --git a/tools/src/py/qpid-ha b/tools/src/py/qpid-ha new file mode 100755 index 0000000000..bd8040cfbe --- /dev/null +++ b/tools/src/py/qpid-ha @@ -0,0 +1,153 @@ +#!/usr/bin/env python + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import qmf.console, optparse, sys, time, os +from qpid.management import managementChannel, managementClient +from qpid.messaging import Connection +from qpid.messaging import Message as QpidMessage +from qpidtoollibs.broker import BrokerAgent +try: + from uuid import uuid4 +except ImportError: + from qpid.datatypes import uuid4 + +# QMF address for the HA broker object. +HA_BROKER = "org.apache.qpid.ha:habroker:ha-broker" + +class Command: + commands = {} + + def __init__(self, name, help, args=[]): + Command.commands[name] = self + self.name = name + self.args = args + usage="%s [options] %s\n\n%s"%(name, " ".join(args), help) + self.help = help + self.op=optparse.OptionParser(usage) + self.op.add_option("-b", "--broker", metavar="", help="Connect to broker at ") + + def execute(self): + opts, args = self.op.parse_args() + if len(args) != len(self.args)+1: + self.op.print_help() + raise Exception("Wrong number of arguments") + broker = opts.broker or "localhost:5672" + connection = Connection.establish(broker, client_properties={"qpid.ha-admin":1}) + qmf_broker = BrokerAgent(connection) + ha_broker = qmf_broker.getHaBroker() + if not ha_broker: raise Exception("HA module is not loaded on broker at %s"%broker) + try: return self.do_execute(qmf_broker, ha_broker, opts, args) + finally: connection.close() + + def do_execute(self, qmf_broker, opts, args): + raise Exception("Command '%s' is not yet implemented"%self.name) + +class PromoteCmd(Command): + def __init__(self): + Command.__init__(self, "promote","Promote broker from backup to primary") + def do_execute(self, qmf_broker, ha_broker, opts, args): + qmf_broker._method("promote", {}, HA_BROKER) +PromoteCmd() + +class StatusCmd(Command): + def __init__(self): + Command.__init__(self, "status", "Print HA status") + self.op.add_option( + "--expect", type="string", metavar="", + help="Don't print status but return 0 if it matches , 1 otherwise") + def do_execute(self, qmf_broker, ha_broker, opts, args): + if opts.expect: + if opts.expect != ha_broker.status: return 1 + else: + print ha_broker.status + return 0 +StatusCmd() + +class ReplicateCmd(Command): + def __init__(self): + Command.__init__(self, "replicate", "Set up replication from on to on the current broker.", ["", ""]) + def do_execute(self, qmf_broker, ha_broker, opts, args): + qmf_broker._method("replicate", {"broker":args[1], "queue":args[2]}, HA_BROKER) +ReplicateCmd() + +class SetCmd(Command): + def __init__(self): + Command.__init__(self, "set", "Set HA configuration settings") + def add(optname, metavar, type, help): + self.op.add_option(optname, metavar=metavar, type=type, help=help, action="store") + add("--brokers", "", "string", "HA brokers use to connect to each other") + add("--public-brokers", "", "string", "Clients use to connect to HA brokers") + add("--backups", "", "int", "Expect backups to be running"), + + def do_execute(self, qmf_broker, ha_broker, opts, args): + if (opts.brokers): qmf_broker._method("setBrokers", {"url":opts.brokers}, HA_BROKER) + if (opts.public_brokers): qmf_broker._method("setPublicBrokers", {"url":opts.public_brokers}, HA_BROKER) + if (opts.backups): qmf_broker._method("setExpectedBackups", {"expectedBackups":opts.backups}, HA_BROKER) + +SetCmd() + +class QueryCmd(Command): + def __init__(self): + Command.__init__(self, "query", "Print HA configuration settings") + + def do_execute(self, qmf_broker, ha_broker, opts, args): + hb = ha_broker + for x in [("Status:", hb.status), + ("Brokers URL:", hb.brokers), + ("Public URL:", hb.publicBrokers), + ("Expected Backups:", hb.expectedBackups), + ("Replicate: ", hb.replicateDefault) + ]: + print "%-20s %s"%(x[0], x[1]) +QueryCmd() + +def print_usage(prog): + print "usage: %s []\n\nCommands are:\n"%prog + for name, command in Command.commands.iteritems(): + help = command.help + print " %-12s %s."%(name, help.split(".")[0]) + print "\nFor help with a command type: %s --help\n"%prog + +def find_command(args): + """Find a command among the arguments and options""" + for arg in args: + if arg in Command.commands: + return Command.commands[arg] + return None + +def main(argv): + try: + args=argv[1:] + if args and args[0] == "--help-all": + for c in Command.commands.itervalues(): + c.op.print_help(); print + return 1 + command = find_command(args) + if not command: + print_usage(os.path.basename(argv[0])); + return 1; + if command.execute(): return 1 + except Exception, e: + print e + return 1 + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/tools/src/py/qpid-ha-tool b/tools/src/py/qpid-ha-tool deleted file mode 100755 index 8e8107657c..0000000000 --- a/tools/src/py/qpid-ha-tool +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import qmf.console, optparse, sys -from qpid.management import managementChannel, managementClient -from qpid.messaging import Connection -from qpid.messaging import Message as QpidMessage -try: - from uuid import uuid4 -except ImportError: - from qpid.datatypes import uuid4 - -# Utility for doing fast qmf2 operations on a broker. -class QmfBroker(object): - def __init__(self, conn): - self.conn = conn - self.sess = self.conn.session() - self.reply_to = "qmf.default.topic/direct.%s;{node:{type:topic}, link:{x-declare:{auto-delete:True,exclusive:True}}}" % \ - str(uuid4()) - self.reply_rx = self.sess.receiver(self.reply_to) - self.reply_rx.capacity = 10 - self.tx = self.sess.sender("qmf.default.direct/broker") - self.next_correlator = 1 - - def close(self): - self.conn.close() - - def __repr__(self): - return "Qpid Broker: %s" % self.url - - def _method(self, method, arguments, addr="org.apache.qpid.broker:broker:amqp-broker"): - props = {'method' : 'request', - 'qmf.opcode' : '_method_request', - 'x-amqp-0-10.app-id' : 'qmf2'} - correlator = str(self.next_correlator) - self.next_correlator += 1 - - content = {'_object_id' : {'_object_name' : addr}, - '_method_name' : method, - '_arguments' : arguments} - - message = QpidMessage(content, reply_to=self.reply_to, correlation_id=correlator, - properties=props, subject="broker") - self.tx.send(message) - response = self.reply_rx.fetch(10) - if response.properties['qmf.opcode'] == '_exception': - raise Exception("Exception from Agent: %r" % response.content['_values']) - if response.properties['qmf.opcode'] != '_method_response': - raise Exception("bad response: %r" % response.properties) - return response.content['_arguments'] - - def _sendRequest(self, opcode, content): - props = {'method' : 'request', - 'qmf.opcode' : opcode, - 'x-amqp-0-10.app-id' : 'qmf2'} - correlator = str(self.next_correlator) - self.next_correlator += 1 - message = QpidMessage(content, reply_to=self.reply_to, correlation_id=correlator, - properties=props, subject="broker") - self.tx.send(message) - return correlator - - def _doClassQuery(self, class_name): - query = {'_what' : 'OBJECT', - '_schema_id' : {'_class_name' : class_name}} - correlator = self._sendRequest('_query_request', query) - response = self.reply_rx.fetch(10) - if response.properties['qmf.opcode'] != '_query_response': - raise Exception("bad response") - items = [] - done = False - while not done: - for item in response.content: - items.append(item['_values']) - if 'partial' in response.properties: - response = self.reply_rx.fetch(10) - else: - done = True - return items - - def _doNameQuery(self, class_name, object_name, package_name='org.apache.qpid.broker'): - query = {'_what' : 'OBJECT', - '_object_id' : {'_object_name' : "%s:%s:%s" % (package_name, class_name, object_name)}} - correlator = self._sendRequest('_query_request', query) - response = self.reply_rx.fetch(10) - if response.properties['qmf.opcode'] != '_query_response': - raise Exception("bad response") - items = [] - done = False - while not done: - for item in response.content: - items.append(item['_values']) - if 'partial' in response.properties: - response = self.reply_rx.fetch(10) - else: - done = True - if len(items) == 1: - return items[0] - return None - - def _getAllBrokerObjects(self, cls): - items = self._doClassQuery(cls.__name__.lower()) - objs = [] - for item in items: - objs.append(cls(self, item)) - return objs - - def _getBrokerObject(self, cls, name): - obj = self._doNameQuery(cls.__name__.lower(), name) - if obj: - return cls(self, obj) - return None - - -op=optparse.OptionParser(usage="Usage: %prog [options] [broker-address]") - -op.add_option("-p", "--promote", action="store_true", - help="Promote a backup broker to become the primary.") -op.add_option("-c", "--client-addresses", action="store", type="string", - help="Set list of addresses used by clients to connect to the HA cluster.") -op.add_option("-b", "--broker-addresses", action="store", type="string", - help="Set list of addresses used by HA brokers to connect to each other.") -op.add_option("-q", "--query", action="store_true", - help="Show the current HA settings on the broker.") - -def get_ha_broker(qmf_broker): - ha_brokers = qmf_broker._doClassQuery("habroker") - if (not ha_brokers): raise Exception("Broker does not have HA enabled.") - return ha_brokers[0] - -def main(argv): - try: - opts, args = op.parse_args(argv) - if len(args) >1: broker = args[1] - else: broker = "localhost:5672" - conn = Connection.establish(broker, client_properties={"qpid.ha-admin":1}) - ha_broker = "org.apache.qpid.ha:habroker:ha-broker" - try: - qmf_broker = QmfBroker(conn) - get_ha_broker(qmf_broker) # Verify that HA is enabled - action=False - if opts.promote: - qmf_broker._method("promote", {}, ha_broker) - action=True - if opts.broker_addresses: - qmf_broker._method('setBrokerAddresses', {'brokerAddresses':opts.broker_addresses}, ha_broker) - action=True - if opts.client_addresses: - qmf_broker._method('setClientAddresses', {'clientAddresses':opts.client_addresses}, ha_broker) - action=True - if opts.query or not action: - hb = get_ha_broker(qmf_broker) - print "status=%s"%hb["status"] - print "broker-addresses=%s"%hb["brokerAddresses"] - print "client-addresses=%s"%hb["clientAddresses"] - return 0 - finally: - conn.close() # Avoid errors shutting down threads. - except Exception, e: - raise # FIXME aconway 2012-01-31: - print e - return 1 - -if __name__ == "__main__": - sys.exit(main(sys.argv)) diff --git a/tools/src/py/qpid-route b/tools/src/py/qpid-route index f90416d7b0..0316c24322 100755 --- a/tools/src/py/qpid-route +++ b/tools/src/py/qpid-route @@ -62,6 +62,7 @@ class Config: self._ack = 0 self._connTimeout = 10 self._client_sasl_mechanism = None + self._ha_admin = False config = Config() @@ -96,7 +97,7 @@ def OptionsAndArguments(argv): parser.add_option("-t", "--transport", action="store", type="string", default="tcp", metavar="", help="Transport to use for links, defaults to tcp") parser.add_option("--client-sasl-mechanism", action="store", type="string", metavar="", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). Used when the client connects to the destination broker (not for authentication between the source and destination brokers - that is specified using the [mechanisms] argument to 'add route'). SASL automatically picks the most secure available mechanism - use this option to override.") - + parser.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.") opts, encArgs = parser.parse_args(args=argv) try: @@ -128,6 +129,9 @@ def OptionsAndArguments(argv): if opts.transport: config._transport = opts.transport + if opts.ha_admin: + config._ha_admin = True + if opts.ack: config._ack = opts.ack @@ -143,7 +147,9 @@ class RouteManager: self.local = BrokerURL(localBroker) self.remote = None self.qmf = Session() - self.broker = self.qmf.addBroker(localBroker, config._connTimeout, config._client_sasl_mechanism) + client_properties = {} + if config._ha_admin: client_properties["qpid.ha-admin"] = 1 + self.broker = self.qmf.addBroker(localBroker, config._connTimeout, config._client_sasl_mechanism, client_properties=client_properties) self.broker._waitForStable() self.agent = self.broker.getBrokerAgent() diff --git a/tools/src/py/qpid-stat b/tools/src/py/qpid-stat index bb094554e6..5a816baf6e 100755 --- a/tools/src/py/qpid-stat +++ b/tools/src/py/qpid-stat @@ -30,8 +30,8 @@ from qpid.messaging import Connection home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools")) sys.path.append(os.path.join(home, "python")) -from qpidtoollibs.broker import BrokerAgent -from qpidtoollibs.disp import Display, Header, Sorter +from qpidtoollibs import BrokerAgent +from qpidtoollibs import Display, Header, Sorter, YN, Commas, TimeLong class Config: @@ -42,8 +42,8 @@ class Config: self._limit = 50 self._increasing = False self._sortcol = None - self._details = None self._sasl_mechanism = None + self._ha_admin = False config = Config() @@ -52,42 +52,45 @@ def OptionsAndArguments(argv): global config - parser = OptionParser(usage="usage: %prog [options] BROKER", - description="Example: $ qpid-stat -q broker-host:10000") + parser = OptionParser(usage="usage: %prog [options] -[gcequm] [object-name]") group1 = OptionGroup(parser, "General Options") - group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="", help="Maximum time to wait for broker connection (in seconds)") - group1.add_option("--sasl-mechanism", action="store", type="string", metavar="", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.") + group1.add_option("-b", "--broker", action="store", type="string", default="localhost", metavar="", + help="URL of the broker to query") + group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="", + help="Maximum time to wait for broker connection (in seconds)") + group1.add_option("--sasl-mechanism", action="store", type="string", metavar="", + help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.") + group1.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.") parser.add_option_group(group1) group2 = OptionGroup(parser, "Display Options") - group2.add_option("-b", "--broker", help="Show Brokers", action="store_const", const="b", dest="show") - group2.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show") - group2.add_option("-e", "--exchanges", help="Show Exchanges", action="store_const", const="e", dest="show") - group2.add_option("-q", "--queues", help="Show Queues", action="store_const", const="q", dest="show") - group2.add_option("-u", "--subscriptions", help="Show Subscriptions", action="store_const", const="u", dest="show") - group2.add_option("-m", "--memory", help="Show Broker Memory Stats", action="store_const", const="m", dest="show") + group2.add_option("-g", "--general", help="Show General Broker Stats", action="store_const", const="g", dest="show") + group2.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show") + group2.add_option("-e", "--exchanges", help="Show Exchanges", action="store_const", const="e", dest="show") + group2.add_option("-q", "--queues", help="Show Queues", action="store_const", const="q", dest="show") + group2.add_option("-u", "--subscriptions", help="Show Subscriptions", action="store_const", const="u", dest="show") + group2.add_option("-m", "--memory", help="Show Broker Memory Stats", action="store_const", const="m", dest="show") + group2.add_option( "--acl", help="Show Access Control List Stats", action="store_const", const="acl", dest="show") group2.add_option("-S", "--sort-by", metavar="", help="Sort by column name") group2.add_option("-I", "--increasing", action="store_true", default=False, help="Sort by increasing value (default = decreasing)") group2.add_option("-L", "--limit", type="int", default=50, metavar="", help="Limit output to n rows") - group2.add_option("-D", "--details", action="store", metavar="", dest="detail", default=None, help="Display details on a single object.") + parser.add_option_group(group2) opts, args = parser.parse_args(args=argv) if not opts.show: - parser.error("You must specify one of these options: -b, -c, -e, -q. or -u. For details, try $ qpid-stat --help") + parser.error("You must specify one of these options: -g, -c, -e, -q, -m, or -u. For details, try $ qpid-stat --help") config._types = opts.show config._sortcol = opts.sort_by + config._host = opts.broker config._connTimeout = opts.timeout config._increasing = opts.increasing config._limit = opts.limit config._sasl_mechanism = opts.sasl_mechanism - config._detail = opts.detail - - if args: - config._host = args[0] + config._ha_admin = opts.ha_admin return args @@ -118,24 +121,24 @@ class IpAddr: class BrokerManager: def __init__(self): - self.brokerName = None - self.connections = [] - self.brokers = [] - self.cluster = None + self.brokerName = None + self.connection = None + self.broker = None + self.cluster = None def SetBroker(self, brokerUrl, mechanism): self.url = brokerUrl - self.connections.append(Connection(self.url, sasl_mechanism=mechanism)) - self.connections[0].open() - self.brokers.append(BrokerAgent(self.connections[0])) + client_properties={} + if config._ha_admin: client_properties["qpid.ha-admin"] = 1 + self.connection = Connection.establish(self.url, sasl_mechanisms=mechanism, client_properties=client_properties) + self.broker = BrokerAgent(self.connection) def Disconnect(self): """ Release any allocated brokers. Ignore any failures as the tool is shutting down. """ try: - for conn in self.connections: - conn.close() + connection.close() except: pass @@ -175,7 +178,7 @@ class BrokerManager: hosts.append(bestUrl) return hosts - def displayBroker(self, subs): + def displayBroker(self): disp = Display(prefix=" ") heads = [] heads.append(Header('uptime', Header.DURATION)) @@ -184,7 +187,7 @@ class BrokerManager: heads.append(Header('exchanges', Header.COMMAS)) heads.append(Header('queues', Header.COMMAS)) rows = [] - broker = self.brokers[0].getBroker() + broker = self.broker.getBroker() connections = self.getConnectionMap() sessions = self.getSessionMap() exchanges = self.getExchangeMap() @@ -229,7 +232,7 @@ class BrokerManager: disp.formattedTable('Aggregate Broker Statistics:', heads, rows) - def displayConn(self, subs): + def displayConn(self): disp = Display(prefix=" ") heads = [] heads.append(Header('client-addr')) @@ -241,8 +244,8 @@ class BrokerManager: heads.append(Header('msgIn', Header.KMG)) heads.append(Header('msgOut', Header.KMG)) rows = [] - connections = self.brokers[0].getAllConnections() - broker = self.brokers[0].getBroker() + connections = self.broker.getAllConnections() + broker = self.broker.getBroker() for conn in connections: row = [] row.append(conn.address) @@ -262,10 +265,10 @@ class BrokerManager: dispRows = rows disp.formattedTable(title, heads, dispRows) - def displaySession(self, subs): + def displaySession(self): disp = Display(prefix=" ") - def displayExchange(self, subs): + def displayExchange(self): disp = Display(prefix=" ") heads = [] heads.append(Header("exchange")) @@ -279,7 +282,7 @@ class BrokerManager: heads.append(Header("byteOut", Header.KMG)) heads.append(Header("byteDrop", Header.KMG)) rows = [] - exchanges = self.brokers[0].getAllExchanges() + exchanges = self.broker.getAllExchanges() for ex in exchanges: row = [] row.append(ex.name) @@ -301,7 +304,7 @@ class BrokerManager: dispRows = rows disp.formattedTable(title, heads, dispRows) - def displayQueues(self, subs): + def displayQueues(self): disp = Display(prefix=" ") heads = [] heads.append(Header("queue")) @@ -317,7 +320,7 @@ class BrokerManager: heads.append(Header("cons", Header.KMG)) heads.append(Header("bind", Header.KMG)) rows = [] - queues = self.brokers[0].getAllQueues() + queues = self.broker.getAllQueues() for q in queues: row = [] row.append(q.name) @@ -341,11 +344,67 @@ class BrokerManager: dispRows = rows disp.formattedTable(title, heads, dispRows) - def displayQueue(self, subs): + + def displayQueue(self, name): + queue = self.broker.getQueue(name) + if not queue: + print "Queue '%s' not found" % name + return + disp = Display(prefix=" ") heads = [] + heads.append(Header('Name')) + heads.append(Header('Durable', Header.YN)) + heads.append(Header('AutoDelete', Header.YN)) + heads.append(Header('Exclusive', Header.YN)) + heads.append(Header('FlowStopped', Header.YN)) + heads.append(Header('FlowStoppedCount', Header.COMMAS)) + heads.append(Header('Consumers', Header.COMMAS)) + heads.append(Header('Bindings', Header.COMMAS)) + rows = [] + rows.append([queue.name, queue.durable, queue.autoDelete, queue.exclusive, + queue.flowStopped, queue.flowStoppedCount, + queue.consumerCount, queue.bindingCount]) + disp.formattedTable("Properties:", heads, rows) + print + + heads = [] + heads.append(Header('Property')) + heads.append(Header('Value')) + rows = [] + rows.append(['arguments', queue.arguments]) + rows.append(['alt-exchange', queue.altExchange]) + disp.formattedTable("Optional Properties:", heads, rows) + print - def displaySubscriptions(self, subs): + heads = [] + heads.append(Header('Statistic')) + heads.append(Header('Messages', Header.COMMAS)) + heads.append(Header('Bytes', Header.COMMAS)) + rows = [] + rows.append(['queue-depth', queue.msgDepth, queue.byteDepth]) + rows.append(['total-enqueues', queue.msgTotalEnqueues, queue.byteTotalEnqueues]) + rows.append(['total-dequeues', queue.msgTotalDequeues, queue.byteTotalDequeues]) + rows.append(['persistent-enqueues', queue.msgPersistEnqueues, queue.bytePersistEnqueues]) + rows.append(['persistent-dequeues', queue.msgPersistDequeues, queue.bytePersistDequeues]) + rows.append(['transactional-enqueues', queue.msgTxnEnqueues, queue.byteTxnEnqueues]) + rows.append(['transactional-dequeues', queue.msgTxnDequeues, queue.byteTxnDequeues]) + rows.append(['flow-to-disk-depth', queue.msgFtdDepth, queue.byteFtdDepth]) + rows.append(['flow-to-disk-enqueues', queue.msgFtdEnqueues, queue.byteFtdEnqueues]) + rows.append(['flow-to-disk-dequeues', queue.msgFtdDequeues, queue.byteFtdDequeues]) + rows.append(['acquires', queue.acquires, None]) + rows.append(['releases', queue.releases, None]) + rows.append(['discards-ttl-expired', queue.discardsTtl, None]) + rows.append(['discards-limit-overflow', queue.discardsOverflow, None]) + rows.append(['discards-ring-overflow', queue.discardsRing, None]) + rows.append(['discards-lvq-replace', queue.discardsLvq, None]) + rows.append(['discards-subscriber-reject', queue.discardsSubscriber, None]) + rows.append(['discards-purged', queue.discardsPurge, None]) + rows.append(['reroutes', queue.reroutes, None]) + disp.formattedTable("Statistics:", heads, rows) + + + def displaySubscriptions(self): disp = Display(prefix=" ") heads = [] heads.append(Header("subscr")) @@ -359,7 +418,7 @@ class BrokerManager: heads.append(Header("creditMode")) heads.append(Header("delivered", Header.KMG)) rows = [] - subscriptions = self.brokers[0].getAllSubscriptions() + subscriptions = self.broker.getAllSubscriptions() sessions = self.getSessionMap() connections = self.getConnectionMap() for s in subscriptions: @@ -388,59 +447,75 @@ class BrokerManager: dispRows = rows disp.formattedTable(title, heads, dispRows) - def displayMemory(self, unused): + def displayMemory(self): disp = Display(prefix=" ") heads = [Header('Statistic'), Header('Value', Header.COMMAS)] rows = [] - memory = self.brokers[0].getMemory() + memory = self.broker.getMemory() for k,v in memory.values.items(): if k != 'name': rows.append([k, v]) disp.formattedTable('Broker Memory Statistics:', heads, rows) + def displayAcl(self): + acl = self.broker.getAcl() + if not acl: + print "ACL Policy Module is not installed" + return + disp = Display(prefix=" ") + heads = [Header('Statistic'), Header('Value')] + rows = [] + rows.append(['policy-file', acl.policyFile]) + rows.append(['enforcing', YN(acl.enforcingAcl)]) + rows.append(['has-transfer-acls', YN(acl.transferAcl)]) + rows.append(['last-acl-load', TimeLong(acl.lastAclLoad)]) + rows.append(['acl-denials', Commas(acl.aclDenyCount)]) + disp.formattedTable('ACL Policy Statistics:', heads, rows) + def getExchangeMap(self): - exchanges = self.brokers[0].getAllExchanges() + exchanges = self.broker.getAllExchanges() emap = {} for e in exchanges: emap[e.name] = e return emap def getQueueMap(self): - queues = self.brokers[0].getAllQueues() + queues = self.broker.getAllQueues() qmap = {} for q in queues: qmap[q.name] = q return qmap def getSessionMap(self): - sessions = self.brokers[0].getAllSessions() + sessions = self.broker.getAllSessions() smap = {} for s in sessions: smap[s.name] = s return smap def getConnectionMap(self): - connections = self.brokers[0].getAllConnections() + connections = self.broker.getAllConnections() cmap = {} for c in connections: cmap[c.address] = c return cmap - def displayMain(self, main, subs): - if main == 'b': self.displayBroker(subs) - elif main == 'c': self.displayConn(subs) - elif main == 's': self.displaySession(subs) - elif main == 'e': self.displayExchange(subs) + def displayMain(self, names, main): + if main == 'g': self.displayBroker() + elif main == 'c': self.displayConn() + elif main == 's': self.displaySession() + elif main == 'e': self.displayExchange() elif main == 'q': - if config._detail: - self.displayQueue(subs, config._detail) + if len(names) >= 1: + self.displayQueue(names[0]) else: - self.displayQueues(subs) - elif main == 'u': self.displaySubscriptions(subs) - elif main == 'm': self.displayMemory(subs) + self.displayQueues() + elif main == 'u': self.displaySubscriptions() + elif main == 'm': self.displayMemory() + elif main == 'acl': self.displayAcl() - def display(self): - self.displayMain(config._types[0], config._types[1:]) + def display(self, names): + self.displayMain(names, config._types) def main(argv=None): @@ -450,7 +525,7 @@ def main(argv=None): try: bm.SetBroker(config._host, config._sasl_mechanism) - bm.display() + bm.display(args) bm.Disconnect() return 0 except KeyboardInterrupt: diff --git a/tools/src/py/qpidtoollibs/__init__.py b/tools/src/py/qpidtoollibs/__init__.py index 31d5a2ef58..2815bac22f 100644 --- a/tools/src/py/qpidtoollibs/__init__.py +++ b/tools/src/py/qpidtoollibs/__init__.py @@ -16,3 +16,7 @@ # specific language governing permissions and limitations # under the License. # + +from qpidtoollibs.broker import * +from qpidtoollibs.disp import * + diff --git a/tools/src/py/qpidtoollibs/broker.py b/tools/src/py/qpidtoollibs/broker.py index 6a380caf8d..0bae786306 100644 --- a/tools/src/py/qpidtoollibs/broker.py +++ b/tools/src/py/qpidtoollibs/broker.py @@ -24,6 +24,9 @@ except ImportError: from qpid.datatypes import uuid4 class BrokerAgent(object): + """ + Proxy for a manageable Qpid Broker - Invoke with an opened qpid.messaging.Connection. + """ def __init__(self, conn): self.conn = conn self.sess = self.conn.session() @@ -35,6 +38,9 @@ class BrokerAgent(object): self.next_correlator = 1 def close(self): + """ + Close the proxy session. This will not affect the connection used in creating the object. + """ self.sess.close() def _method(self, method, arguments, addr="org.apache.qpid.broker:broker:amqp-broker", timeout=10): @@ -89,9 +95,8 @@ class BrokerAgent(object): self.sess.acknowledge() return items - def _doNameQuery(self, class_name, object_name, package_name='org.apache.qpid.broker'): - query = {'_what' : 'OBJECT', - '_object_id' : {'_object_name' : "%s:%s:%s" % (package_name, class_name, object_name)}} + def _doNameQuery(self, object_id): + query = {'_what' : 'OBJECT', '_object_id' : {'_object_name' : object_id}} correlator = self._sendRequest('_query_request', query) response = self.reply_rx.fetch(10) if response.properties['qmf.opcode'] != '_query_response': @@ -116,65 +121,74 @@ class BrokerAgent(object): for item in items: objs.append(cls(self, item)) return objs - - def _getBrokerObject(self, cls, name): - obj = self._doNameQuery(cls.__name__.lower(), name) + + def _getBrokerObject(self, cls, oid): + obj = self._doNameQuery(oid) if obj: return cls(self, obj) return None - def getCluster(self): - return self._getAllBrokerObjects(Cluster) - - def getBroker(self): + def _getSingleObject(self, cls): # # getAllBrokerObjects is used instead of getBrokerObject(Broker, 'amqp-broker') because # of a bug that used to be in the broker whereby by-name queries did not return the # object timestamps. # - brokers = self._getAllBrokerObjects(Broker) - if brokers: - return brokers[0] + objects = self._getAllBrokerObjects(cls) + if objects: return objects[0] return None - def getMemory(self): - return self._getAllBrokerObjects(Memory)[0] + def getBroker(self): + """ + Get the Broker object that contains broker-scope statistics and operations. + """ + return self._getSingleObject(Broker) + + + def getCluster(self): + return self._getSingleObject(Cluster) + + def getHaBroker(self): + return self._getSingleObject(HaBroker) def getAllConnections(self): return self._getAllBrokerObjects(Connection) - def getConnection(self, name): - return self._getBrokerObject(Connection, name) + def getConnection(self, oid): + return self._getBrokerObject(Connection, "org.apache.qpid.broker:connection:%s" % oid) def getAllSessions(self): return self._getAllBrokerObjects(Session) - def getSession(self, name): - return self._getBrokerObject(Session, name) + def getSession(self, oid): + return self._getBrokerObject(Session, "org.apache.qpid.broker:session:%s" % oid) def getAllSubscriptions(self): return self._getAllBrokerObjects(Subscription) - def getSubscription(self, name): - return self._getBrokerObject(Subscription, name) + def getSubscription(self, oid): + return self._getBrokerObject(Subscription, "org.apache.qpid.broker:subscription:%s" % oid) def getAllExchanges(self): return self._getAllBrokerObjects(Exchange) def getExchange(self, name): - return self._getBrokerObject(Exchange, name) + return self._getBrokerObject(Exchange, "org.apache.qpid.broker:exchange:%s" % name) def getAllQueues(self): return self._getAllBrokerObjects(Queue) def getQueue(self, name): - return self._getBrokerObject(Queue, name) + return self._getBrokerObject(Queue, "org.apache.qpid.broker:queue:%s" % name) def getAllBindings(self): return self._getAllBrokerObjects(Binding) - def getBinding(self, exchange=None, queue=None): - pass + def getAllLinks(self): + return self._getAllBrokerObjects(Link) + + def getAcl(self): + return self._getSingleObject(Acl) def echo(self, sequence, body): """Request a response to test the path to the management broker""" @@ -204,23 +218,69 @@ class BrokerAgent(object): """Get the message timestamping configuration""" pass -# def addExchange(self, exchange_type, name, **kwargs): -# pass - -# def delExchange(self, name): -# pass - -# def addQueue(self, name, **kwargs): -# pass - -# def delQueue(self, name): -# pass - -# def bind(self, exchange, queue, key, **kwargs): -# pass - -# def unbind(self, exchange, queue, key, **kwargs): -# pass + def addExchange(self, exchange_type, name, options={}, **kwargs): + properties = {} + properties['exchange-type'] = exchange_type + for k,v in options.items(): + properties[k] = v + for k,v in kwargs.items(): + properties[k] = v + args = {'type': 'exchange', + 'name': name, + 'properties': properties, + 'strict': True} + self._method('create', args) + + def delExchange(self, name): + args = {'type': 'exchange', 'name': name} + self._method('delete', args) + + def addQueue(self, name, options={}, **kwargs): + properties = options + for k,v in kwargs.items(): + properties[k] = v + args = {'type': 'queue', + 'name': name, + 'properties': properties, + 'strict': True} + self._method('create', args) + + def delQueue(self, name): + args = {'type': 'queue', 'name': name} + self._method('delete', args) + + def bind(self, exchange, queue, key, options={}, **kwargs): + properties = options + for k,v in kwargs.items(): + properties[k] = v + args = {'type': 'binding', + 'name': "%s/%s/%s" % (exchange, queue, key), + 'properties': properties, + 'strict': True} + self._method('create', args) + + def unbind(self, exchange, queue, key, **kwargs): + args = {'type': 'binding', + 'name': "%s/%s/%s" % (exchange, queue, key), + 'strict': True} + self._method('delete', args) + + def reloadAclFile(self): + self._method('reloadACLFile', {}, "org.apache.qpid.acl:acl:org.apache.qpid.broker:broker:amqp-broker") + + def acl_lookup(self, userName, action, aclObj, aclObjName, propMap): + args = {'userId': userName, + 'action': action, + 'object': aclObj, + 'objectName': aclObjName, + 'propertyMap': propMap} + return self._method('Lookup', args, "org.apache.qpid.acl:acl:org.apache.qpid.broker:broker:amqp-broker") + + def acl_lookupPublish(self, userName, exchange, key): + args = {'userId': userName, + 'exchangeName': exchange, + 'routingKey': key} + return self._method('LookupPublish', args, "org.apache.qpid.acl:acl:org.apache.qpid.broker:broker:amqp-broker") def create(self, _type, name, properties, strict): """Create an object of the specified type""" @@ -230,9 +290,9 @@ class BrokerAgent(object): """Delete an object of the specified type""" pass - def query(self, _type, name): + def query(self, _type, oid): """Query the current state of an object""" - return self._getBrokerObject(self, _type, name) + return self._getBrokerObject(self, _type, oid) class BrokerObject(object): @@ -255,6 +315,9 @@ class BrokerObject(object): return full_name[colon+1:] return value + def getObjectId(self): + return self.content['_object_id']['_object_name'] + def getAttributes(self): return self.values @@ -271,7 +334,7 @@ class BrokerObject(object): """ Reload the property values from the agent. """ - refreshed = self.broker._getBrokerObject(self.__class__, self.name) + refreshed = self.broker._getBrokerObject(self.__class__, self.getObjectId()) if refreshed: self.content = refreshed.content self.values = self.content['_values'] @@ -282,6 +345,14 @@ class Broker(BrokerObject): def __init__(self, broker, values): BrokerObject.__init__(self, broker, values) +class Cluster(BrokerObject): + def __init__(self, broker, values): + BrokerObject.__init__(self, broker, values) + +class HaBroker(BrokerObject): + def __init__(self, broker, values): + BrokerObject.__init__(self, broker, values) + class Memory(BrokerObject): def __init__(self, broker, values): BrokerObject.__init__(self, broker, values) @@ -328,3 +399,10 @@ class Queue(BrokerObject): self.broker._method("reroute", {'request':request,'useAltExchange':useAltExchange,'exchange':exchange,'filter':filter}, "org.apache.qpid.broker:queue:%s" % self.name) +class Link(BrokerObject): + def __init__(self, broker, values): + BrokerObject.__init__(self, broker, values) + +class Acl(BrokerObject): + def __init__(self, broker, values): + BrokerObject.__init__(self, broker, values) diff --git a/tools/src/py/qpidtoollibs/disp.py b/tools/src/py/qpidtoollibs/disp.py index cb7d3da306..a0c77370a5 100644 --- a/tools/src/py/qpidtoollibs/disp.py +++ b/tools/src/py/qpidtoollibs/disp.py @@ -21,6 +21,31 @@ from time import strftime, gmtime +def YN(val): + if val: + return 'Y' + return 'N' + +def Commas(value): + sval = str(value) + result = "" + while True: + if len(sval) == 0: + return result + left = sval[:-3] + right = sval[-3:] + result = right + result + if len(left) > 0: + result = ',' + result + sval = left + +def TimeLong(value): + return strftime("%c", gmtime(value / 1000000000)) + +def TimeShort(value): + return strftime("%X", gmtime(value / 1000000000)) + + class Header: """ """ NONE = 1 @@ -59,9 +84,9 @@ class Header: return 'Y' return '' if self.format == Header.TIME_LONG: - return strftime("%c", gmtime(value / 1000000000)) + return TimeLong(value) if self.format == Header.TIME_SHORT: - return strftime("%X", gmtime(value / 1000000000)) + return TimeShort(value) if self.format == Header.DURATION: if value < 0: value = 0 sec = value / 1000000000 @@ -78,17 +103,7 @@ class Header: result += "%ds" % (sec % 60) return result if self.format == Header.COMMAS: - sval = str(value) - result = "" - while True: - if len(sval) == 0: - return result - left = sval[:-3] - right = sval[-3:] - result = right + result - if len(left) > 0: - result = ',' + result - sval = left + return Commas(value) except: return "?" diff --git a/wcf/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp b/wcf/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp index 33d125e3c6..ec98289923 100644 --- a/wcf/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp +++ b/wcf/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp @@ -49,6 +49,7 @@ #include "qpid/client/AsyncSession.h" #include "qpid/client/Connection.h" +#include "qpid/framing/FieldValue.h" #include @@ -472,13 +473,15 @@ INT ResourceManager::recover(XID *xids, long count, long flags) { try { // status if we can't talk to the broker status = XAER_RMFAIL; - std::vector wireFormatXids; DtxRecoverResult dtxrr = qpidSession.dtxRecover(true); // status if we can't process the xids status = XAER_RMERR; - dtxrr.getInDoubt().collect(wireFormatXids); + + std::vector wireFormatXids(dtxrr.getInDoubt().size()); + std::transform(dtxrr.getInDoubt().begin(), dtxrr.getInDoubt().end(), wireFormatXids.begin(), Array::get); + size_t nXids = wireFormatXids.size(); if (nXids > 0) { -- cgit v1.2.1