diff options
author | Kim van der Riet <kpvdr@apache.org> | 2013-02-28 16:14:30 +0000 |
---|---|---|
committer | Kim van der Riet <kpvdr@apache.org> | 2013-02-28 16:14:30 +0000 |
commit | 9c73ef7a5ac10acd6a50d5d52bd721fc2faa5919 (patch) | |
tree | 2a890e1df09e5b896a9b4168a7b22648f559a1f2 /java/systests | |
parent | 172d9b2a16cfb817bbe632d050acba7e31401cd2 (diff) | |
download | qpid-python-asyncstore.tar.gz |
Update from trunk r1375509 through r1450773asyncstore
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1451244 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/systests')
106 files changed, 9374 insertions, 3962 deletions
diff --git a/java/systests/build.xml b/java/systests/build.xml index 57337bdc55..dee73b2e1e 100644 --- a/java/systests/build.xml +++ b/java/systests/build.xml @@ -32,7 +32,9 @@ nn - or more contributor license agreements. See the NOTICE file </or> </condition> - <property name="module.depends" value="client management/common broker broker/test common amqp-1-0-common common/test jca ${systests.optional.depends}"/> + <!-- The jca module is unusual in that it produces a jar with the name ra rather than jca. Unfortunately this means we + need to add both jca (finds jca's jar dependencies) and ra (to find the qpid-ra jar file itself). --> + <property name="module.depends" value="client management/common broker broker/tests common amqp-1-0-common common/tests jca ra broker-plugins/access-control broker-plugins/management-http broker-plugins/management-jmx ${systests.optional.depends}"/> <property name="module.test.src" location="src/main/java"/> <property name="module.test.excludes" value="**/DropInTest.java,**/TestClientControlledTest.java"/> diff --git a/java/systests/etc/config-systests-bdb-settings.xml b/java/systests/etc/config-systests-bdb-settings.xml deleted file mode 100644 index 4fa69d0abc..0000000000 --- a/java/systests/etc/config-systests-bdb-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-bdb.xml</virtualhosts> -</broker> - - diff --git a/java/systests/etc/config-systests-bdb.xml b/java/systests/etc/config-systests-bdb.xml deleted file mode 100644 index 6b17b564a8..0000000000 --- a/java/systests/etc/config-systests-bdb.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - - KIND, either express or implied. See the License for the - - specific language governing permissions and limitations - - under the License. - - - --> -<configuration> - <system/> - <override> - <xml fileName="${QPID_HOME}/${test.config}" optional="true"/> - <xml fileName="${QPID_HOME}/etc/config-systests-bdb-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/> - </override> -</configuration> diff --git a/java/systests/etc/config-systests-derby-mem-settings.xml b/java/systests/etc/config-systests-derby-mem-settings.xml deleted file mode 100644 index 69369d9ac9..0000000000 --- a/java/systests/etc/config-systests-derby-mem-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml</virtualhosts> -</broker> - - diff --git a/java/systests/etc/config-systests-derby-mem.xml b/java/systests/etc/config-systests-derby-mem.xml deleted file mode 100644 index 8e40df986e..0000000000 --- a/java/systests/etc/config-systests-derby-mem.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - - KIND, either express or implied. See the License for the - - specific language governing permissions and limitations - - under the License. - - - --> -<configuration> - <system/> - <override> - <xml fileName="${QPID_HOME}/${test.config}" optional="true"/> - <xml fileName="${QPID_HOME}/etc/config-systests-derby-mem-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/> - </override> -</configuration> diff --git a/java/systests/etc/config-systests-derby-settings.xml b/java/systests/etc/config-systests-derby-settings.xml deleted file mode 100644 index 3ed3a9e33b..0000000000 --- a/java/systests/etc/config-systests-derby-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-derby.xml</virtualhosts> -</broker> - - diff --git a/java/systests/etc/config-systests-derby.xml b/java/systests/etc/config-systests-derby.xml deleted file mode 100644 index 21a7a8cabe..0000000000 --- a/java/systests/etc/config-systests-derby.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - - KIND, either express or implied. See the License for the - - specific language governing permissions and limitations - - under the License. - - - --> -<configuration> - <system/> - <override> - <xml fileName="${QPID_HOME}/${test.config}" optional="true"/> - <xml fileName="${QPID_HOME}/etc/config-systests-derby-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/> - </override> -</configuration> diff --git a/java/systests/etc/config-systests-firewall-2.xml b/java/systests/etc/config-systests-firewall-2.xml deleted file mode 100644 index 5167d88f12..0000000000 --- a/java/systests/etc/config-systests-firewall-2.xml +++ /dev/null @@ -1,83 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <prefix>${QPID_HOME}</prefix> - <work>${QPID_WORK}</work> - <conf>${prefix}/etc</conf> - <plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory> - <cache-directory>${QPID_WORK}/cache</cache-directory> - <connector> - <!-- To enable SSL edit the keystorePath and keystorePassword - and set enabled to true. - To disasble Non-SSL port set sslOnly to true --> - <ssl> - <enabled>false</enabled> - <port>8672</port> - <sslOnly>false</sslOnly> - <keyStorePath>/path/to/keystore.ks</keyStorePath> - <keyStorePassword>keystorepass</keyStorePassword> - </ssl> - <port>5672</port> - <socketReceiveBuffer>262144</socketReceiveBuffer> - <socketSendBuffer>262144</socketSendBuffer> - </connector> - <management> - <enabled>false</enabled> - </management> - <advanced> - <framesize>65535</framesize> - <locale>en_US</locale> - </advanced> - - <security> - <pd-auth-manager> - <principal-database> - <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class> - <attributes> - <attribute> - <name>passwordFile</name> - <value>${conf}/passwd</value> - </attribute> - </attributes> - </principal-database> - </pd-auth-manager> - - <msg-auth>false</msg-auth> - - <firewall default-action="deny"/> - </security> - - <virtualhosts>${conf}/virtualhosts-systests-firewall-2.xml</virtualhosts> - - <heartbeat> - <delay>0</delay> - <timeoutFactor>2.0</timeoutFactor> - </heartbeat> - <queue> - <auto_register>true</auto_register> - </queue> - - <status-updates>ON</status-updates> - -</broker> - - diff --git a/java/systests/etc/config-systests-firewall-3.xml b/java/systests/etc/config-systests-firewall-3.xml deleted file mode 100644 index 2bcbf53a39..0000000000 --- a/java/systests/etc/config-systests-firewall-3.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <prefix>${QPID_HOME}</prefix> - <work>${QPID_WORK}</work> - <conf>${prefix}/etc</conf> - <plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory> - <cache-directory>${QPID_WORK}/cache</cache-directory> - <connector> - <!-- To enable SSL edit the keystorePath and keystorePassword - and set enabled to true. - To disable Non-SSL port set sslOnly to true --> - <ssl> - <enabled>false</enabled> - <port>8672</port> - <sslOnly>false</sslOnly> - <keyStorePath>/path/to/keystore.ks</keyStorePath> - <keyStorePassword>keystorepass</keyStorePassword> - </ssl> - <port>5672</port> - <socketReceiveBuffer>262144</socketReceiveBuffer> - <socketSendBuffer>262144</socketSendBuffer> - </connector> - <management> - <enabled>false</enabled> - </management> - <advanced> - <framesize>65535</framesize> - <locale>en_US</locale> - </advanced> - - <security> - <pd-auth-manager> - <principal-database> - <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class> - <attributes> - <attribute> - <name>passwordFile</name> - <value>${conf}/passwd</value> - </attribute> - </attributes> - </principal-database> - </pd-auth-manager> - - <msg-auth>false</msg-auth> - - <firewall default-action="deny"> - <rule access="allow" network="127.0.0.1"/> - </firewall> - </security> - - <virtualhosts>${conf}/virtualhosts-systests-firewall-3.xml</virtualhosts> - - <heartbeat> - <delay>0</delay> - <timeoutFactor>2.0</timeoutFactor> - </heartbeat> - <queue> - <auto_register>true</auto_register> - </queue> - - <status-updates>ON</status-updates> - -</broker> - - diff --git a/java/systests/etc/config-systests-firewall-settings.xml b/java/systests/etc/config-systests-firewall-settings.xml deleted file mode 100644 index aa73be0646..0000000000 --- a/java/systests/etc/config-systests-firewall-settings.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <security> - <firewall> - <rule access="allow" network="127.0.0.1"/> - </firewall> - </security> - - <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-firewall.xml</virtualhosts> -</broker> diff --git a/java/systests/etc/config-systests-firewall.xml b/java/systests/etc/config-systests-firewall.xml deleted file mode 100644 index a884a39614..0000000000 --- a/java/systests/etc/config-systests-firewall.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - - KIND, either express or implied. See the License for the - - specific language governing permissions and limitations - - under the License. - - - --> -<configuration> - <system/> - <override> - <xml fileName="${QPID_HOME}/${test.config}" optional="true"/> - <xml fileName="${QPID_FIREWALL_CONFIG_SETTINGS}" optional="true"/> - <xml fileName="${QPID_HOME}/etc/config-systests-firewall-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/> - </override> -</configuration> diff --git a/java/systests/etc/config-systests-settings.xml b/java/systests/etc/config-systests-settings.xml deleted file mode 100644 index 0b65ad83c3..0000000000 --- a/java/systests/etc/config-systests-settings.xml +++ /dev/null @@ -1,103 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - Licensed to the Apache Software Foundation (ASF) under one - - or more contributor license agreements. See the NOTICE file - - distributed with this work for additional information - - regarding copyright ownership. The ASF licenses this file - - to you under the Apache License, Version 2.0 (the - - "License"); you may not use this file except in compliance - - with the License. You may obtain a copy of the License at - - - - http://www.apache.org/licenses/LICENSE-2.0 - - - - Unless required by applicable law or agreed to in writing, - - software distributed under the License is distributed on an - - "AS IS" BASIS, WITHOUT 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> - <prefix>${QPID_HOME}</prefix> - <work>${QPID_WORK}</work> - <conf>${prefix}/etc</conf> - - <plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory> - <cache-directory>${QPID_WORK}/cache</cache-directory> - - <connector> - <!-- To enable SSL edit the keystorePath and keystorePassword - and set enabled to true. - To disable Non-SSL port set sslOnly to true --> - <ssl> - <port>15671</port> - <enabled>false</enabled> - <sslOnly>false</sslOnly> - <keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath> - <keyStorePassword>password</keyStorePassword> - </ssl> - <port>5672</port> - <socketReceiveBuffer>262144</socketReceiveBuffer> - <socketSendBuffer>262144</socketSendBuffer> - </connector> - <management> - <enabled>false</enabled> - <jmxport> - <registryServer>8999</registryServer> - <!-- - If unspecified, connectorServer defaults to 100 + registryServer port. - <connectorServer>9099</connectionServer> - --> - </jmxport> - <ssl> - <enabled>false</enabled> - <keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath> - <keyStorePassword>password</keyStorePassword> - </ssl> - <http> - <enabled>false</enabled> - </http> - </management> - <advanced> - <framesize>65535</framesize> - <locale>en_US</locale> - </advanced> - - <security> - <pd-auth-manager> - <principal-database> - <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class> - <attributes> - <attribute> - <name>passwordFile</name> - <value>${conf}/passwd</value> - </attribute> - </attributes> - </principal-database> - </pd-auth-manager> - - <!-- By default, all authenticated users have permissions to perform all actions --> - - <!-- ACL Example - This example illustrates securing the both Management (JMX) and Messaging. - <acl>${conf}/broker_example.acl</acl> - --> - - <msg-auth>false</msg-auth> - </security> - - <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests.xml</virtualhosts> - - <heartbeat> - <delay>0</delay> - <timeoutFactor>2.0</timeoutFactor> - </heartbeat> - <queue> - <auto_register>true</auto_register> - </queue> - - <status-updates>ON</status-updates> - -</broker> diff --git a/java/systests/etc/config-systests.json b/java/systests/etc/config-systests.json new file mode 100644 index 0000000000..a5b85a2050 --- /dev/null +++ b/java/systests/etc/config-systests.json @@ -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. + * + */ +{ + "name": "QpidBroker", + "defaultAuthenticationProvider" : "plain", + "defaultVirtualHost" : "test", + "keyStorePath": "${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks", + "keyStorePassword": "password", + "trustStorePath": "${QPID_HOME}/../test-profiles/test_resources/ssl/java_client_truststore.jks", + "trustStorePassword": "password", + "authenticationproviders" : [ { + "name" : "plain", + "authenticationProviderType" : "PlainPasswordFileAuthenticationProvider", + "path" : "${QPID_HOME}/etc/passwd" + } ], + "ports" : [ { + "name" : "amqp", + "port" : "${test.port}" + }, { + "name" : "http", + "port" : "${test.hport}", + "protocols" : [ "HTTP" ] + }, { + "name" : "rmi", + "port" : "${test.mport}", + "protocols" : [ "RMI" ] + }, { + "name" : "jmx", + "port" : "${test.cport}", + "protocols" : [ "JMX_RMI" ] + }], + "virtualhosts" : [ { + "name" : "test", + "configPath" : "${broker.virtualhosts-config}" + } ] + /* +, + "plugins" : [ { + "pluginType" : "MANAGEMENT-HTTP", + "name" : "httpManagement" + }, { + "pluginType" : "MANAGEMENT-JMX", + "name" : "jmxManagement" + } ] + */ +}
\ No newline at end of file diff --git a/java/systests/etc/groups-systests b/java/systests/etc/groups-systests new file mode 100644 index 0000000000..e3912ece99 --- /dev/null +++ b/java/systests/etc/groups-systests @@ -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. +# + +# +# To define a group, use the format: +# +# <groupname>.users=<user1>,<user2>,...,<usern> +# + +messaging-users.users=guest,client,server +administrators.users=admin +webadmins.users=webadmin + diff --git a/java/systests/etc/virtualhosts-systests-bdb-settings.xml b/java/systests/etc/virtualhosts-systests-bdb-settings.xml index ce16523f13..350f05c178 100644 --- a/java/systests/etc/virtualhosts-systests-bdb-settings.xml +++ b/java/systests/etc/virtualhosts-systests-bdb-settings.xml @@ -20,37 +20,13 @@ - --> <virtualhosts> - <work>${QPID_WORK}</work> - - <virtualhost> - <name>localhost</name> - <localhost> - <store> - <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class> - <environment-path>${work}/bdbstore/localhost-store</environment-path> - </store> - </localhost> - </virtualhost> - - <virtualhost> - <name>development</name> - <development> - <store> - <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class> - <environment-path>${work}/bdbstore/development-store</environment-path> - </store> - </development> - </virtualhost> - <virtualhost> <name>test</name> <test> <store> <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class> - <environment-path>${work}/bdbstore/test-store</environment-path> + <environment-path>${QPID_WORK}/test-store</environment-path> </store> </test> </virtualhost> </virtualhosts> - - diff --git a/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml b/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml index 74189ad5e9..4e28f6d330 100644 --- a/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml +++ b/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml @@ -20,35 +20,12 @@ - --> <virtualhosts> - <directory>${QPID_HOME}/virtualhosts</directory> - <default>test</default> - - <virtualhost> - <localhost> - <store> - <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass> - <environment-path>:memory:</environment-path> - </store> - </localhost> - </virtualhost> - - <virtualhost> - <development> - <store> - <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass> - <environment-path>:memory:</environment-path> - </store> - </development> - </virtualhost> - <virtualhost> <test> <store> - <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass> + <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class> <environment-path>:memory:</environment-path> </store> </test> </virtualhost> </virtualhosts> - - diff --git a/java/systests/etc/virtualhosts-systests-derby-settings.xml b/java/systests/etc/virtualhosts-systests-derby-settings.xml index 08a40ca812..f9cc3d2336 100644 --- a/java/systests/etc/virtualhosts-systests-derby-settings.xml +++ b/java/systests/etc/virtualhosts-systests-derby-settings.xml @@ -20,35 +20,12 @@ - --> <virtualhosts> - <directory>${QPID_HOME}/virtualhosts</directory> - <default>test</default> - - <virtualhost> - <localhost> - <store> - <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class> - <environment-path>${QPID_WORK}/derbyDB/localhost-store</environment-path> - </store> - </localhost> - </virtualhost> - - <virtualhost> - <development> - <store> - <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class> - <environment-path>${QPID_WORK}/derbyDB/development-store</environment-path> - </store> - </development> - </virtualhost> - <virtualhost> <test> <store> <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class> - <environment-path>${QPID_WORK}/derbyDB/test-store</environment-path> + <environment-path>${QPID_WORK}/test-store</environment-path> </store> </test> </virtualhost> </virtualhosts> - - diff --git a/java/systests/etc/virtualhosts-systests-settings.xml b/java/systests/etc/virtualhosts-systests-settings.xml index 0ec16b31ef..5d4ec28b71 100644 --- a/java/systests/etc/virtualhosts-systests-settings.xml +++ b/java/systests/etc/virtualhosts-systests-settings.xml @@ -22,136 +22,11 @@ <virtualhosts> <default>test</default> <virtualhost> - <name>localhost</name> - <localhost> - <store> - <class>org.apache.qpid.server.store.MemoryMessageStore</class> - </store> - - <housekeeping> - <threadCount>2</threadCount> - <checkPeriod>20000</checkPeriod> - </housekeeping> - - <exchanges> - <exchange> - <type>direct</type> - <name>test.direct</name> - <durable>true</durable> - </exchange> - <exchange> - <type>topic</type> - <name>test.topic</name> - </exchange> - </exchanges> - <queues> - <exchange>amq.direct</exchange> - <maximumQueueDepth>4235264</maximumQueueDepth> - <!-- 4Mb --> - <maximumMessageSize>2117632</maximumMessageSize> - <!-- 2Mb --> - <maximumMessageAge>600000</maximumMessageAge> - <!-- 10 mins --> - <maximumMessageCount>50</maximumMessageCount> - <!-- 50 messages --> - - <queue> - <name>queue</name> - </queue> - <queue> - <name>ping</name> - </queue> - <queue> - <name>test-queue</name> - <test-queue> - <exchange>test.direct</exchange> - <durable>true</durable> - </test-queue> - </queue> - <queue> - <name>test-ping</name> - <test-ping> - <exchange>test.direct</exchange> - </test-ping> - </queue> - - </queues> - </localhost> - </virtualhost> - - - <virtualhost> - <name>development</name> - <development> - <store> - <class>org.apache.qpid.server.store.MemoryMessageStore</class> - </store> - - <queues> - <minimumAlertRepeatGap>30000</minimumAlertRepeatGap> - <maximumMessageCount>50</maximumMessageCount> - <queue> - <name>queue</name> - <queue> - <exchange>amq.direct</exchange> - <maximumQueueDepth>4235264</maximumQueueDepth> - <!-- 4Mb --> - <maximumMessageSize>2117632</maximumMessageSize> - <!-- 2Mb --> - <maximumMessageAge>600000</maximumMessageAge> - <!-- 10 mins --> - </queue> - </queue> - <queue> - <name>ping</name> - <ping> - <exchange>amq.direct</exchange> - <maximumQueueDepth>4235264</maximumQueueDepth> - <!-- 4Mb --> - <maximumMessageSize>2117632</maximumMessageSize> - <!-- 2Mb --> - <maximumMessageAge>600000</maximumMessageAge> - <!-- 10 mins --> - </ping> - </queue> - </queues> - </development> - </virtualhost> - <virtualhost> <name>test</name> <test> <store> <class>org.apache.qpid.server.store.MemoryMessageStore</class> </store> - - <queues> - <minimumAlertRepeatGap>30000</minimumAlertRepeatGap> - <maximumMessageCount>50</maximumMessageCount> - <queue> - <name>queue</name> - <queue> - <exchange>amq.direct</exchange> - <maximumQueueDepth>4235264</maximumQueueDepth> - <!-- 4Mb --> - <maximumMessageSize>2117632</maximumMessageSize> - <!-- 2Mb --> - <maximumMessageAge>600000</maximumMessageAge> - <!-- 10 mins --> - </queue> - </queue> - <queue> - <name>ping</name> - <ping> - <exchange>amq.direct</exchange> - <maximumQueueDepth>4235264</maximumQueueDepth> - <!-- 4Mb --> - <maximumMessageSize>2117632</maximumMessageSize> - <!-- 2Mb --> - <maximumMessageAge>600000</maximumMessageAge> - <!-- 10 mins --> - </ping> - </queue> - </queues> </test> </virtualhost> </virtualhosts> diff --git a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java index 6655202067..3025414e4a 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java @@ -27,7 +27,6 @@ import org.apache.qpid.framing.AMQShortString; 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.MessageProducer; @@ -72,10 +71,11 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase for (int i = start; i < end && !interrupted(); i++) { producer.send(session.createTextMessage(Integer.toString(i))); + ((AMQSession<?, ?>)session).sync(); } this._logger.info("Sent " + (end - start) + " messages"); } - catch (JMSException e) + catch (Exception e) { throw new RuntimeException(e); } @@ -101,7 +101,7 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase con.start(); } - public void testPausedOrder() throws Exception + public void testMessagesSentByTwoThreadsAreDeliveredInOrder() throws Exception { // Setup initial messages @@ -121,9 +121,9 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase for (int i = 0; i < numMessages; i++) { Message msg = consumer.receive(3000); - assertNotNull("Message should not be null", msg); - assertTrue("Message should be a text message", msg instanceof TextMessage); - assertEquals("Message content does not match expected", Integer.toString(i), ((TextMessage) msg).getText()); + assertNotNull("Message " + i + " should not be null", msg); + assertTrue("Message " + i + " should be a text message", msg instanceof TextMessage); + assertEquals("Message content " + i + "does not match expected", Integer.toString(i), ((TextMessage) msg).getText()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.java b/java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.java new file mode 100644 index 0000000000..0e01bda8d0 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.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.client; + +import javax.jms.Destination; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class HeartbeatTest extends QpidBrokerTestCase +{ + public void testHeartbeats() throws Exception + { + setTestSystemProperty("amqj.heartbeat.delay", "1"); + AMQConnection conn = (AMQConnection) getConnection(); + TestListener listener = new TestListener(); + conn.setHeartbeatListener(listener); + conn.start(); + + Thread.sleep(2500); + + assertTrue("Too few heartbeats received: "+listener._heartbeatsReceived+" (expected at least 2)", listener._heartbeatsReceived>=2); + assertTrue("Too few heartbeats sent "+listener._heartbeatsSent+" (expected at least 2)", listener._heartbeatsSent>=2); + + conn.close(); + } + + public void testNoHeartbeats() throws Exception + { + setTestSystemProperty("amqj.heartbeat.delay", "0"); + AMQConnection conn = (AMQConnection) getConnection(); + TestListener listener = new TestListener(); + conn.setHeartbeatListener(listener); + conn.start(); + + Thread.sleep(2500); + + assertEquals("Heartbeats unexpectedly received", 0, listener._heartbeatsReceived); + assertEquals("Heartbeats unexpectedly sent ", 0, listener._heartbeatsSent); + + conn.close(); + } + + public void testReadOnlyConnectionHeartbeats() throws Exception + { + setTestSystemProperty("amqj.heartbeat.delay","1"); + AMQConnection receiveConn = (AMQConnection) getConnection(); + AMQConnection sendConn = (AMQConnection) getConnection(); + Destination destination = getTestQueue(); + TestListener receiveListener = new TestListener(); + TestListener sendListener = new TestListener(); + + + Session receiveSession = receiveConn.createSession(false, Session.CLIENT_ACKNOWLEDGE); + Session senderSession = sendConn.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + MessageConsumer consumer = receiveSession.createConsumer(destination); + MessageProducer producer = senderSession.createProducer(destination); + + receiveConn.setHeartbeatListener(receiveListener); + sendConn.setHeartbeatListener(sendListener); + receiveConn.start(); + + for(int i = 0; i < 5; i++) + { + producer.send(senderSession.createTextMessage("Msg " + i)); + Thread.sleep(500); + assertNotNull("Expected to received message", consumer.receive(500)); + } + + + + assertTrue("Too few heartbeats sent "+receiveListener._heartbeatsSent+" (expected at least 2)", receiveListener._heartbeatsSent>=2); + assertEquals("Unexpected sent at the sender: ",0,sendListener._heartbeatsSent); + + assertTrue("Too few heartbeats received at the sender "+sendListener._heartbeatsReceived+" (expected at least 2)", sendListener._heartbeatsReceived>=2); + assertEquals("Unexpected received at the receiver: ",0,receiveListener._heartbeatsReceived); + + receiveConn.close(); + sendConn.close(); + } + + private class TestListener implements HeartbeatListener + { + int _heartbeatsReceived; + int _heartbeatsSent; + @Override + public void heartbeatReceived() + { + _heartbeatsReceived++; + } + + @Override + public void heartbeatSent() + { + _heartbeatsSent++; + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java index 4b766864b4..4f8a6ee54a 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java @@ -25,11 +25,12 @@ import org.apache.qpid.client.AMQSession; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.jms.FailoverPolicy; import org.apache.qpid.test.utils.FailoverBaseCase; +import org.apache.qpid.url.URLSyntaxException; import javax.jms.Connection; +import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.ExceptionListener; import javax.jms.JMSException; @@ -929,18 +930,22 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio return queue; } - private AMQConnection createConnectionWithFailover() throws NamingException, JMSException + private AMQConnection createConnectionWithFailover() throws NamingException, JMSException, URLSyntaxException { - AMQConnection connection; - AMQConnectionFactory connectionFactory = (AMQConnectionFactory)getConnectionFactory("default"); - ConnectionURL connectionURL = connectionFactory.getConnectionURL(); - connectionURL.setOption(ConnectionURL.OPTIONS_FAILOVER, "singlebroker"); - connectionURL.setOption(ConnectionURL.OPTIONS_FAILOVER_CYCLE, "2"); - BrokerDetails details = connectionURL.getBrokerDetails(0); - details.setProperty(BrokerDetails.OPTIONS_RETRY, "200"); - details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "1000"); + BrokerDetails origBrokerDetails = ((AMQConnectionFactory) getConnectionFactory("default")).getConnectionURL().getBrokerDetails(0); - connection = (AMQConnection)connectionFactory.createConnection("admin", "admin"); + String retries = "200"; + String connectdelay = "1000"; + String cycleCount = "2"; + + String newUrlFormat="amqp://username:password@clientid/test?brokerlist=" + + "'tcp://%s:%s?retries='%s'&connectdelay='%s''&failover='singlebroker?cyclecount='%s''"; + + String newUrl = String.format(newUrlFormat, origBrokerDetails.getHost(), origBrokerDetails.getPort(), + retries, connectdelay, cycleCount); + + ConnectionFactory connectionFactory = new AMQConnectionFactory(newUrl); + AMQConnection connection = (AMQConnection) connectionFactory.createConnection("admin", "admin"); connection.setConnectionListener(this); return connection; } @@ -1313,7 +1318,7 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio * @param acknowledgeMode session acknowledge mode * @throws JMSException */ - private void sessionCloseWhileFailoverImpl(int acknowledgeMode) throws JMSException + private void sessionCloseWhileFailoverImpl(int acknowledgeMode) throws Exception { initDelayedFailover(acknowledgeMode); @@ -1324,9 +1329,14 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio failBroker(getFailingPort()); + // wait until failover is started + _failoverStarted.await(5, TimeUnit.SECONDS); + // test whether session#close blocks while failover is in progress _consumerSession.close(); + assertTrue("Failover has not completed yet but session was closed", _failoverComplete.await(5, TimeUnit.SECONDS)); + assertFailoverException(); } @@ -1360,10 +1370,8 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio * @param acknowledgeMode session acknowledge mode * @throws JMSException */ - private void browserCloseWhileFailoverImpl(int acknowledgeMode) throws JMSException + private void browserCloseWhileFailoverImpl(int acknowledgeMode) throws Exception { - setDelayedFailoverPolicy(); - QueueBrowser browser = prepareQueueBrowser(acknowledgeMode); @SuppressWarnings("unchecked") @@ -1373,8 +1381,13 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio failBroker(getFailingPort()); + // wait until failover is started + _failoverStarted.await(5, TimeUnit.SECONDS); + browser.close(); + assertTrue("Failover has not completed yet but browser was closed", _failoverComplete.await(5, TimeUnit.SECONDS)); + assertFailoverException(); } @@ -1402,5 +1415,11 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio ((AMQConnection) _connection).setFailoverPolicy(failoverPolicy); return failoverPolicy; } - + + @Override + public void failBroker(int port) + { + killBroker(port); + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java new file mode 100644 index 0000000000..a0fd093bfe --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java @@ -0,0 +1,285 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.failover; + +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.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.log4j.Logger; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestUtils; +import org.apache.qpid.util.FileUtils; + +public class MultipleBrokersFailoverTest extends QpidBrokerTestCase implements ConnectionListener +{ + private static final Logger _logger = Logger.getLogger(MultipleBrokersFailoverTest.class); + + private static final String FAILOVER_VIRTUAL_HOST = "failover"; + private static final String NON_FAILOVER_VIRTUAL_HOST = "nonfailover"; + private static final String BROKER_PORTION_FORMAT = "tcp://localhost:%d?connectdelay='%d',retries='%d'"; + private static final int FAILOVER_RETRIES = 1; + private static final int FAILOVER_CONNECTDELAY = 1000; + private int[] _brokerPorts; + private AMQConnectionURL _connectionURL; + private Connection _connection; + private CountDownLatch _failoverComplete; + private CountDownLatch _failoverStarted; + private Session _consumerSession; + private Destination _destination; + private MessageConsumer _consumer; + private Session _producerSession; + private MessageProducer _producer; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + int numBrokers = 4; + int port = findFreePort(); + _brokerPorts = new int[numBrokers]; + + // we need to create 4 brokers: + // 1st broker will be running in test JVM and will not have failover host (only tcp connection will established, amqp connection will be closed) + // 2d broker will be spawn in separate JVM and should have a failover host (amqp connection should be established) + // 3d broker will be spawn in separate JVM and should not have a failover host (only tcp connection will established, amqp connection will be closed) + // 4d broker will be spawn in separate JVM and should have a failover host (amqp connection should be established) + + // the test should connect to the second broker first and fail over to the forth broker + // after unsuccessful try to establish the connection to the 3d broker + for (int i = 0; i < numBrokers; i++) + { + if (i > 0) + { + port = getNextAvailable(port + 1); + } + _brokerPorts[i] = port; + + createBrokerConfiguration(port); + String host = null; + if (i == 1 || i == _brokerPorts.length - 1) + { + host = FAILOVER_VIRTUAL_HOST; + } + else + { + host = NON_FAILOVER_VIRTUAL_HOST; + } + createTestVirtualHost(port, host); + + startBroker(port); + revertSystemProperties(); + } + + _connectionURL = new AMQConnectionURL(generateUrlString(numBrokers)); + + _connection = getConnection(_connectionURL); + ((AMQConnection) _connection).setConnectionListener(this); + _failoverComplete = new CountDownLatch(1); + _failoverStarted = new CountDownLatch(1); + } + + public void startBroker() throws Exception + { + // noop, prevent the broker startup in super.setUp() + } + + private String generateUrlString(int numBrokers) + { + String baseString = "amqp://guest:guest@test/" + FAILOVER_VIRTUAL_HOST + + "?&failover='roundrobin?cyclecount='1''&brokerlist='"; + StringBuffer buffer = new StringBuffer(baseString); + + for(int i = 0; i< numBrokers ; i++) + { + if(i != 0) + { + buffer.append(";"); + } + + String broker = String.format(BROKER_PORTION_FORMAT, _brokerPorts[i], + FAILOVER_CONNECTDELAY, FAILOVER_RETRIES); + buffer.append(broker); + } + buffer.append("'"); + + return buffer.toString(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + for (int i = 0; i < _brokerPorts.length; i++) + { + if (_brokerPorts[i] > 0) + { + stopBrokerSafely(_brokerPorts[i]); + FileUtils.deleteDirectory(System.getProperty("QPID_WORK") + "/" + getFailingPort()); + } + } + + } + } + + + public void testFailoverOnBrokerKill() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + assertConnectionPort(_brokerPorts[1]); + + assertSendReceive(0); + + killBroker(_brokerPorts[1]); + + awaitForFailoverCompletion(FAILOVER_CONNECTDELAY * _brokerPorts.length * 2); + assertEquals("Failover is not started as expected", 0, _failoverStarted.getCount()); + + assertSendReceive(2); + assertConnectionPort(_brokerPorts[_brokerPorts.length - 1]); + } + + public void testFailoverOnBrokerStop() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + assertConnectionPort(_brokerPorts[1]); + + assertSendReceive(0); + + stopBroker(_brokerPorts[1]); + + awaitForFailoverCompletion(FAILOVER_CONNECTDELAY * _brokerPorts.length * 2); + assertEquals("Failover is not started as expected", 0, _failoverStarted.getCount()); + + assertSendReceive(1); + assertConnectionPort(_brokerPorts[_brokerPorts.length - 1]); + } + + private void assertConnectionPort(int brokerPort) + { + int connectionPort = ((AMQConnection)_connection).getActiveBrokerDetails().getPort(); + assertEquals("Unexpected broker port", brokerPort, connectionPort); + } + + private void assertSendReceive(int index) throws JMSException + { + Message message = createNextMessage(_producerSession, index); + _producer.send(message); + if (_producerSession.getTransacted()) + { + _producerSession.commit(); + } + Message receivedMessage = _consumer.receive(1000l); + assertReceivedMessage(receivedMessage, index); + if (_consumerSession.getTransacted()) + { + _consumerSession.commit(); + } + } + + private void awaitForFailoverCompletion(long delay) + { + _logger.info("Awaiting Failover completion.."); + try + { + if (!_failoverComplete.await(delay, TimeUnit.MILLISECONDS)) + { + _logger.warn("Test thread stack:\n\n" + TestUtils.dumpThreads()); + fail("Failover did not complete"); + } + } + catch (InterruptedException e) + { + fail("Test was interrupted:" + e.getMessage()); + } + } + + private void assertReceivedMessage(Message receivedMessage, int messageIndex) + { + assertNotNull("Expected message [" + messageIndex + "] is not received!", receivedMessage); + assertTrue( + "Failure to receive message [" + messageIndex + "], expected TextMessage but received " + receivedMessage, + receivedMessage instanceof TextMessage); + } + + private void init(int acknowledgeMode, boolean startConnection) throws JMSException + { + boolean isTransacted = acknowledgeMode == Session.SESSION_TRANSACTED ? true : false; + + _consumerSession = _connection.createSession(isTransacted, acknowledgeMode); + _destination = _consumerSession.createQueue(getTestQueueName()); + _consumer = _consumerSession.createConsumer(_destination); + + if (startConnection) + { + _connection.start(); + } + + _producerSession = _connection.createSession(isTransacted, acknowledgeMode); + _producer = _producerSession.createProducer(_destination); + + } + + @Override + public void bytesSent(long count) + { + } + + @Override + public void bytesReceived(long count) + { + } + + @Override + public boolean preFailover(boolean redirect) + { + _failoverStarted.countDown(); + return true; + } + + @Override + public boolean preResubscribe() + { + return true; + } + + @Override + public void failoverComplete() + { + _failoverComplete.countDown(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java index 39689f5096..884e89fb65 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java @@ -20,54 +20,55 @@ */ package org.apache.qpid.client.ssl; -import org.apache.qpid.client.AMQConnection; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQTestConnection_0_10; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.transport.Connection; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import javax.jms.Connection; +import javax.jms.JMSException; import javax.jms.Session; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class SSLTest extends QpidBrokerTestCase { - private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; - private static final String KEYSTORE_PASSWORD = "password"; - private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "password"; private static final String CERT_ALIAS_APP1 = "app1"; private static final String CERT_ALIAS_APP2 = "app2"; @Override protected void setUp() throws Exception { - if(isJavaBroker()) - { - setTestClientSystemProperty("profile.use_ssl", "true"); - setConfigurationProperty("connector.ssl.enabled", "true"); - setConfigurationProperty("connector.ssl.sslOnly", "true"); - setConfigurationProperty("connector.ssl.wantClientAuth", "true"); - } - - // set the ssl system properties - setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); - setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); - setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); - setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); setSystemProperty("javax.net.debug", "ssl"); - super.setUp(); + + setSslStoreSystemProperties(); + + //We dont call super.setUp, the tests start the broker after deciding + //whether to run and then configuring it appropriately } public void testCreateSSLConnectionUsingConnectionURLParams() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { - // Clear the ssl system properties - setSystemProperty("javax.net.ssl.keyStore", null); - setSystemProperty("javax.net.ssl.keyStorePassword", null); - setSystemProperty("javax.net.ssl.trustStore", null); - setSystemProperty("javax.net.ssl.trustStorePassword", null); + clearSslStoreSystemProperties(); + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + "?ssl='true'&ssl_verify_hostname='true'" + "&key_store='%s'&key_store_password='%s'" + @@ -76,24 +77,75 @@ public class SSLTest extends QpidBrokerTestCase url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, KEYSTORE,KEYSTORE_PASSWORD,TRUSTSTORE,TRUSTSTORE_PASSWORD); - - AMQConnection con = new AMQConnection(url); + + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should be successful", con); Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); assertNotNull("create session should be successful", ssn); - } + } + } + + /** + * Create an SSL connection using the SSL system properties for the trust and key store, but using + * the {@link ConnectionURL} ssl='true' option to indicate use of SSL at a Connection level, + * without specifying anything at the {@link ConnectionURL#OPTIONS_BROKERLIST} level. + */ + public void testSslConnectionOption() throws Exception + { + if (shouldPerformTest()) + { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + + //Create URL enabling SSL at the connection rather than brokerlist level + String url = "amqp://guest:guest@test/?ssl='true'&brokerlist='tcp://localhost:%s'"; + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); + + Connection con = getConnection(new AMQConnectionURL(url)); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); + } + } + + /** + * Create an SSL connection using the SSL system properties for the trust and key store, but using + * the {@link ConnectionURL} ssl='true' option to indicate use of SSL at a Connection level, + * overriding the false setting at the {@link ConnectionURL#OPTIONS_BROKERLIST} level. + */ + public void testSslConnectionOptionOverridesBrokerlistOption() throws Exception + { + if (shouldPerformTest()) + { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + + //Create URL enabling SSL at the connection, overriding the false at the brokerlist level + String url = "amqp://guest:guest@test/?ssl='true'&brokerlist='tcp://localhost:%s?ssl='false''"; + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); + + Connection con = getConnection(new AMQConnectionURL(url)); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); + } } public void testCreateSSLConnectionUsingSystemProperties() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s?ssl='true''"; url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); - AMQConnection con = new AMQConnection(url); + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should be successful", con); Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); assertNotNull("create session should be successful", ssn); @@ -102,14 +154,18 @@ public class SSLTest extends QpidBrokerTestCase public void testMultipleCertsInSingleStore() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP1 + "''"; AMQTestConnection_0_10 con = new AMQTestConnection_0_10(url); - Connection transportCon = con.getConnection(); + org.apache.qpid.transport.Connection transportCon = con.getConnection(); String userID = transportCon.getSecurityLayer().getUserID(); assertEquals("The correct certificate was not choosen","app1@acme.org",userID); con.close(); @@ -126,65 +182,82 @@ public class SSLTest extends QpidBrokerTestCase } } - public void testVerifyHostNameWithIncorrectHostname() + public void testVerifyHostNameWithIncorrectHostname() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://127.0.0.1:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; try { - AMQConnection con = new AMQConnection(url); + getConnection(new AMQConnectionURL(url)); fail("Hostname verification failed. No exception was thrown"); } catch (Exception e) { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - e.printStackTrace(new PrintStream(bout)); - String strace = bout.toString(); - assertTrue("Correct exception not thrown",strace.contains("SSL hostname verification failed")); + verifyExceptionCausesContains(e, "SSL hostname verification failed"); } - } } + + private void verifyExceptionCausesContains(Exception e, String expectedString) + { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bout)); + String strace = bout.toString(); + assertTrue("Correct exception not thrown", strace.contains(expectedString)); + } public void testVerifyLocalHost() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; - AMQConnection con = new AMQConnection(url); - assertNotNull("connection should have been created", con); + Connection con = getConnection(new AMQConnectionURL(url)); + assertNotNull("connection should have been created", con); } } public void testVerifyLocalHostLocalDomain() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost.localdomain:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; - AMQConnection con = new AMQConnection(url); + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should have been created", con); } } public void testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { - // Clear the ssl system properties - setSystemProperty("javax.net.ssl.keyStore", null); - setSystemProperty("javax.net.ssl.keyStorePassword", null); - setSystemProperty("javax.net.ssl.trustStore", null); - setSystemProperty("javax.net.ssl.trustStorePassword", null); + clearSslStoreSystemProperties(); + + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + "?ssl='true'&ssl_verify_hostname='true'" + @@ -193,10 +266,122 @@ public class SSLTest extends QpidBrokerTestCase url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, TRUSTSTORE,TRUSTSTORE_PASSWORD); - AMQConnection con = new AMQConnection(url); + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should be successful", con); Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); assertNotNull("create session should be successful", ssn); } } + + /** + * Verifies that when the broker is configured to NEED client certificates, + * a client which doesn't supply one fails to connect. + */ + public void testClientCertMissingWhilstNeeding() throws Exception + { + missingClientCertWhileNeedingOrWantingTestImpl(true, false, false); + } + + /** + * Verifies that when the broker is configured to WANT client certificates, + * a client which doesn't supply one succeeds in connecting. + */ + public void testClientCertMissingWhilstWanting() throws Exception + { + missingClientCertWhileNeedingOrWantingTestImpl(false, true, true); + } + + /** + * Verifies that when the broker is configured to WANT and NEED client certificates + * that a client which doesn't supply one fails to connect. + */ + public void testClientCertMissingWhilstWantingAndNeeding() throws Exception + { + missingClientCertWhileNeedingOrWantingTestImpl(true, true, false); + } + + private void missingClientCertWhileNeedingOrWantingTestImpl(boolean needClientCerts, + boolean wantClientCerts, boolean shouldSucceed) throws Exception + { + if (shouldPerformTest()) + { + clearSslStoreSystemProperties(); + + //Start the broker + configureJavaBrokerIfNecessary(true, true, needClientCerts, wantClientCerts); + super.setUp(); + + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + + "?ssl='true'&trust_store='%s'&trust_store_password='%s''"; + + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT,TRUSTSTORE,TRUSTSTORE_PASSWORD); + try + { + Connection con = getConnection(new AMQConnectionURL(url)); + if(!shouldSucceed) + { + fail("Connection succeeded, expected exception was not thrown"); + } + else + { + //Use the connection to verify it works + con.createSession(true, Session.SESSION_TRANSACTED); + } + } + catch(JMSException e) + { + if(shouldSucceed) + { + _logger.error("Caught unexpected exception",e); + fail("Connection failed, unexpected exception thrown"); + } + else + { + //expected + verifyExceptionCausesContains(e, "Caused by: javax.net.ssl.SSLException:"); + } + } + } + } + + private boolean shouldPerformTest() + { + // We run the SSL tests on all the Java broker profiles + if(isJavaBroker()) + { + setTestClientSystemProperty(PROFILE_USE_SSL, "true"); + } + + return Boolean.getBoolean(PROFILE_USE_SSL); + } + + private void configureJavaBrokerIfNecessary(boolean sslEnabled, boolean sslOnly, boolean needClientAuth, boolean wantClientAuth) throws ConfigurationException + { + if(isJavaBroker()) + { + Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); + sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.NEED_CLIENT_AUTH, needClientAuth); + sslPortAttributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth); + sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + getBrokerConfiguration().addPortConfiguration(sslPortAttributes); + } + } + + private void setSslStoreSystemProperties() + { + setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); + setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + } + + private void clearSslStoreSystemProperties() + { + setSystemProperty("javax.net.ssl.keyStore", null); + setSystemProperty("javax.net.ssl.keyStorePassword", null); + setSystemProperty("javax.net.ssl.trustStore", null); + setSystemProperty("javax.net.ssl.trustStorePassword", null); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java b/java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java new file mode 100644 index 0000000000..80001099a8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java @@ -0,0 +1,120 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.admin; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.naming.NamingException; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.naming.Reference; +import javax.naming.Referenceable; +import javax.naming.spi.ObjectFactory; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; + +import junit.framework.TestCase; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class QpidConnectionFactoryProxyTest 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 testQueueConnectionFactory() throws Exception + { + QueueConnectionFactory cf = null; + QueueConnection c = null; + + try + { + cf = new QpidConnectionFactoryProxy(); + ((QpidConnectionFactoryProxy)cf).setConnectionURL(URL); + c = cf.createQueueConnection(); + assertTrue(c instanceof QueueConnection); + + } + finally + { + if(c != null) + { + c.close(); + } + } + } + + public void testTopicConnectionFactory() throws Exception + { + TopicConnectionFactory cf = null; + TopicConnection c = null; + + try + { + cf = new QpidConnectionFactoryProxy(); + ((QpidConnectionFactoryProxy)cf).setConnectionURL(URL); + c = cf.createTopicConnection(); + assertTrue(c instanceof TopicConnection); + + } + finally + { + if(c != null) + { + c.close(); + } + } + try + { + + } + finally + { + + } + } + + public void testConnectionFactory() throws Exception + { + ConnectionFactory cf = null; + Connection c = null; + + try + { + cf = new QpidConnectionFactoryProxy(); + ((QpidConnectionFactoryProxy)cf).setConnectionURL(URL); + c = cf.createConnection(); + assertTrue(c instanceof Connection); + + } + finally + { + if(c != null) + { + c.close(); + } + + } + } +} + diff --git a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java index 9f3994fc91..eba2a638c0 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java @@ -30,6 +30,7 @@ import org.apache.qpid.util.LogMonitor; import javax.jms.Connection; import javax.jms.Queue; import javax.jms.Session; +import java.io.File; import java.util.List; /** @@ -72,10 +73,7 @@ public class BrokerStartupTest extends AbstractTestLogging if (isJavaBroker() && isExternalBroker() && !isInternalBroker()) { //Remove test Log4j config from the commandline - _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l")); - - // Add an invalid value - _brokerCommand += " -l invalid"; + setBrokerCommandLog4JFile(new File("invalid file")); // The broker has a built in default log4j configuration set up // so if the the broker cannot load the -l value it will use default @@ -145,4 +143,4 @@ public class BrokerStartupTest extends AbstractTestLogging } } -}
\ No newline at end of file +} 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 e8d72c13bd..23a00431d1 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 @@ -23,13 +23,17 @@ package org.apache.qpid.server; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.adapter.PortFactoryTest; import org.apache.qpid.test.utils.QpidBrokerTestCase; /** * Tests to validate it is possible to disable support for particular protocol * versions entirely, rather than selectively excluding them on particular ports, * and it is possible to configure the reply to an unsupported protocol initiation. + *<p> + * Protocol exclusion/inclusion are unit tested as part of {@link PortFactoryTest} */ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase { @@ -41,8 +45,8 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase private void clearProtocolSupportManipulations() { //Remove the QBTC provided protocol manipulations, giving only the protocols which default to enabled - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_EXCLUDES, null); - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_INCLUDES, null); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, null); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, null); } /** @@ -87,8 +91,8 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase clearProtocolSupportManipulations(); //disable 0-10 and 1-0 support - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, + Protocol.AMQP_1_0 + "," + Protocol.AMQP_0_10); super.setUp(); @@ -100,52 +104,14 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase connection.close(); } - public void testDisabling091and010and10() throws Exception - { - clearProtocolSupportManipulations(); - - //disable 0-91 and 0-10 and 1-0 support - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false"); - - super.setUp(); - - //Verify initially requesting a 0-10 connection now negotiates a 0-9 - //connection as the broker should reply with its highest supported protocol - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_9, connection.getProtocolVersion()); - connection.close(); - } - - public void testDisabling09and091and010and10() throws Exception - { - clearProtocolSupportManipulations(); - - //disable 0-9, 0-91, 0-10 and 1-0 support - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP09ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); - - super.setUp(); - - //Verify initially requesting a 0-10 connection now negotiates a 0-8 - //connection as the broker should reply with its highest supported protocol - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v8_0, connection.getProtocolVersion()); - connection.close(); - } - public void testConfiguringReplyingToUnsupported010ProtocolInitiationWith09insteadOf091() throws Exception { clearProtocolSupportManipulations(); //disable 0-10 support, and set the default unsupported protocol initiation reply to 0-9 - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP_SUPPORTED_REPLY, "v0_9"); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, + Protocol.AMQP_1_0 + "," + Protocol.AMQP_0_10); + setSystemProperty(BrokerProperties.PROPERTY_DEFAULT_SUPPORTED_PROTOCOL_REPLY, "v0_9"); super.setUp(); @@ -164,71 +130,5 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase connection.close(); } - public void testProtocolInclusionThroughQBTCSystemPropertiesOverridesProtocolExclusion() throws Exception - { - testProtocolInclusionOverridesProtocolExclusion(false); - } - - public void testProtocolInclusionThroughConfigOverridesProtocolExclusion() throws Exception - { - testProtocolInclusionOverridesProtocolExclusion(true); - } - - private void testProtocolInclusionOverridesProtocolExclusion(boolean useConfig) throws Exception - { - clearProtocolSupportManipulations(); - - //selectively exclude 0-10 and 1-0 on the test port - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_EXCLUDES,"--exclude-0-10 @PORT --exclude-1-0 @PORT"); - - super.setUp(); - - //Verify initially requesting a 0-10 connection negotiates a 0-9-1 connection - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_91, connection.getProtocolVersion()); - connection.close(); - - stopBroker(); - - if(useConfig) - { - //selectively include 0-10 support again on the test port through config - setConfigurationProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, String.valueOf(getPort())); - } - else - { - //selectively include 0-10 support again on the test port through QBTC sys props - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_INCLUDES,"--include-0-10 @PORT"); - } - - startBroker(); - - //Verify requesting a 0-10 connection now returns one - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_10, connection.getProtocolVersion()); - connection.close(); - } - - public void testProtocolInclusionOverridesProtocolDisabling() throws Exception - { - clearProtocolSupportManipulations(); - - //disable 0-10 and 1-0 - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); - - //selectively include 0-10 support again on the test port - setConfigurationProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, String.valueOf(getPort())); - - super.setUp(); - - //Verify initially requesting a 0-10 connection still works - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_10, connection.getProtocolVersion()); - connection.close(); - } }
\ No newline at end of file diff --git a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java b/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java deleted file mode 100644 index 6f54a56e93..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java +++ /dev/null @@ -1,75 +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.configuration; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -/** - * This system test ensures that when loading our default system-test - * configuration file the configuration is correctly loaded. - * - * All configuration values should be set in the systest config file so that - * the ability to load them can be validated. - */ -public class ServerConfigurationFileTest extends QpidBrokerTestCase -{ - private ServerConfiguration _serverConfig; - - public void setUp() throws ConfigurationException - { - if (!_configFile.exists()) - { - fail("Unable to test without config file:" + _configFile); - } - - saveTestConfiguration(); - saveTestVirtualhosts(); - - _serverConfig = new ServerConfiguration(_configFile); - } - - /** - * This helper method ensures that when we attempt to read a value that is - * set in the configuration file we do actualy read a value and not - * simply get a defaulted value from the ServerConfiguration.get*() methods. - * - * @param property the propert to test - */ - private void validatePropertyDefinedInFile(String property) - { - //Verify that we are not just picking up the the default value from the getBoolean - assertNotNull("The value set in the configuration file is not being read for property:" + property, - _serverConfig.getConfig().getProperty(property)); - } - - public void testStatusUpdates() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.STATUS_UPDATES); - } - - public void testLocale() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.ADVANCED_LOCALE); - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java b/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java deleted file mode 100644 index 87a53a0765..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java +++ /dev/null @@ -1,237 +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.failure; - -import junit.framework.TestCase; -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.client.failover.FailoverException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.test.utils.QpidClientConnectionHelper; - -import javax.jms.DeliveryMode; -import javax.jms.JMSException; -import java.io.IOException; - - -/** Test Case provided by client Non-functional Test NF101: heap exhaustion behaviour */ -public class HeapExhaustion extends TestCase -{ - private static final Logger _logger = Logger.getLogger(HeapExhaustion.class); - - protected QpidClientConnectionHelper conn; - protected final String BROKER = "localhost"; - protected final String vhost = "/test"; - protected final String queue = "direct://amq.direct//queue"; - - protected String hundredK; - protected String megabyte; - - protected String generatePayloadOfSize(Integer numBytes) - { - return new String(new byte[numBytes]); - } - - protected void setUp() throws Exception - { - conn = new QpidClientConnectionHelper(BROKER); - conn.setVirtualHost(vhost); - - try - { - conn.connect(); - } catch (JMSException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - // clear queue - _logger.debug("setup: clearing test queue"); - conn.consume(queue, 2000); - - hundredK = generatePayloadOfSize(1024 * 100); - megabyte = generatePayloadOfSize(1024 * 1024); - } - - protected void tearDown() throws Exception - { - conn.disconnect(); - } - - - /** - * PUT at maximum rate (although we commit after each PUT) until failure - * - * @throws Exception on error - */ - public void testUntilFailureTransient() throws Exception - { - int copies = 0; - int total = 0; - String payload = hundredK; - int size = payload.getBytes().length; - while (true) - { - conn.put(queue, payload, 1, DeliveryMode.NON_PERSISTENT); - copies++; - total += size; - System.out.println("put copy " + copies + " OK for total bytes: " + total); - } - } - - /** - * PUT at lower rate (5 per second) until failure - * - * @throws Exception on error - */ - public void testUntilFailureWithDelaysTransient() throws Exception - { - int copies = 0; - int total = 0; - String payload = hundredK; - int size = payload.getBytes().length; - while (true) - { - conn.put(queue, payload, 1, DeliveryMode.NON_PERSISTENT); - copies++; - total += size; - System.out.println("put copy " + copies + " OK for total bytes: " + total); - Thread.sleep(200); - } - } - - public static void noDelay() - { - HeapExhaustion he = new HeapExhaustion(); - - try - { - he.setUp(); - } - catch (Exception e) - { - _logger.info("Unable to connect"); - System.exit(0); - } - - try - { - _logger.info("Running testUntilFailure"); - try - { - he.testUntilFailureTransient(); - } - catch (FailoverException fe) - { - _logger.error("Caught failover:" + fe); - } - _logger.info("Finishing Connection "); - - try - { - he.tearDown(); - } - catch (JMSException jmse) - { - if (((AMQException) jmse.getLinkedException()).getErrorCode() == AMQConstant.REQUEST_TIMEOUT) - { - _logger.info("Successful test of testUntilFailure"); - } - else - { - _logger.error("Test Failed due to:" + jmse); - } - } - } - catch (Exception e) - { - _logger.error("Test Failed due to:" + e); - } - } - - public static void withDelay() - { - HeapExhaustion he = new HeapExhaustion(); - - try - { - he.setUp(); - } - catch (Exception e) - { - _logger.info("Unable to connect"); - System.exit(0); - } - - try - { - _logger.info("Running testUntilFailure"); - try - { - he.testUntilFailureWithDelaysTransient(); - } - catch (FailoverException fe) - { - _logger.error("Caught failover:" + fe); - } - _logger.info("Finishing Connection "); - - try - { - he.tearDown(); - } - catch (JMSException jmse) - { - if (((AMQException) jmse.getLinkedException()).getErrorCode() == AMQConstant.REQUEST_TIMEOUT) - { - _logger.info("Successful test of testUntilFailure"); - } - else - { - _logger.error("Test Failed due to:" + jmse); - } - } - } - catch (Exception e) - { - _logger.error("Test Failed due to:" + e); - } - } - - public static void main(String args[]) - { - noDelay(); - - - try - { - System.out.println("Restart failed broker now to retest broker with delays in send."); - System.in.read(); - } - catch (IOException e) - { - _logger.info("Continuing"); - } - - withDelay(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java index b666b1f424..84017b6850 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java @@ -20,12 +20,7 @@ */ package org.apache.qpid.server.logging; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.util.LogMonitor; @@ -47,8 +42,6 @@ public class AbstractTestLogging extends QpidBrokerTestCase public static final String TEST_LOG_PREFIX = "MESSAGE"; protected LogMonitor _monitor; - private InternalBrokerBaseCase _configLoader; - @Override public void setUp() throws Exception { @@ -58,32 +51,6 @@ public class AbstractTestLogging extends QpidBrokerTestCase _monitor = new LogMonitor(_outputFile); } - protected ServerConfiguration getServerConfig() throws ConfigurationException - { - ServerConfiguration _serverConfiguration; - if (isExternalBroker()) - { - _serverConfiguration = new ServerConfiguration(_configFile) - { - @Override - public void initialise() throws ConfigurationException - { - //Overriding initialise to only setup the vhosts and not - //perform the ConfigurationPlugin setup, removing need for - //an ApplicationRegistry to be loaded. - setupVirtualHosts(getConfig()); - } - }; - _serverConfiguration.initialise(); - } - else - { - _serverConfiguration = ApplicationRegistry.getInstance().getConfiguration(); - } - - return _serverConfiguration; - } - protected void setLogMessagePrefix() { //set the message prefix to facilitate scraping from the munged test output. @@ -94,10 +61,6 @@ public class AbstractTestLogging extends QpidBrokerTestCase public void tearDown() throws Exception { _monitor.close(); - if (isExternalBroker() && _configLoader != null) - { - _configLoader.tearDown(); - } super.tearDown(); } @@ -159,7 +122,7 @@ public class AbstractTestLogging extends QpidBrokerTestCase } protected String fromMessage(String log) - { + {; int startSubject = log.indexOf("]") + 1; int start = log.indexOf("]", startSubject) + 1; diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java index 4b7b3f0cf0..37f960a65a 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java @@ -31,10 +31,10 @@ import java.util.List; /** * ACL version 2/3 file testing to verify that ACL actor logging works correctly. - * + * * This suite of tests validate that the AccessControl messages occur correctly * and according to the following format: - * + * * <pre> * ACL-1001 : Allowed Operation Object {PROPERTIES} * ACL-1002 : Denied Operation Object {PROPERTIES} @@ -83,12 +83,12 @@ public class AccessControlLoggingTest extends AbstractTestLogging Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("allow"), false, false, false); - + List<String> matches = findMatches(ACL_LOG_PREFIX); - + assertTrue("Should be no ACL log messages", matches.isEmpty()); } - + /** * Test that {@code allow-log} ACL entries log correctly. */ @@ -98,25 +98,25 @@ public class AccessControlLoggingTest extends AbstractTestLogging Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("allow-log"), false, false, false); - + List<String> matches = findMatches(ACL_LOG_PREFIX); - + assertEquals("Should only be one ACL log message", 1, matches.size()); - + String log = getLogMessage(matches, 0); String actor = fromActor(log); String subject = fromSubject(log); String message = getMessageString(fromMessage(log)); - + validateMessageID(ACL_LOG_PREFIX + 1001, log); - - assertTrue("Actor should contain the user identity", actor.contains(USER)); + + assertTrue("Actor " + actor + " should contain the user identity: " + USER, actor.contains(USER)); assertTrue("Subject should be empty", subject.length() == 0); assertTrue("Message should start with 'Allowed'", message.startsWith("Allowed")); assertTrue("Message should contain 'Create Queue'", message.contains("Create Queue")); assertTrue("Message should have contained the queue name", message.contains("allow-log")); } - + /** * Test that {@code deny-log} ACL entries log correctly. */ @@ -134,25 +134,25 @@ public class AccessControlLoggingTest extends AbstractTestLogging // Denied, so exception thrown assertEquals("Expected ACCESS_REFUSED error code", AMQConstant.ACCESS_REFUSED, amqe.getErrorCode()); } - + List<String> matches = findMatches(ACL_LOG_PREFIX); - + assertEquals("Should only be one ACL log message", 1, matches.size()); - + String log = getLogMessage(matches, 0); String actor = fromActor(log); String subject = fromSubject(log); String message = getMessageString(fromMessage(log)); - + validateMessageID(ACL_LOG_PREFIX + 1002, log); - - assertTrue("Actor should contain the user identity", actor.contains(USER)); + + assertTrue("Actor " + actor + " should contain the user identity: " + USER, actor.contains(USER)); assertTrue("Subject should be empty", subject.length() == 0); assertTrue("Message should start with 'Denied'", message.startsWith("Denied")); assertTrue("Message should contain 'Create Queue'", message.contains("Create Queue")); assertTrue("Message should have contained the queue name", message.contains("deny-log")); } - + /** * Test that {@code deny} ACL entries do not log anything. */ @@ -170,9 +170,9 @@ public class AccessControlLoggingTest extends AbstractTestLogging // Denied, so exception thrown assertEquals("Expected ACCESS_REFUSED error code", AMQConstant.ACCESS_REFUSED, amqe.getErrorCode()); } - + List<String> matches = findMatches(ACL_LOG_PREFIX); - + assertTrue("Should be no ACL log messages", matches.isEmpty()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java index 02c41e14c0..68ec101245 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java @@ -22,10 +22,6 @@ package org.apache.qpid.server.logging; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.util.FileUtils; import javax.jms.Connection; import javax.jms.Queue; @@ -44,29 +40,19 @@ public class AlertingTest extends AbstractTestLogging public void setUp() throws Exception { - // Update the configuration to make our virtualhost Persistent. - makeVirtualHostPersistent(VIRTUALHOST); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "5000"); - _numMessages = 50; + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", String.valueOf(ALERT_LOG_WAIT_PERIOD)); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", String.valueOf(_numMessages)); + // Then we do the normal setup stuff like starting the broker, getting a connection etc. super.setUp(); setupConnection(); } - @Override - public void tearDown() throws Exception - { - // Ensure queue is clean for next run. - drainQueue(_destination); - super.tearDown(); - } - - /** - * Create a new connection and ensure taht our destination queue is created + * Create a new connection and ensure that our destination queue is created * and bound. * * Note that the tests here that restart the broker rely on persistence. @@ -102,20 +88,6 @@ public class AlertingTest extends AbstractTestLogging if (!waitForMessage(MESSAGE_COUNT_ALERT, ALERT_LOG_WAIT_PERIOD)) { StringBuffer message = new StringBuffer("Could not find 'MESSAGE_COUNT_ALERT' in log file: " + _monitor.getMonitoredFile().getAbsolutePath()); - message.append("\n"); - - // Add the current contents of the log file to test output - message.append(_monitor.readFile()); - - // Write the test config file to test output - message.append("Server configuration overrides in use:\n"); - message.append(FileUtils.readFileAsString(getTestConfigFile())); - - message.append("\nVirtualhost maxMessageCount:\n"); - ServerConfiguration config = new ServerConfiguration(_configFile); - config.initialise(); - message.append(config.getVirtualHostConfig(VIRTUALHOST).getMaximumMessageCount()); - fail(message.toString()); } } @@ -148,9 +120,6 @@ public class AlertingTest extends AbstractTestLogging * Test sends two messages to the broker then restarts the broker with new * configuration. * - * If the test is running inVM the test validates that the new configuration - * has been applied. - * * Validates that we only have two messages on the queue and then sends * enough messages to trigger the alert. * @@ -172,31 +141,24 @@ public class AlertingTest extends AbstractTestLogging _monitor.markDiscardPoint(); // Change max message count to 5, start broker and make sure that that's triggered at the right time - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5"); startBroker(); - if (isInternalBroker()) - { - assertEquals("Alert Max Msg Count is not correct", 5, ApplicationRegistry.getInstance().getVirtualHostRegistry(). - getVirtualHost(VIRTUALHOST).getQueueRegistry().getQueue(new AMQShortString(_destination.getQueueName())). - getMaximumMessageCount()); - } - setupConnection(); // Validate the queue depth is as expected long messageCount = ((AMQSession<?, ?>) _session).getQueueDepth((AMQDestination) _destination); assertEquals("Broker has invalid message count for test", 2, messageCount); - // Ensure the alert has not occured yet + // Ensure the alert has not occurred yet assertLoggingNotYetOccured(MESSAGE_COUNT_ALERT); // Trigger the new value sendMessage(_session, _destination, 3); _session.commit(); - // Validate that the alert occured. + // Validate that the alert occurred. wasAlertFired(); } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java index dee593b12b..c5f5e06ae1 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java @@ -23,12 +23,20 @@ package org.apache.qpid.server.logging; import junit.framework.AssertionFailedError; import org.apache.qpid.server.BrokerOptions; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.transport.ConnectionException; import org.apache.qpid.util.LogMonitor; import java.io.IOException; import java.net.Socket; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Broker Test Suite @@ -47,6 +55,8 @@ import java.util.List; */ public class BrokerLoggingTest extends AbstractTestLogging { + private static final String BROKER_MESSAGE_LOG_REG_EXP = ".*\\[\\w*\\] (BRK\\-\\d*) .*"; + private static final Pattern BROKER_MESSAGE_LOG_PATTERN = Pattern.compile(BROKER_MESSAGE_LOG_REG_EXP); private static final String BRK_LOG_PREFIX = "BRK-"; public void setUp() throws Exception @@ -95,7 +105,7 @@ public class BrokerLoggingTest extends AbstractTestLogging _monitor = new LogMonitor(_outputFile); - String configFilePath = _configFile.toString(); + String configFilePath = getConfigPath(); // Ensure we wait for TESTID to be logged waitAndFindMatches(TESTID); @@ -118,8 +128,9 @@ public class BrokerLoggingTest extends AbstractTestLogging 1, results.size()); //3 - assertTrue("Config file details not correctly logged", - log.endsWith(configFilePath)); + assertTrue("Config file details not correctly logged, got " + + log + " but expected it to end with " + configFilePath, + log.endsWith(configFilePath)); } catch (AssertionFailedError afe) { @@ -130,6 +141,11 @@ public class BrokerLoggingTest extends AbstractTestLogging } } + private String getConfigPath() + { + return getPathRelativeToWorkingDirectory(getTestConfigFile(DEFAULT_PORT)); + } + /** * Description: * On startup the broker must report correctly report the log4j file in use. This is important as it can help diagnose why logging messages are not being reported. @@ -155,8 +171,7 @@ public class BrokerLoggingTest extends AbstractTestLogging { String TESTID = "BRK-1007"; - //Remove test Log4j config from the commandline - _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l")); + _brokerCommandHelper.removeBrokerCommandLog4JFile(); startBroker(); @@ -243,8 +258,7 @@ public class BrokerLoggingTest extends AbstractTestLogging // This logging startup code only occurs when you run a Java broker if (isJavaBroker() && isExternalBroker()) { - // Get custom -l value used during testing for the broker startup - String customLog4j = _brokerCommand.substring(_brokerCommand.indexOf("-l") + 2).trim(); + String customLog4j = getBrokerCommandLog4JFile().getAbsolutePath(); String TESTID = "BRK-1007"; @@ -293,8 +307,10 @@ public class BrokerLoggingTest extends AbstractTestLogging 1, findMatches(TESTID).size()); //3 - assertTrue("Log4j file details not correctly logged:" + getMessageString(log), - getMessageString(log).endsWith(customLog4j)); + String messageString = getMessageString(log); + assertTrue("Log4j file details not correctly logged. Message '" + + messageString + "' should contain '" +customLog4j + "'", + messageString.endsWith(customLog4j)); validation = true; } @@ -442,10 +458,13 @@ public class BrokerLoggingTest extends AbstractTestLogging { String log = getLog(rawLog); + // using custom method to get id as getMessageId() fails to correctly identify id + // because of using brackets for protocols + String id = getBrokerLogId(log); // Ensure we do not have a BRK-1002 message - if (!getMessageID(log).equals(TESTID)) + if (!id.equals(TESTID)) { - if (getMessageID(log).equals("BRK-1001")) + if (id.equals("BRK-1001")) { foundBRK1001 = true; } @@ -455,7 +474,7 @@ public class BrokerLoggingTest extends AbstractTestLogging assertTrue("BRK-1001 not logged before this message", foundBRK1001); //1 - validateMessageID(TESTID, log); + assertEquals("Incorrect message", TESTID, id); //2 //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) @@ -465,7 +484,7 @@ public class BrokerLoggingTest extends AbstractTestLogging //3 String message = getMessageString(log); assertTrue("Expected Listen log not correct" + message, - message.endsWith("Listening on TCP port " + getPort())); + message.endsWith("Listening on [TCP] port " + getPort())); validation = true; } @@ -481,6 +500,16 @@ public class BrokerLoggingTest extends AbstractTestLogging } } + private String getBrokerLogId(String log) + { + Matcher m = BROKER_MESSAGE_LOG_PATTERN.matcher(log); + if (m.matches()) + { + return m.group(1); + } + return getMessageID(log); + } + /** * Description: * On startup the broker may listen on a number of ports and protocols. Each of these must be reported as they are made available. @@ -498,8 +527,8 @@ public class BrokerLoggingTest extends AbstractTestLogging * 1. The BRK ID is correct * 2. This occurs after the BRK-1001 startup message * 3. With SSL enabled in the configuration two BRK-1002 will be printed (order is not specified) - * 1. One showing values TCP / 5672 - * 2. One showing values TCP/SSL / 5672 + * 1. One showing values [TCP] 5672 + * 2. One showing values [SSL] 5671 * * @throws Exception caused by broker startup */ @@ -512,12 +541,11 @@ public class BrokerLoggingTest extends AbstractTestLogging String TESTID = "BRK-1002"; // Enable SSL on the connection - setConfigurationProperty("connector.ssl.enabled", "true"); - setConfigurationProperty("connector.ssl.sslOnly", "false"); - setConfigurationProperty("connector.ssl.keyStorePath", getConfigurationStringProperty("management.ssl.keyStorePath")); - setConfigurationProperty("connector.ssl.keyStorePassword", getConfigurationStringProperty("management.ssl.keyStorePassword")); - - Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.ssl.port")); + Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); + sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + getBrokerConfiguration().addPortConfiguration(sslPortAttributes); startBroker(); @@ -545,10 +573,11 @@ public class BrokerLoggingTest extends AbstractTestLogging { String log = getLog(rawLog); + String id = getBrokerLogId(log); // Ensure we do not have a BRK-1002 message - if (!getMessageID(log).equals(TESTID)) + if (!id.equals(TESTID)) { - if (getMessageID(log).equals("BRK-1001")) + if (id.equals("BRK-1001")) { foundBRK1001 = true; } @@ -558,7 +587,7 @@ public class BrokerLoggingTest extends AbstractTestLogging assertTrue("BRK-1001 not logged before this message", foundBRK1001); //1 - validateMessageID(TESTID, log); + assertEquals("Incorrect message", TESTID, id); //2 //There will be 4 copies of the startup message (two via SystemOut, and two via Log4J) @@ -570,16 +599,16 @@ public class BrokerLoggingTest extends AbstractTestLogging //Check the first String message = getMessageString(getLog(listenMessages .get(0))); assertTrue("Expected Listen log not correct" + message, - message.endsWith("Listening on TCP port " + getPort())); + message.endsWith("Listening on [TCP] port " + getPort())); // Check the third, ssl listen. message = getMessageString(getLog(listenMessages .get(2))); assertTrue("Expected Listen log not correct" + message, - message.endsWith("Listening on TCP/SSL port " + sslPort)); + message.endsWith("Listening on [SSL] port " + DEFAULT_SSL_PORT)); //4 Test ports open testSocketOpen(getPort()); - testSocketOpen(sslPort); + testSocketOpen(DEFAULT_SSL_PORT); validation = true; } @@ -803,11 +832,11 @@ public class BrokerLoggingTest extends AbstractTestLogging String TESTID = "BRK-1003"; // Enable SSL on the connection - setConfigurationProperty("connector.ssl.enabled", "true"); - setConfigurationProperty("connector.ssl.keyStorePath", getConfigurationStringProperty("management.ssl.keyStorePath")); - setConfigurationProperty("connector.ssl.keyStorePassword", getConfigurationStringProperty("management.ssl.keyStorePassword")); - - Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.ssl.port")); + Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); + sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + getBrokerConfiguration().addPortConfiguration(sslPortAttributes); startBroker(); @@ -848,13 +877,13 @@ public class BrokerLoggingTest extends AbstractTestLogging // Check second, ssl, listen. message = getMessageString(getLog(listenMessages.get(1))); assertTrue("Expected shutdown log not correct" + message, - message.endsWith("TCP/SSL port " + sslPort)); + message.endsWith("TCP/SSL port " + DEFAULT_SSL_PORT)); //4 //Test Port closed checkSocketClosed(getPort()); //Test SSL Port closed - checkSocketClosed(sslPort); + checkSocketClosed(DEFAULT_SSL_PORT); } catch (AssertionFailedError afe) { @@ -999,4 +1028,5 @@ public class BrokerLoggingTest extends AbstractTestLogging + ". Due to:" + e.getMessage()); } } + } 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 236202f323..9f532ec5f7 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 @@ -66,8 +66,8 @@ public class SubscriptionLoggingTest extends AbstractTestLogging _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _queue = (Queue) getInitialContext().lookup(QUEUE); - _topic = (Topic) getInitialContext().lookup(TOPIC); + _queue = _session.createQueue(getTestQueueName() + "Queue"); + _topic = _session.createTopic(getTestQueueName() + "Topic"); } /** @@ -434,10 +434,6 @@ public class SubscriptionLoggingTest extends AbstractTestLogging throw afe; } _connection.close(); - - //Ensure the queue is drained before the test ends - drainQueue(_queue); - } /** diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java index 5f96215269..1ea105ae1a 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.logging; import junit.framework.AssertionFailedError; -import org.apache.qpid.server.configuration.ServerConfiguration; import java.util.Arrays; import java.util.List; @@ -68,7 +67,7 @@ public class VirtualHostLoggingTest extends AbstractTestLogging try { - List<String> vhosts = Arrays.asList(getServerConfig().getVirtualHosts()); + List<String> vhosts = Arrays.asList("test"); assertEquals("Each vhost did not create a store.", vhosts.size(), results.size()); @@ -110,23 +109,17 @@ public class VirtualHostLoggingTest extends AbstractTestLogging // Wait for the correct VHT message to arrive. waitForMessage(VHT_PREFIX + "1002"); - + // Validate each vhost logs a closure List<String> results = findMatches(VHT_PREFIX + "1002"); - + try { - // Load VirtualHost list from file. - ServerConfiguration configuration = new ServerConfiguration(_configFile); - configuration.initialise(); - List<String> vhosts = Arrays.asList(configuration.getVirtualHosts()); - - assertEquals("Each vhost did not close their store.", vhosts.size(), results.size()); + assertEquals("Each vhost did not close their store.", 1, results.size()); } catch (AssertionFailedError afe) { dumpLogs(results, _monitor); - throw afe; } } 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 bcad59a1fa..82b421a531 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 @@ -39,7 +39,7 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; */ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase { - protected final String MY_TOPIC_SUBSCRIPTION_NAME = this.getName(); + protected final String MY_TOPIC_SUBSCRIPTION_NAME = getTestQueueName(); protected static final int SEND_COUNT = 10; public void testNoLocalNotQueued() throws Exception diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java index 8536651ffb..cbf4e032db 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java @@ -30,6 +30,7 @@ import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.Session; + import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -54,7 +55,9 @@ public class MultipleTransactedBatchProducerTest extends QpidBrokerTestCase //debug level logging often makes this test pass artificially, turn the level down to info. setSystemProperty("amqj.server.logging.level", "INFO"); _receivedLatch = new CountDownLatch(MESSAGE_COUNT * NUM_PRODUCERS); - setConfigurationProperty("management.enabled", "true"); + + getBrokerConfiguration().addJmxManagementConfiguration(); + super.setUp(); _queueName = getTestQueueName(); _failMsg = null; diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java index 8ccf74a22b..814936f342 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -26,6 +26,7 @@ import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.url.URLSyntaxException; @@ -45,7 +46,7 @@ import java.util.concurrent.TimeUnit; /** * Abstract test case for ACLs. * - * This base class contains convenience methods to mange ACL files and implements a mechanism that allows each + * This base class contains convenience methods to manage ACL files and implements a mechanism that allows each * test method to run its own setup code before the broker starts. * * TODO move the pre broker-startup setup method invocation code to {@link QpidBrokerTestCase} @@ -58,25 +59,11 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements { /** Used to synchronise {@link #tearDown()} when exceptions are thrown */ protected CountDownLatch _exceptionReceived; - - /** Override this to return the name of the configuration XML file. */ - public String getConfig() - { - return "config-systests.xml"; - } - /** - * This setup method checks {@link #getConfig()} and {@link #getHostList()} to initialise the broker with specific - * ACL configurations and then runs an optional per-test setup method, which is simply a method with the same name - * as the test, but starting with {@code setUp} rather than {@code test}. - * - * @see org.apache.qpid.test.utils.QpidBrokerTestCase#setUp() - */ @Override public void setUp() throws Exception { - // Initialise ACLs. - _configFile = new File("build" + File.separator + "etc" + File.separator + getConfig()); + getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, System.getProperty(QPID_HOME) + "/etc/groups-systests"); // run test specific setup String testSetup = StringUtils.replace(getName(), "test", "setUp"); @@ -123,11 +110,11 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements if (vhost == null) { - testcase.setConfigurationProperty("security.acl", aclFile.getAbsolutePath()); + testcase.getBrokerConfiguration().setBrokerAttribute(Broker.ACL_FILE, aclFile.getAbsolutePath()); } else { - testcase.setConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.acl", aclFile.getAbsolutePath()); + testcase.setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.acl", aclFile.getAbsolutePath()); } PrintWriter out = new PrintWriter(new FileWriter(aclFile)); diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java index ceff2b998a..1830040007 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java @@ -33,14 +33,19 @@ import java.lang.management.RuntimeMXBean; */ public class ExternalACLJMXTest extends AbstractACLTestCase { + private JMXTestUtils _jmx; private static final String TEST_QUEUE_OWNER = "admin"; private static final String TEST_VHOST = "test"; + private static final String TEST2_VHOST = "test2"; @Override public void setUp() throws Exception { + createTestVirtualHost(0, TEST_VHOST); + createTestVirtualHost(0, TEST2_VHOST); + _jmx = new JMXTestUtils(this); _jmx.setUp(); super.setUp(); @@ -54,15 +59,14 @@ public class ExternalACLJMXTest extends AbstractACLTestCase super.tearDown(); } - /** - * Ensure an empty ACL defaults to DENY ALL. - */ - public void setUpDenyAllIsDefault() throws Exception + public void setUpDenyAllIsCatchAllRule() throws Exception { - writeACLFile(null, "#Empty ACL file"); + writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", + "#No more rules, default catch all (deny all) should apply"); } - public void testDenyAllIsDefault() throws Exception + public void testDenyAllIsCatchAllRule() throws Exception { //try a broker-level method ServerInformation info = _jmx.getServerInformation(); @@ -115,6 +119,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUpVhostAllowOverridesGlobalDeny() throws Exception { writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); writeACLFile(TEST_VHOST, "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); @@ -128,7 +133,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase //try a vhost-level method on a different vhost try { - _jmx.createQueue("development", getTestQueueName(), TEST_QUEUE_OWNER, true); + _jmx.createQueue(TEST2_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); fail("Exception not thrown"); } catch (SecurityException e) @@ -144,6 +149,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUpUpdateComponentOnlyAllow() throws Exception { writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager'"); } @@ -162,6 +168,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUpUpdateMethodOnlyAllow() throws Exception { writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", "ACL ALLOW admin UPDATE METHOD"); } @@ -179,8 +186,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase */ public void setUpCreateQueueSuccess() throws Exception { - writeACLFile(TEST_VHOST, - "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); + writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT"); + writeACLFile(TEST_VHOST, "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); } public void testCreateQueueSuccess() throws Exception @@ -194,6 +201,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase */ public void setUpCreateQueueSuccessNoAMQPRights() throws Exception { + writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT"); writeACLFile(TEST_VHOST, "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'", "ACL DENY admin CREATE QUEUE"); @@ -210,6 +218,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase */ public void setUpCreateQueueDenied() throws Exception { + writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT"); writeACLFile(TEST_VHOST, "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); } @@ -234,6 +243,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUpServerInformationUpdateDenied() throws Exception { writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", "ACL DENY admin UPDATE METHOD component='ServerInformation' name='resetStatistics'"); } @@ -258,6 +268,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUpServerInformationAccessGranted() throws Exception { writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", "ACL ALLOW-LOG admin ACCESS METHOD component='ServerInformation' name='getManagementApiMajorVersion'"); } @@ -284,6 +295,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUpServerInformationUpdateMethodPermission() throws Exception { writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", "ACL ALLOW admin UPDATE METHOD component='ServerInformation' name='resetStatistics'"); } @@ -300,7 +312,9 @@ public class ExternalACLJMXTest extends AbstractACLTestCase */ public void setUpServerInformationAllMethodPermissions() throws Exception { - writeACLFile(null, "ACL ALLOW admin ALL METHOD component='ServerInformation'"); + writeACLFile(null, + "ACL ALLOW admin ACCESS MANAGEMENT", + "ACL ALLOW admin ALL METHOD component='ServerInformation'"); } public void testServerInformationAllMethodPermissions() throws Exception diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java index 0e45ca9493..8324ac74a5 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java @@ -319,8 +319,12 @@ public class ExternalACLTest extends AbstractACLTestCase public void setUpRequestResponseSuccess() throws Exception { - writeACLFile("test", "GROUP messaging-users client server", - "ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST", + // The group "messaging-users", referenced in the ACL below, is currently defined + // in broker/etc/groups-systests. + // We tolerate a dependency from this test to that file because its + // contents are expected to change rarely. + + writeACLFile("test", "ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST", "# Server side", "ACL ALLOW-LOG server CREATE QUEUE name=\"example.RequestQueue\"" , "ACL ALLOW-LOG server BIND EXCHANGE", @@ -389,14 +393,44 @@ public class ExternalACLTest extends AbstractACLTestCase conn.start(); // create kipper - Topic kipper = sess.createTopic("kipper"); - TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); + String topicName = "kipper"; + Topic topic = sess.createTopic(topicName); + TopicSubscriber subscriber = sess.createDurableSubscriber(topic, topicName); subscriber.close(); - sess.unsubscribe("kipper"); + sess.unsubscribe(topicName); //Do something to show connection is active. sess.rollback(); conn.close(); } + + public void setUpFirewallAllow() throws Exception + { + writeACLFile("test", "ACL ALLOW client ACCESS VIRTUALHOST from_network=\"127.0.0.1\""); + } + + public void testFirewallAllow() throws Exception + { + getConnection("test", "client", "guest"); + // test pass because we successfully connected + } + + public void setUpFirewallDeny() throws Exception + { + writeACLFile("test", "ACL DENY client ACCESS VIRTUALHOST from_network=\"127.0.0.1\""); + } + + public void testFirewallDeny() throws Exception + { + try + { + getConnection("test", "client", "guest"); + fail("We expected the connection to fail"); + } + catch(JMSException e) + { + // pass + } + } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java new file mode 100644 index 0000000000..c7a43a292b --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.security.auth.manager; + +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.JMSException; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class ExternalAuthenticationTest extends QpidBrokerTestCase +{ + @Override + protected void setUp() throws Exception + { + // not calling super.setUp() to avoid broker start-up + } + + /** + * Tests that when EXTERNAL authentication is used on the SSL port, clients presenting certificates are able to connect. + * Also, checks that default authentication manager PrincipalDatabaseAuthenticationManager is used on non SSL port. + */ + public void testExternalAuthenticationManagerOnSSLPort() throws Exception + { + setCommonBrokerSSLProperties(true); + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_MANAGER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); + super.setUp(); + + setClientKeystoreProperties(); + setClientTrustoreProperties(); + + try + { + getExternalSSLConnection(false); + } + catch (JMSException e) + { + fail("Should be able to create a connection to the SSL port: " + e.getMessage()); + } + + try + { + getConnection(); + } + catch (JMSException e) + { + fail("Should be able to create a connection with credentials to the standard port: " + e.getMessage()); + } + + } + + /** + * Tests that when EXTERNAL authentication manager is set as the default, clients presenting certificates are able to connect. + * Also, checks a client with valid username and password but not using ssl is unable to connect to the non SSL port. + */ + public void testExternalAuthenticationManagerAsDefault() throws Exception + { + setCommonBrokerSSLProperties(true); + getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); + super.setUp(); + + setClientKeystoreProperties(); + setClientTrustoreProperties(); + + try + { + getConnection(); + fail("Connection should not succeed"); + } + catch (JMSException e) + { + // pass + } + + try + { + getExternalSSLConnection(false); + } + catch (JMSException e) + { + fail("Should be able to create a connection to the SSL port. " + e.getMessage()); + } + } + + /** + * Tests that when EXTERNAL authentication manager is set as the default, clients without certificates are unable to connect to the SSL port + * even with valid username and password. + */ + public void testExternalAuthenticationManagerWithoutClientKeyStore() throws Exception + { + setCommonBrokerSSLProperties(false); + getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); + super.setUp(); + + setClientTrustoreProperties(); + + try + { + getExternalSSLConnection(true); + fail("Connection should not succeed"); + } + catch (JMSException e) + { + // pass + } + } + + private Connection getExternalSSLConnection(boolean includeUserNameAndPassword) throws Exception + { + String url = "amqp://%s@test/?brokerlist='tcp://localhost:%s?ssl='true'&sasl_mechs='EXTERNAL''"; + if (includeUserNameAndPassword) + { + url = String.format(url, "guest:guest", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT)); + } + else + { + url = String.format(url, ":", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT)); + } + return getConnection(new AMQConnectionURL(url)); + } + + private void setCommonBrokerSSLProperties(boolean needClientAuth) throws ConfigurationException + { + TestBrokerConfiguration config = getBrokerConfiguration(); + Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); + sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.NEED_CLIENT_AUTH, String.valueOf(needClientAuth)); + sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + config.addPortConfiguration(sslPortAttributes); + + Map<String, Object> externalAuthProviderAttributes = new HashMap<String, Object>(); + externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE); + externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); + config.addAuthenticationProviderConfiguration(externalAuthProviderAttributes); + } + + private void setClientKeystoreProperties() + { + setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); + setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); + } + + private void setClientTrustoreProperties() + { + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + setSystemProperty("javax.net.debug", "ssl"); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java index 858b32c24c..f41f1159ab 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java @@ -20,28 +20,44 @@ */ package org.apache.qpid.server.security.auth.manager; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + import javax.jms.Connection; import javax.jms.JMSException; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; public class MultipleAuthenticationManagersTest extends QpidBrokerTestCase { - private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; - private static final String KEYSTORE_PASSWORD = "password"; - private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "password"; - @Override protected void setUp() throws Exception { - setConfigurationProperty("connector.ssl.enabled", "true"); - setConfigurationProperty("connector.ssl.sslOnly", "false"); - setConfigurationProperty("security.anonymous-auth-manager", ""); - setConfigurationProperty("security.default-auth-manager", "PrincipalDatabaseAuthenticationManager"); - setConfigurationProperty("security.port-mappings.port-mapping.port", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT)); - setConfigurationProperty("security.port-mappings.port-mapping.auth-manager", "AnonymousAuthenticationManager"); + TestBrokerConfiguration config = getBrokerConfiguration(); + + Map<String, Object> externalAuthProviderAttributes = new HashMap<String, Object>(); + externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE); + externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER); + config.addAuthenticationProviderConfiguration(externalAuthProviderAttributes); + + Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); + sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + sslPortAttributes.put(Port.AUTHENTICATION_MANAGER, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER); + config.addPortConfiguration(sslPortAttributes); // set the ssl system properties setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java deleted file mode 100644 index f5adf815aa..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java +++ /dev/null @@ -1,283 +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.security.firewall; - -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.JMSException; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; - -public class FirewallConfigTest extends QpidBrokerTestCase -{ - private File _tmpConfig, _tmpVirtualhosts; - private String _ipAddressOfBrokerHost; - - @Override - protected void setUp() throws Exception - { - // Setup initial config file. - _configFile = new File("build/etc/config-systests-firewall.xml"); - - // Setup temporary config file - _tmpConfig = File.createTempFile("config-systests-firewall", ".xml"); - setSystemProperty("QPID_FIREWALL_CONFIG_SETTINGS", _tmpConfig.getAbsolutePath()); - _tmpConfig.deleteOnExit(); - - // Setup temporary virtualhosts file - _tmpVirtualhosts = File.createTempFile("virtualhosts-systests-firewall", ".xml"); - setSystemProperty("QPID_FIREWALL_VIRTUALHOSTS_SETTINGS", _tmpVirtualhosts.getAbsolutePath()); - _tmpVirtualhosts.deleteOnExit(); - - _ipAddressOfBrokerHost = getIpAddressOfBrokerHost(); - } - - private void writeFirewallFile(boolean allow, boolean inVhost) throws IOException - { - FileWriter out = new FileWriter(inVhost ? _tmpVirtualhosts : _tmpConfig); - if (inVhost) - { - out.write("<virtualhosts><virtualhost><test>"); - } - else - { - out.write("<broker>"); - } - out.write("<security><firewall>"); - out.write("<rule access=\""+((allow) ? "allow" : "deny")+"\" network=\"" + _ipAddressOfBrokerHost + "\"/>"); - out.write("</firewall></security>"); - if (inVhost) - { - out.write("</test></virtualhost></virtualhosts>"); - } - else - { - out.write("</broker>"); - } - out.close(); - } - - public void testVhostAllowBrokerDeny() throws Exception - { - - _configFile = new File("build/etc/config-systests-firewall-2.xml"); - - super.setUp(); - try - { - //Try to get a connection to the 'test2' vhost - //This is expected to succeed as it is allowed at the vhost level - getConnection(new AMQConnectionURL("amqp://guest:guest@clientid/test2?brokerlist='" + getBroker() + "'")); - } - catch (JMSException e) - { - e.getLinkedException().printStackTrace(); - fail("The connection was expected to succeed: " + e.getMessage()); - } - - try - { - //Try to get a connection to the 'test' vhost - //This is expected to fail as it is denied at the broker level - getConnection(); - fail("We expected the connection to fail"); - } - catch (JMSException e) - { - //ignore - } - } - - public void testVhostDenyBrokerAllow() throws Exception - { - _configFile = new File("build/etc/config-systests-firewall-3.xml"); - - super.setUp(); - try - { - //Try to get a connection to the 'test2' vhost - //This is expected to fail as it is denied at the vhost level - getConnection(new AMQConnectionURL("amqp://guest:guest@clientid/test2?brokerlist='" + getBroker() + "'")); - fail("The connection was expected to fail"); - } - catch (JMSException e) - { - //ignore - } - - try - { - //Try to get a connection to the 'test' vhost - //This is expected to succeed as it is allowed at the broker level - getConnection(); - } - catch (JMSException e) - { - e.getLinkedException().printStackTrace(); - fail("The connection was expected to succeed: " + e.getMessage()); - } - } - - public void testDenyOnRestart() throws Exception - { - testDeny(false, new Runnable() { - - public void run() - { - try - { - restartBroker(); - } catch (Exception e) - { - fail(e.getMessage()); - } - } - }); - } - - public void testDenyOnRestartInVhost() throws Exception - { - testDeny(true, new Runnable() { - - public void run() - { - try - { - restartBroker(); - } catch (Exception e) - { - fail(e.getMessage()); - } - } - }); - } - - public void testAllowOnReloadInVhost() throws Exception - { - testFirewall(false, true, new Runnable() { - - public void run() - { - try - { - reloadBrokerSecurityConfig(); - } catch (Exception e) - { - fail(e.getMessage()); - } - } - }); - } - - public void testDenyOnReload() throws Exception - { - testDeny(false, new Runnable() { - - public void run() - { - try - { - reloadBrokerSecurityConfig(); - } catch (Exception e) - { - fail(e.getMessage()); - } - } - } - ); - } - - public void testDenyOnReloadInVhost() throws Exception - { - testDeny(true, new Runnable() { - - public void run() - { - try - { - reloadBrokerSecurityConfig(); - } catch (Exception e) - { - fail(e.getMessage()); - } - } - } - ); - - } - - private void testDeny(boolean inVhost, Runnable restartOrReload) throws Exception - { - testFirewall(true, inVhost, restartOrReload); - } - - /* - * Check we can get a connection - */ - private boolean checkConnection() throws Exception - { - Exception exception = null; - Connection conn = null; - try - { - conn = getConnection(); - } - catch (JMSException e) - { - exception = e; - } - - return conn != null; - } - - private void testFirewall(boolean initial, boolean inVhost, Runnable restartOrReload) throws Exception - { - - writeFirewallFile(initial, inVhost); - setConfigurationProperty("management.enabled", String.valueOf(true)); - super.setUp(); - - assertEquals("Initial connection check failed", initial, checkConnection()); - - // Reload changed firewall file after restart or reload - writeFirewallFile(!initial, inVhost); - restartOrReload.run(); - - assertEquals("Second connection check failed", !initial, checkConnection()); - } - - private String getIpAddressOfBrokerHost() - { - String brokerHost = getBroker().getHost(); - try - { - return InetAddress.getByName(brokerHost).getHostAddress(); - } - catch (UnknownHostException e) - { - throw new RuntimeException("Could not determine IP address of host : " + brokerHost, e); - } - - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java index c38fcd9199..6d53896371 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java @@ -27,10 +27,13 @@ import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.util.LogMonitor; import java.util.List; +import java.util.Map; import javax.jms.Connection; import javax.jms.Destination; @@ -45,46 +48,55 @@ import javax.jms.TextMessage; */ public class StatisticsReportingTest extends QpidBrokerTestCase { + private static final String VHOST_NAME1 = "vhost1"; + private static final String VHOST_NAME2 = "vhost2"; + private static final String VHOST_NAME3 = "vhost3"; + private static long STATISTICS_REPORTING_PERIOD_IN_SECONDS = 10l; + protected LogMonitor _monitor; protected static final String USER = "admin"; - protected Connection _test, _dev, _local; + protected Connection _conToVhost1, _conToVhost2, _conToVhost3; protected String _queueName = "statistics"; protected Destination _queue; protected String _brokerUrl; + private long _startTestTime; @Override public void setUp() throws Exception { - setConfigurationProperty("statistics.generation.broker", "true"); - setConfigurationProperty("statistics.generation.virtualhosts", "true"); + createTestVirtualHost(0, VHOST_NAME1); + createTestVirtualHost(0, VHOST_NAME2); + createTestVirtualHost(0, VHOST_NAME3); if (getName().equals("testEnabledStatisticsReporting")) { - setConfigurationProperty("statistics.reporting.period", "10"); + TestBrokerConfiguration config = getBrokerConfiguration(); + config.removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + config.setBrokerAttribute(Broker.STATISTICS_REPORTING_PERIOD, STATISTICS_REPORTING_PERIOD_IN_SECONDS); } _monitor = new LogMonitor(_outputFile); + _startTestTime = System.currentTimeMillis(); super.setUp(); _brokerUrl = getBroker().toString(); - _test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test"); - _dev = new AMQConnection(_brokerUrl, USER, USER, "clientid", "development"); - _local = new AMQConnection(_brokerUrl, USER, USER, "clientid", "localhost"); - - _test.start(); - _dev.start(); - _local.start(); + _conToVhost1 = new AMQConnection(_brokerUrl, USER, USER, "clientid", VHOST_NAME1); + _conToVhost2 = new AMQConnection(_brokerUrl, USER, USER, "clientid", VHOST_NAME2); + _conToVhost3 = new AMQConnection(_brokerUrl, USER, USER, "clientid", VHOST_NAME3); + _conToVhost1.start(); + _conToVhost2.start(); + _conToVhost3.start(); } @Override public void tearDown() throws Exception { - _test.close(); - _dev.close(); - _local.close(); + _conToVhost1.close(); + _conToVhost2.close(); + _conToVhost3.close(); super.tearDown(); } @@ -94,21 +106,30 @@ public class StatisticsReportingTest extends QpidBrokerTestCase */ public void testEnabledStatisticsReporting() throws Exception { - sendUsing(_test, 10, 100); - sendUsing(_dev, 20, 100); - sendUsing(_local, 15, 100); - - Thread.sleep(10 * 1000); // 15s - - List<String> brokerStatsData = _monitor.findMatches("BRK-1008"); - List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009"); - List<String> vhostStatsData = _monitor.findMatches("VHT-1003"); - List<String> vhostStatsMessages = _monitor.findMatches("VHT-1004"); - - assertEquals("Incorrect number of broker data stats log messages", 2, brokerStatsData.size()); - assertEquals("Incorrect number of broker message stats log messages", 2, brokerStatsMessages.size()); - assertEquals("Incorrect number of virtualhost data stats log messages", 6, vhostStatsData.size()); - assertEquals("Incorrect number of virtualhost message stats log messages", 6, vhostStatsMessages.size()); + sendUsing(_conToVhost1, 10, 100); + sendUsing(_conToVhost2, 20, 100); + sendUsing(_conToVhost3, 15, 100); + + Thread.sleep(STATISTICS_REPORTING_PERIOD_IN_SECONDS * 1000); + + Map<String, List<String>> brokerStatsData = _monitor.findMatches("BRK-1008", "BRK-1009", "VHT-1003", "VHT-1004"); + long endTestTime = System.currentTimeMillis(); + + int maxNumberOfReports = (int)((endTestTime - _startTestTime)/STATISTICS_REPORTING_PERIOD_IN_SECONDS); + + int brk1008LinesNumber = brokerStatsData.get("BRK-1008").size(); + int brk1009LinesNumber = brokerStatsData.get("BRK-1009").size(); + int vht1003LinesNumber = brokerStatsData.get("VHT-1003").size(); + int vht1004LinesNumber = brokerStatsData.get("VHT-1004").size(); + + assertTrue("Incorrect number of broker data stats log messages:" + brk1008LinesNumber, 2 <= brk1008LinesNumber + && brk1008LinesNumber <= maxNumberOfReports * 2); + assertTrue("Incorrect number of broker message stats log messages:" + brk1009LinesNumber, 2 <= brk1009LinesNumber + && brk1009LinesNumber <= maxNumberOfReports * 2); + assertTrue("Incorrect number of virtualhost data stats log messages:" + vht1003LinesNumber, 6 <= vht1003LinesNumber + && vht1003LinesNumber <= maxNumberOfReports * 6); + assertTrue("Incorrect number of virtualhost message stats log messages: " + vht1004LinesNumber, 6 <= vht1004LinesNumber + && vht1004LinesNumber <= maxNumberOfReports * 6); } /** @@ -116,9 +137,9 @@ public class StatisticsReportingTest extends QpidBrokerTestCase */ public void testNotEnabledStatisticsReporting() throws Exception { - sendUsing(_test, 10, 100); - sendUsing(_dev, 20, 100); - sendUsing(_local, 15, 100); + sendUsing(_conToVhost1, 10, 100); + sendUsing(_conToVhost2, 20, 100); + sendUsing(_conToVhost3, 15, 100); Thread.sleep(10 * 1000); // 15s @@ -135,7 +156,7 @@ public class StatisticsReportingTest extends QpidBrokerTestCase private void sendUsing(Connection con, int number, int size) throws Exception { - Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session session = con.createSession(true, Session.SESSION_TRANSACTED); createQueue(session); MessageProducer producer = session.createProducer(_queue); String content = new String(new byte[size]); @@ -144,6 +165,8 @@ public class StatisticsReportingTest extends QpidBrokerTestCase { producer.send(msg); } + session.commit(); + session.close(); } private void createQueue(Session session) throws AMQException, JMSException 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 9db04b64b3..6d38004451 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 @@ -27,8 +27,6 @@ import org.apache.qpid.AMQStoreException; 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.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; @@ -322,35 +320,6 @@ public class SlowMessageStore implements MessageStore doPostDelay("updateQueue"); } - - public void createBrokerLink(final BrokerLink link) throws AMQStoreException - { - doPreDelay("createBrokerLink"); - _durableConfigurationStore.createBrokerLink(link); - doPostDelay("createBrokerLink"); - } - - public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException - { - doPreDelay("deleteBrokerLink"); - _durableConfigurationStore.deleteBrokerLink(link); - doPostDelay("deleteBrokerLink"); - } - - public void createBridge(final Bridge bridge) throws AMQStoreException - { - doPreDelay("createBridge"); - _durableConfigurationStore.createBridge(bridge); - doPostDelay("createBridge"); - } - - public void deleteBridge(final Bridge bridge) throws AMQStoreException - { - doPreDelay("deleteBridge"); - _durableConfigurationStore.deleteBridge(bridge); - doPostDelay("deleteBridge"); - } - @Override public void activate() throws Exception { diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java index 9fb1db3a4f..61ca6d9c28 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java @@ -60,9 +60,9 @@ public class StoreOverfullTest extends QpidBrokerTestCase public void setUp() throws Exception { - setConfigurationProperty("virtualhosts.virtualhost.test.store.class", QuotaMessageStore.class.getName()); - setConfigurationProperty("virtualhosts.virtualhost.test.store.overfull-size", String.valueOf(OVERFULL_SIZE)); - setConfigurationProperty("virtualhosts.virtualhost.test.store.underfull-size", String.valueOf(UNDERFULL_SIZE)); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.class", QuotaMessageStore.class.getName()); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.overfull-size", String.valueOf(OVERFULL_SIZE)); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.underfull-size", String.valueOf(UNDERFULL_SIZE)); super.setUp(); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java b/java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java deleted file mode 100644 index 9ff143daf3..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java +++ /dev/null @@ -1,223 +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.systest; - -import org.apache.commons.configuration.ConfigurationException; - -import javax.jms.Session; -import javax.naming.NamingException; -import java.io.IOException; - -/** - * QPID-1447 : Add slow consumer detection and disconnection. - * - * Slow consumers should on a topic should expect to receive a - * 506 : Resource Error if the hit a predefined threshold. - */ -public class GlobalQueuesTest extends TestingBaseCase -{ - - protected String CONFIG_SECTION = ".queues"; - - /** - * Queue Configuration - - <slow-consumer-detection> - <!-- The depth before which the policy will be applied--> - <depth>4235264</depth> - - <!-- The message age before which the policy will be applied--> - <messageAge>600000</messageAge> - - <!-- The number of message before which the policy will be applied--> - <messageCount>50</messageCount> - - <!-- Policies configuration --> - <policy> - <name>TopicDelete</name> - <topicDelete> - <delete-persistent/> - </topicDelete> - </policy> - </slow-consumer-detection> - - */ - - - /** - * VirtualHost Plugin Configuration - - <slow-consumer-detection> - <delay>1</delay> - <timeunit>MINUTES</timeunit> - </slow-consumer-detection> - - */ - - public void setConfig(String property, String value, boolean deleteDurable) throws NamingException, IOException, ConfigurationException - { - setProperty(CONFIG_SECTION + ".slow-consumer-detection." + - "policy.name", "TopicDelete"); - - setProperty(CONFIG_SECTION + ".slow-consumer-detection." + - property, value); - - if (deleteDurable) - { - setProperty(CONFIG_SECTION + ".slow-consumer-detection." + - "policy.topicdelete.delete-persistent", ""); - } - } - - /** - * Test that setting messageCount takes affect on topics - * - * We send 10 messages and disconnect at 9 - * - * @throws Exception - */ - public void testTopicConsumerMessageCount() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("messageCount", String.valueOf(MAX_QUEUE_MESSAGE_COUNT - 1), false); - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, false); - } - - /** - * Test that setting depth has an effect on topics - * - * Sets the message size for the test - * Sets the depth to be 9 * the depth - * Ensure that sending 10 messages causes the disconnection - * - * @throws Exception - */ - public void testTopicConsumerMessageSize() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("depth", String.valueOf(MESSAGE_SIZE * 9), false); - - //Start the broker - startBroker(); - - setMessageSize(MESSAGE_SIZE); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, false); - } - - /** - * Test that setting messageAge has an effect on topics - * - * Sets the messageAge to be half the disconnection wait timeout - * Send 10 messages and then ensure that we get disconnected as we will - * wait for the full timeout. - * - * @throws Exception - */ - public void testTopicConsumerMessageAge() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("messageAge", String.valueOf(DISCONNECTION_WAIT / 2), false); - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, false); - } - - /** - * Test that setting messageCount takes affect on a durable Consumer - * - * Ensure we set the delete-persistent option - * - * We send 10 messages and disconnect at 9 - * - * @throws Exception - */ - - public void testTopicDurableConsumerMessageCount() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("messageCount", String.valueOf(MAX_QUEUE_MESSAGE_COUNT - 1), true); - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - - /** - * Test that setting depth has an effect on durable consumer topics - * - * Ensure we set the delete-persistent option - * - * Sets the message size for the test - * Sets the depth to be 9 * the depth - * Ensure that sending 10 messages causes the disconnection - * - * @throws Exception - */ - public void testTopicDurableConsumerMessageSize() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("depth", String.valueOf(MESSAGE_SIZE * 9), true); - - //Start the broker - startBroker(); - - setMessageSize(MESSAGE_SIZE); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - - /** - * Test that setting messageAge has an effect on topics - * - * Ensure we set the delete-persistent option - * - * Sets the messageAge to be 1/5 the disconnection wait timeout (or 1sec) - * Send 10 messages and then ensure that we get disconnected as we will - * wait for the full timeout. - * - * @throws Exception - */ - public void testTopicDurableConsumerMessageAge() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("messageAge", String.valueOf(DISCONNECTION_WAIT / 5), true); - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.java b/java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.java deleted file mode 100644 index 993d71ea34..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.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.systest; - -import org.apache.commons.configuration.ConfigurationException; - -import javax.jms.Session; -import javax.naming.NamingException; -import java.io.IOException; - -public class MergeConfigurationTest extends TestingBaseCase -{ - - protected int topicCount = 0; - - - public void configureTopic(String topic, int msgCount) throws NamingException, IOException, ConfigurationException - { - - setProperty(".topics.topic("+topicCount+").name", topic); - setProperty(".topics.topic("+topicCount+").slow-consumer-detection.messageCount", String.valueOf(msgCount)); - setProperty(".topics.topic("+topicCount+").slow-consumer-detection.policy.name", "TopicDelete"); - topicCount++; - } - - - /** - * Test that setting messageCount takes affect on topics - * - * We send 10 messages and disconnect at 9 - * - * @throws Exception - */ - public void testTopicConsumerMessageCount() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - configureTopic(getName(), (MAX_QUEUE_MESSAGE_COUNT * 4) - 1); - - //Configure topic as a subscription - setProperty(".topics.topic("+topicCount+").subscriptionName", "clientid:"+getTestQueueName()); - configureTopic(getName(), (MAX_QUEUE_MESSAGE_COUNT - 1)); - - - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - - -// -// public void testMerge() throws ConfigurationException, AMQException -// { -// -// AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()+":stockSubscription"), false, new AMQShortString("testowner"), -// false, false, _virtualHost, null); -// -// _virtualHost.getQueueRegistry().registerQueue(queue); -// Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange(); -// _virtualHost.getBindingFactory().addBinding(getName(), queue, defaultExchange, null); -// -// -// Exchange topicExchange = _virtualHost.getExchangeRegistry().getExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME); -// _virtualHost.getBindingFactory().addBinding("stocks.nyse.orcl", queue, topicExchange, null); -// -// TopicConfig config = queue.getConfiguration().getConfiguration(TopicConfig.class.getName()); -// -// assertNotNull("Queue should have topic configuration bound to it.", config); -// assertEquals("Configuration name not correct", getName() + ":stockSubscription", config.getSubscriptionName()); -// -// ConfigurationPlugin scdConfig = queue.getConfiguration().getConfiguration(SlowConsumerDetectionQueueConfiguration.class.getName()); -// if (scdConfig instanceof org.apache.qpid.server.configuration.plugin.SlowConsumerDetectionQueueConfiguration) -// { -// System.err.println("********************** scd is a SlowConsumerDetectionQueueConfiguration."); -// } -// else -// { -// System.err.println("********************** Test SCD "+SlowConsumerDetectionQueueConfiguration.class.getClassLoader()); -// System.err.println("********************** Broker SCD "+scdConfig.getClass().getClassLoader()); -// System.err.println("********************** Broker SCD "+scdConfig.getClass().isAssignableFrom(SlowConsumerDetectionQueueConfiguration.class)); -// System.err.println("********************** is a "+scdConfig.getClass()); -// } -// -// assertNotNull("Queue should have scd configuration bound to it.", scdConfig); -// assertEquals("MessageCount is not correct", 10 , ((SlowConsumerDetectionQueueConfiguration)scdConfig).getMessageCount()); -// assertEquals("Policy is not correct", TopicDeletePolicy.class.getName() , ((SlowConsumerDetectionQueueConfiguration)scdConfig).getPolicy().getClass().getName()); -// } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java deleted file mode 100644 index 9e9375fd44..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java +++ /dev/null @@ -1,146 +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.systest; - -import org.apache.commons.configuration.ConfigurationException; - -import javax.jms.Session; -import javax.naming.NamingException; -import java.io.IOException; - -/** - * Test SCD when configured with Subscription details. - * - * We run the subscription based tests here to validate that the - * subscriptionname value is correctly associated with the subscription. - * - * - */ -public class SubscriptionTest extends TestingBaseCase -{ - private int _count=0; - protected String CONFIG_SECTION = ".topics.topic"; - - /** - * Add configuration for the queue that relates just to this test. - * We use the getTestQueueName() as our subscription. To ensure the - * config sections do not overlap we identify each section with a _count - * value. - * - * This would allow each test to configure more than one section. - * - * @param property to set - * @param value the value to set - * @param deleteDurable should deleteDurable be set. - * @throws NamingException - * @throws IOException - * @throws ConfigurationException - */ - public void setConfig(String property, String value, boolean deleteDurable) throws NamingException, IOException, ConfigurationException - { - setProperty(CONFIG_SECTION + "("+_count+").subscriptionName", "clientid:"+getTestQueueName()); - - setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." + - "policy.name", "TopicDelete"); - - setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." + - property, value); - - if (deleteDurable) - { - setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." + - "policy.topicdelete.delete-persistent", ""); - } - _count++; - } - - - /** - * Test that setting messageCount takes affect on a durable Consumer - * - * Ensure we set the delete-persistent option - * - * We send 10 messages and disconnect at 9 - * - * @throws Exception - */ - - public void testTopicDurableConsumerMessageCount() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("messageCount", String.valueOf(MAX_QUEUE_MESSAGE_COUNT - 1), true); - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - - /** - * Test that setting depth has an effect on durable consumer topics - * - * Ensure we set the delete-persistent option - * - * Sets the message size for the test - * Sets the depth to be 9 * the depth - * Ensure that sending 10 messages causes the disconnection - * - * @throws Exception - */ - public void testTopicDurableConsumerMessageSize() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("depth", String.valueOf(MESSAGE_SIZE * 9), true); - - //Start the broker - startBroker(); - - setMessageSize(MESSAGE_SIZE); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - - /** - * Test that setting messageAge has an effect on topics - * - * Ensure we set the delete-persistent option - * - * Sets the messageAge to be 1/5 the disconnection wait timeout (or 1sec) - * Send 10 messages and then ensure that we get disconnected as we will - * wait for the full timeout. - * - * @throws Exception - */ - public void testTopicDurableConsumerMessageAge() throws Exception - { - MAX_QUEUE_MESSAGE_COUNT = 10; - - setConfig("messageAge", String.valueOf(DISCONNECTION_WAIT / 5), true); - - //Start the broker - startBroker(); - - topicConsumer(Session.AUTO_ACKNOWLEDGE, true); - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java b/java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java deleted file mode 100644 index 86c9462fc9..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java +++ /dev/null @@ -1,240 +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.systest; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.AMQException; -import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.Topic; -import javax.naming.NamingException; -import java.io.IOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class TestingBaseCase extends QpidBrokerTestCase implements ExceptionListener, ConnectionListener -{ - - private Topic _destination; - protected CountDownLatch _disconnectionLatch = new CountDownLatch(1); - protected int MAX_QUEUE_MESSAGE_COUNT; - protected int MESSAGE_SIZE = DEFAULT_MESSAGE_SIZE; - - private Thread _publisher; - protected static final long DISCONNECTION_WAIT = 5; - protected Exception _publisherError = null; - protected JMSException _connectionException = null; - private static final long JOIN_WAIT = 5000; - - @Override - public void setUp() throws Exception - { - - setConfigurationProperty("virtualhosts.virtualhost." - + getConnectionURL().getVirtualHost().substring(1) + - ".slow-consumer-detection.delay", "1"); - - setConfigurationProperty("virtualhosts.virtualhost." - + getConnectionURL().getVirtualHost().substring(1) + - ".slow-consumer-detection.timeunit", "SECONDS"); - - } - - - protected void setProperty(String property, String value) throws NamingException, IOException, ConfigurationException - { - setConfigurationProperty("virtualhosts.virtualhost." + - getConnectionURL().getVirtualHost().substring(1) + - property, value); - } - - - /** - * Create and start an asynchrounous publisher that will send MAX_QUEUE_MESSAGE_COUNT - * messages to the provided destination. Messages are sent in a new connection - * on a transaction. Any error is captured and the test is signalled to exit. - * - * @param destination - */ - private void startPublisher(final Destination destination) - { - _publisher = new Thread(new Runnable() - { - - public void run() - { - try - { - Connection connection = getConnection(); - Session session = connection.createSession(true, Session.SESSION_TRANSACTED); - - MessageProducer publisher = session.createProducer(destination); - - for (int count = 0; count < MAX_QUEUE_MESSAGE_COUNT; count++) - { - publisher.send(createNextMessage(session, count)); - session.commit(); - } - } - catch (Exception e) - { - _publisherError = e; - _disconnectionLatch.countDown(); - } - } - }); - - _publisher.start(); - } - - - - /** - * Perform the Main test of a topic Consumer with the given AckMode. - * - * Test creates a new connection and sets up the connection to prevent - * failover - * - * A new consumer is connected and started so that it will prefetch msgs. - * - * An asynchrounous publisher is started to fill the broker with messages. - * - * We then wait to be notified of the disconnection via the ExceptionListener - * - * 0-10 does not have the same notification paths but sync() apparently should - * give us the exception, currently it doesn't, so the test is excluded from 0-10 - * - * We should ensure that this test has the same path for all protocol versions. - * - * Clients should not have to modify their code based on the protocol in use. - * - * @param ackMode @see javax.jms.Session - * - * @throws Exception - */ - protected void topicConsumer(int ackMode, boolean durable) throws Exception - { - Connection connection = getConnection(); - - connection.setExceptionListener(this); - - Session session = connection.createSession(ackMode == Session.SESSION_TRANSACTED, ackMode); - - _destination = session.createTopic(getName()); - - MessageConsumer consumer; - - if (durable) - { - consumer = session.createDurableSubscriber(_destination, getTestQueueName()); - } - else - { - consumer = session.createConsumer(_destination); - } - - connection.start(); - - // Start the consumer pre-fetching - // Don't care about response as we will fill the broker up with messages - // after this point and ensure that the client is disconnected at the - // right point. - consumer.receiveNoWait(); - startPublisher(_destination); - - boolean disconnected = _disconnectionLatch.await(DISCONNECTION_WAIT, TimeUnit.SECONDS); - - assertTrue("Client was not disconnected", disconnected); - assertTrue("Client was not disconnected.", _connectionException != null); - - Exception linked = _connectionException.getLinkedException(); - - _publisher.join(JOIN_WAIT); - - assertFalse("Publisher still running", _publisher.isAlive()); - - //Validate publishing occurred ok - if (_publisherError != null) - { - throw _publisherError; - } - - // NOTE these exceptions will need to be modeled so that they are not - // 0-8 specific. e.g. JMSSessionClosedException - - assertNotNull("No error received onException listener.", _connectionException); - - assertNotNull("No linked exception set on:" + _connectionException.getMessage(), linked); - - assertTrue("Incorrect linked exception received.", linked instanceof AMQException); - - AMQException amqException = (AMQException) linked; - - assertEquals("Channel was not closed with correct code.", AMQConstant.RESOURCE_ERROR, amqException.getErrorCode()); - } - - - // Exception Listener - - public void onException(JMSException e) - { - _connectionException = e; - - e.printStackTrace(); - - _disconnectionLatch.countDown(); - } - - /// Connection Listener - - public void bytesSent(long count) - { - } - - public void bytesReceived(long count) - { - } - - public boolean preFailover(boolean redirect) - { - // Prevent Failover - return false; - } - - public boolean preResubscribe() - { - return false; - } - - public void failoverComplete() - { - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java b/java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java deleted file mode 100644 index 09c849cfde..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java +++ /dev/null @@ -1,85 +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.systest; - -import org.apache.commons.configuration.ConfigurationException; - -import javax.naming.NamingException; -import java.io.IOException; - -/** - * This Topic test extends the Global queue test so it will run all the topic - * and subscription tests. - * - * We redefine the CONFIG_SECTION here so that the configuration is written - * against a topic element. - * - * To complete the migration to testing 'topic' elements we also override - * the setConfig to use the test name as the topic name. - * - */ -public class TopicTest extends GlobalQueuesTest -{ - private int _count=0; - - @Override - public void setUp() throws Exception - { - CONFIG_SECTION = ".topics.topic"; - super.setUp(); - } - - /** - * Add configuration for the queue that relates just to this test. - * We use the getTestQueueName() as our subscription. To ensure the - * config sections do not overlap we identify each section with a _count - * value. - * - * This would allow each test to configure more than one section. - * - * @param property to set - * @param value the value to set - * @param deleteDurable should deleteDurable be set. - * @throws NamingException - * @throws IOException - * @throws ConfigurationException - */ - @Override - public void setConfig(String property, String value, boolean deleteDurable) throws NamingException, IOException, ConfigurationException - { - setProperty(CONFIG_SECTION + "("+_count+").name", getName()); - - setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." + - "policy.name", "TopicDelete"); - - setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." + - property, value); - - if (deleteDurable) - { - setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." + - "policy.topicdelete.delete-persistent", ""); - } - _count++; - } - - -} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java new file mode 100644 index 0000000000..954208e78e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.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.systest.management.jmx; + +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedExchange; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +/** + * Tests the JMX API for the Managed Broker. + * + */ +public class BrokerManagementTest extends QpidBrokerTestCase +{ + private static final String VIRTUAL_HOST = "test"; + + /** + * JMX helper. + */ + private JMXTestUtils _jmxUtils; + private ManagedBroker _managedBroker; + + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + super.setUp(); + _jmxUtils.open(); + _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + } + + public void tearDown() throws Exception + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + super.tearDown(); + } + + /** + * Tests queue creation/deletion also verifying the automatic binding to the default exchange. + */ + public void testCreateQueueAndDeletion() throws Exception + { + final String queueName = getTestQueueName(); + final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); + + // Check that bind does not exist before queue creation + assertFalse("Binding to " + queueName + " should not exist in default exchange before queue creation", + defaultExchange.bindings().containsKey(new String[] {queueName})); + + _managedBroker.createNewQueue(queueName, "testowner", true); + + // Ensure the queue exists + assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName)); + assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); + + // Now verify that the default exchange has been bound. + assertTrue("Binding to " + queueName + " should exist in default exchange after queue creation", + defaultExchange.bindings().containsKey(new String[] {queueName})); + + // Now delete the queue + _managedBroker.deleteQueue(queueName); + + // Finally ensure that the binding has been removed. + assertFalse("Binding to " + queueName + " should not exist in default exchange after queue deletion", + defaultExchange.bindings().containsKey(new String[] {queueName})); + } + + /** + * Tests exchange creation/deletion via JMX API. + */ + public void testCreateExchangeAndUnregister() throws Exception + { + String exchangeName = getTestName(); + _managedBroker.createNewExchange(exchangeName, "topic", true); + + ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName); + assertNotNull("Exchange should exist", exchange); + + _managedBroker.unregisterExchange(exchangeName); + } + + /** + * Tests that it is disallowed to unregister the default exchange. + */ + public void testUnregisterOfDefaultExchangeDisallowed() throws Exception + { + String defaultExchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(); + + ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName); + assertNotNull("Exchange should exist", defaultExchange); + try + { + _managedBroker.unregisterExchange(defaultExchangeName); + fail("Exception not thrown"); + } + catch (UnsupportedOperationException e) + { + // PASS + assertEquals("'<<default>>' is a reserved exchange and can't be deleted", e.getMessage()); + } + defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName); + assertNotNull("Exchange should exist", defaultExchange); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java new file mode 100644 index 0000000000..28d7bf4aed --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.jmx; + +import java.io.IOException; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.management.JMException; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.TabularData; + +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.management.common.mbeans.ManagedConnection; +import org.apache.qpid.management.common.mbeans.ManagedQueue; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class ConnectionManagementTest extends QpidBrokerTestCase +{ + private static final String VIRTUAL_HOST_NAME = "test"; + + private JMXTestUtils _jmxUtils; + private Connection _connection; + + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp() + super.setUp(); + _jmxUtils.open(); + } + + public void tearDown() throws Exception + { + try + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception + { + assertEquals("Expected no managed connections", 0, getManagedConnections().size()); + + _connection = getConnection(); + assertEquals("Expected one managed connection", 1, getManagedConnections().size()); + + _connection.close(); + assertEquals("Expected no managed connections after client connection closed", 0, getManagedConnections().size()); + } + + public void testGetAttributes() throws Exception + { + _connection = getConnection(); + final ManagedConnection mBean = getConnectionMBean(); + + checkAuthorisedId(mBean); + checkClientVersion(mBean); + checkClientId(mBean); + } + + public void testNonTransactedSession() throws Exception + { + _connection = getConnection(); + + boolean transactional = false; + boolean flowBlocked = false; + + _connection.createSession(transactional, Session.AUTO_ACKNOWLEDGE); + + final ManagedConnection mBean = getConnectionMBean(); + final CompositeDataSupport row = getTheOneChannelRow(mBean); + assertChannelRowData(row, 0, transactional, flowBlocked); + } + + public void testTransactedSessionWithUnackMessages() throws Exception + { + _connection = getConnection(); + _connection.start(); + + boolean transactional = true; + int numberOfMessages = 2; + final Session session = _connection.createSession(transactional, Session.SESSION_TRANSACTED); + final Destination destination = session.createQueue(getTestQueueName()); + final MessageConsumer consumer = session.createConsumer(destination); + + sendMessage(session, destination, numberOfMessages); + receiveMessagesWithoutCommit(consumer, numberOfMessages); + + final ManagedConnection mBean = getConnectionMBean(); + final CompositeDataSupport row = getTheOneChannelRow(mBean); + boolean flowBlocked = false; + assertChannelRowData(row, numberOfMessages, transactional, flowBlocked); + + // check that commit advances the lastIoTime + final Date initialLastIOTime = mBean.getLastIoTime(); + session.commit(); + assertTrue("commit should have caused last IO time to advance", mBean.getLastIoTime().after(initialLastIOTime)); + + // check that channels() now returns one session with no unacknowledged messages + final CompositeDataSupport rowAfterCommit = getTheOneChannelRow(mBean); + final Number unackCountAfterCommit = (Number) rowAfterCommit.get(ManagedConnection.UNACKED_COUNT); + assertEquals("Unexpected number of unacknowledged messages", 0, unackCountAfterCommit); + } + + + public void testProducerFlowBlocked() throws Exception + { + _connection = getConnection(); + _connection.start(); + + String queueName = getTestQueueName(); + Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); + Queue queue = session.createQueue(queueName); + createQueueOnBroker(session, queue); + + ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + managedQueue.setFlowResumeCapacity(DEFAULT_MESSAGE_SIZE * 2l); + managedQueue.setCapacity(DEFAULT_MESSAGE_SIZE * 3l); + + final ManagedConnection managedConnection = getConnectionMBean(); + + // Check that producer flow is not block before test + final CompositeDataSupport rowBeforeSend = getTheOneChannelRow(managedConnection); + assertFlowBlocked(rowBeforeSend, false); + + + // Check that producer flow does not become block too soon + sendMessage(session, queue, 3); + final CompositeDataSupport rowBeforeFull = getTheOneChannelRow(managedConnection); + assertFlowBlocked(rowBeforeFull, false); + + // Fourth message will over-fill the queue (but as we are not sending more messages, client thread wont't block) + sendMessage(session, queue, 1); + final CompositeDataSupport rowAfterFull = getTheOneChannelRow(managedConnection); + assertFlowBlocked(rowAfterFull, true); + + // Consume two to bring the queue down to the resume capacity + MessageConsumer consumer = session.createConsumer(queue); + assertNotNull("Could not receive first message", consumer.receive(1000)); + assertNotNull("Could not receive second message", consumer.receive(1000)); + session.commit(); + + // Check that producer flow is no longer blocked + final CompositeDataSupport rowAfterReceive = getTheOneChannelRow(managedConnection); + assertFlowBlocked(rowAfterReceive, false); + } + + private void createQueueOnBroker(Session session, Destination destination) throws JMSException + { + session.createConsumer(destination).close(); // Create a consumer only to cause queue creation + } + + private void assertChannelRowData(final CompositeData row, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked) + { + assertNotNull(row); + assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL)); + assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT)); + assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED)); + } + + private void assertFlowBlocked(final CompositeData row, boolean flowBlocked) + { + assertNotNull(row); + assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED)); + } + + private void checkAuthorisedId(ManagedConnection mBean) throws Exception + { + assertEquals("Unexpected authorized id", GUEST_USERNAME, mBean.getAuthorizedId()); + } + + private void checkClientVersion(ManagedConnection mBean) throws Exception + { + String expectedVersion = QpidProperties.getReleaseVersion(); + assertTrue(StringUtils.isNotBlank(expectedVersion)); + + assertEquals("Unexpected version", expectedVersion, mBean.getVersion()); + } + + private void checkClientId(ManagedConnection mBean) throws Exception + { + String expectedClientId = _connection.getClientID(); + assertTrue(StringUtils.isNotBlank(expectedClientId)); + + assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId()); + } + + private ManagedConnection getConnectionMBean() + { + List<ManagedConnection> connections = getManagedConnections(); + assertNotNull("Connection MBean is not found", connections); + assertEquals("Unexpected number of connection mbeans", 1, connections.size()); + final ManagedConnection mBean = connections.get(0); + assertNotNull("Connection MBean is null", mBean); + return mBean; + } + + private List<ManagedConnection> getManagedConnections() + { + return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME); + } + + private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception + { + TabularData channelsData = getChannelsDataWithRetry(mBean); + + assertEquals("Unexpected number of rows in channel table", 1, channelsData.size()); + + @SuppressWarnings("unchecked") + final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator(); + final CompositeDataSupport row = rowItr.next(); + return row; + } + + private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception + { + for (int i = 0; i < numberOfMessages; i++) + { + final Message m = consumer.receive(1000l); + assertNotNull("Message " + i + " is not received", m); + } + } + + private TabularData getChannelsDataWithRetry(final ManagedConnection mBean) + throws IOException, JMException + { + TabularData channelsData = mBean.channels(); + int retries = 0; + while(channelsData.size() == 0 && retries < 5) + { + sleep(); + channelsData = mBean.channels(); + retries++; + } + return channelsData; + } + + private void sleep() + { + try + { + Thread.sleep(50); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + } + }} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java new file mode 100644 index 0000000000..3c3bbdca41 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.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.systest.management.jmx; + +import java.io.File; +import java.util.List; + +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; + +import org.apache.qpid.management.common.mbeans.LoggingManagement; +import org.apache.qpid.server.logging.log4j.LoggingManagementFacadeTest; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.util.FileUtils; +import org.apache.qpid.util.LogMonitor; + +/** + * System test for Logging Management. <b>These tests rely on value set within + * test-profiles/log4j-test.xml</b>. + * + * @see LoggingManagementMBeanTest + * @see LoggingManagementFacadeTest + * + */ +public class LoggingManagementTest extends QpidBrokerTestCase +{ + private JMXTestUtils _jmxUtils; + private LoggingManagement _loggingManagement; + private LogMonitor _monitor; + + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + + // System test normally run with log for4j test config from beneath test-profiles. We need to + // copy it as some of our tests write to this file. + + File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml"); + tmpLogFile.deleteOnExit(); + FileUtils.copy(getBrokerCommandLog4JFile(), tmpLogFile); + setBrokerCommandLog4JFile(tmpLogFile); + + super.setUp(); + _jmxUtils.open(); + + _loggingManagement = _jmxUtils.getLoggingManagement(); + _monitor = new LogMonitor(_outputFile); + } + + public void tearDown() throws Exception + { + try + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testViewEffectiveRuntimeLoggerLevels() throws Exception + { + final String qpidMainLogger = "org.apache.qpid"; + + TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); + final CompositeData row = table.get(new String[] {qpidMainLogger} ); + assertChannelRow(row, qpidMainLogger, "DEBUG"); + } + + public void testViewConfigFileLoggerLevels() throws Exception + { + final String operationalLoggingLogger = "qpid.message"; + + TabularData table = _loggingManagement.viewConfigFileLoggerLevels(); + final CompositeData row = table.get(new String[] {operationalLoggingLogger} ); + assertChannelRow(row, operationalLoggingLogger, "INFO"); + } + + public void testTurnOffOrgApacheQpidAtRuntime() throws Exception + { + final String logger = "org.apache.qpid"; + _monitor.markDiscardPoint(); + _loggingManagement.setRuntimeLoggerLevel(logger, "OFF"); + + List<String> matches = _monitor.waitAndFindMatches("Setting level to OFF for logger 'org.apache.qpid'", 5000); + assertEquals(1, matches.size()); + + TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); + final CompositeData row1 = table.get(new String[] {logger} ); + assertChannelRow(row1, logger, "OFF"); + } + + public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception + { + final String operationalLoggingLogger = "qpid.message"; + assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); + + _monitor.markDiscardPoint(); + _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF"); + + List<String> matches = _monitor.waitAndFindMatches("Setting level to OFF for logger 'qpid.message'", 5000); + assertEquals(1, matches.size()); + + assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); + + _loggingManagement.reloadConfigFile(); + + assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF"); + } + + private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel) + { + TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); + final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} ); + assertChannelRow(row1, operationalLoggingLogger, expectedLevel); + } + + private void assertChannelRow(final CompositeData row, String logger, String level) + { + assertNotNull("No row for " + logger, row); + assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME)); + assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL)); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java new file mode 100644 index 0000000000..47b38381c5 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java @@ -0,0 +1,480 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.jmx; + +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; +import org.apache.qpid.management.common.mbeans.ManagedExchange; +import org.apache.qpid.server.logging.AbstractTestLogging; +import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; +import org.apache.qpid.test.utils.JMXTestUtils; + +import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.management.JMException; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Test class to test if any change in the broker JMX code is affesting the management console + * There are some hardcoding of management feature names and parameter names to create a customized + * look in the console. + */ +public class ManagementActorLoggingTest extends AbstractTestLogging +{ + private JMXTestUtils _jmxUtils; + private boolean _closed = false; + + @Override + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + super.setUp(); + _jmxUtils.open(); + } + + @Override + public void tearDown() throws Exception + { + if(!_closed) + { + _jmxUtils.close(); + } + super.tearDown(); + } + + /** + * Description: + * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message. + * Input: + * + * 1. Running Broker + * 2. Connected Client + * 3. Connection is closed via Management Console + * Output: + * + * <date> CON-1002 : Close + * + * Validation Steps: + * 4. The CON ID is correct + * 5. This must be the last CON message for the Connection + * 6. It must be preceded by a CON-1001 for this Connection + * + * @throws Exception - {@see ManagedConnection.closeConnection and #getConnection} + * @throws java.io.IOException - if there is a problem reseting the log monitor + */ + public void testConnectionCloseViaManagement() throws IOException, Exception + { + //Create a connection to the broker + Connection connection = getConnection(); + + // Monitor the connection for an exception being thrown + // this should be a DisconnectionException but it is not this tests + // job to valiate that. Only use the exception as a synchronisation + // to check the log file for the Close message + final CountDownLatch exceptionReceived = new CountDownLatch(1); + connection.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + //Failover being attempted. + exceptionReceived.countDown(); + } + }); + + //Remove the connection close from any 0-10 connections + _monitor.markDiscardPoint(); + + // Get a managedConnection + ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*"); + + //Close the connection + mangedConnection.closeConnection(); + + //Wait for the connection to close + assertTrue("Timed out waiting for conneciton to report close", + exceptionReceived.await(2, TimeUnit.SECONDS)); + + //Validate results + List<String> results = waitAndFindMatches("CON-1002"); + + assertEquals("Unexpected Connection Close count", 1, results.size()); + } + + /** + * Description: + * Exchange creation is possible from the Management Console. + * When an exchanged is created in this way then a EXH-1001 create message + * is expected to be logged. + * Input: + * + * 1. Running broker + * 2. Connected Management Console + * 3. Exchange Created via Management Console + * Output: + * + * EXH-1001 : Create : [Durable] Type:<value> Name:<value> + * + * Validation Steps: + * 4. The EXH ID is correct + * 5. The correct tags are present in the message based on the create options + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} + */ + public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException + { + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "direct", false); + + // Validate + + //1 - ID is correct + List<String> results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous exchange declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "topic", false); + + // Validate + + //1 - ID is correct + List<String> results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous exchange declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "fanout", false); + + // Validate + + //1 - ID is correct + List<String> results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous exchange declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "headers", false); + + // Validate + + //1 - ID is correct + List<String> results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + /** + * Description: + * Queue creation is possible from the Management Console. When a queue is created in this way then a QUE-1001 create message is expected to be logged. + * Input: + * + * 1. Running broker + * 2. Connected Management Console + * 3. Queue Created via Management Console + * Output: + * + * <date> QUE-1001 : Create : Transient Owner:<name> + * + * Validation Steps: + * 4. The QUE ID is correct + * 5. The correct tags are present in the message based on the create options + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} + */ + public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + // Validate + + List<String> results = waitAndFindMatches("QUE-1001"); + + assertEquals("More than one queue creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct queue name + String subject = fromSubject(log); + assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + /** + * Description: + * The ManagementConsole can be used to delete a queue. When this is done a QUE-1002 Deleted message must be logged. + * Input: + * + * 1. Running Broker + * 2. Queue created on the broker with no subscribers + * 3. Management Console connected + * 4. Queue is deleted via Management Console + * Output: + * + * <date> QUE-1002 : Deleted + * + * Validation Steps: + * 5. The QUE ID is correct + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} + */ + public void testQueueDeleteViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); + + managedBroker.deleteQueue(getName()); + + List<String> results = waitAndFindMatches("QUE-1002"); + + assertEquals("More than one queue deletion found", 1, results.size()); + + String log = getLog(results.get(0)); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + /** + * Description: + * The binding of a Queue and an Exchange is done via a Binding. When this Binding is created via the Management Console a BND-1001 Create message will be logged. + * Input: + * + * 1. Running Broker + * 2. Connected Management Console + * 3. Use Management Console to perform binding + * Output: + * + * <date> BND-1001 : Create + * + * Validation Steps: + * 4. The BND ID is correct + * 5. This will be the first message for the given binding + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.createNewBinding} + */ + public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct"); + + managedExchange.createNewBinding(getName(), getName()); + + List<String> results = waitAndFindMatches("BND-1001"); + + assertEquals("Unexpected number of bindings logged", 2, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic"); + + managedExchange.createNewBinding(getName(), getName()); + + List<String> results = waitAndFindMatches("BND-1001"); + + assertEquals("Unexpected number of bindings logged", 2, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout"); + + managedExchange.createNewBinding(getName(), getName()); + + List<String> results = waitAndFindMatches("BND-1001"); + + assertEquals("Unexpected number of bindings logged", 2, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + /** + * Description: + * Bindings can be deleted so that a queue can be rebound with a different set of values. This can be performed via the Management Console + * Input: + * + * 1. Running Broker + * 2. Management Console connected + * 3. Management Console is used to perform unbind. + * Output: + * + * <date> BND-1002 : Deleted + * + * Validation Steps: + * 4. The BND ID is correct + * 5. There must have been a BND-1001 Create message first. + * 6. This will be the last message for the given binding + * + * @throws java.io.IOException - if there is a problem reseting the log monitor or an issue with the JMX Connection + * @throws javax.management.JMException - {@see #createExchange and ManagedBroker.unregisterExchange} + */ + public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "direct", false); + + ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); + + managedBroker.unregisterExchange(getName()); + + List<String> results = waitAndFindMatches("EXH-1002"); + + assertEquals("More than one exchange deletion found", 1, results.size()); + + String log = getLog(results.get(0)); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java new file mode 100644 index 0000000000..950b002b87 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java @@ -0,0 +1,330 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.jmx; + + +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.logging.AbstractTestLogging; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestSSLConstants; +import org.apache.qpid.util.LogMonitor; + +import java.util.Collections; +import java.util.List; + +/** + * Management Console Test Suite + * + * The Management Console test suite validates that the follow log messages as specified in the Functional Specification. + * + * This suite of tests validate that the management console messages occur correctly and according to the following format: + * + * MNG-1001 : <type> Management Startup + * MNG-1002 : Starting : <service> : Listening on port <Port> + * MNG-1003 : Shutting down : <service> : port <Port> + * MNG-1004 : <type> Management Ready + * MNG-1005 : <type> Management Stopped + * MNG-1006 : Using SSL Keystore : <path> + * MNG-1007 : Open : User <username> + * MNG-1008 : Close : User <username> + */ +public class ManagementLoggingTest extends AbstractTestLogging +{ + private static final String MNG_PREFIX = "MNG-"; + + public void setUp() throws Exception + { + setLogMessagePrefix(); + + // We either do this here or have a null check in tearDown. + // As when this test is run against profiles other than java it will NPE + _monitor = new LogMonitor(_outputFile); + //We explicitly do not call super.setUp as starting up the broker is + //part of the test case. + + } + + /** + * Description: + * Using the startup configuration validate that the management startup + * message is logged correctly. + * Input: + * Standard configuration with management enabled + * Output: + * + * <date> MNG-1001 : Startup + * + * Constraints: + * This is the FIRST message logged by MNG + * Validation Steps: + * + * 1. The BRK ID is correct + * 2. This is the FIRST message logged by MNG + */ + public void testManagementStartupEnabled() throws Exception + { + // This test only works on java brokers + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(true, false); + + // Ensure we have received the MNG log msg. + waitForMessage("MNG-1001"); + + List<String> results = findMatches(MNG_PREFIX); + // Validation + + assertTrue("MNGer message not logged", results.size() > 0); + + String log = getLogMessage(results, 0); + + //1 + validateMessageID("MNG-1001", log); + + //2 + //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) + results = findMatches("MNG-1001"); + assertEquals("Unexpected startup message count.", + 2, results.size()); + + //3 + assertEquals("Startup log message is not 'Startup'.", "JMX Management Startup", + getMessageString(log)); + } + } + + /** + * Description: + * Verify that when management is disabled in the configuration file the + * startup message is not logged. + * Input: + * Standard configuration with management disabled + * Output: + * NO MNG messages + * Validation Steps: + * + * 1. Validate that no MNG messages are produced. + */ + public void testManagementStartupDisabled() throws Exception + { + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(false, false); + + List<String> results = findMatches(MNG_PREFIX); + // Validation + + assertEquals("MNGer messages logged", 0, results.size()); + } + } + + /** + * The two MNG-1002 messages are logged at the same time so lets test them + * at the same time. + * + * Description: + * Using the default configuration validate that the RMI Registry socket is + * correctly reported as being opened + * + * Input: + * The default configuration file + * Output: + * + * <date> MESSAGE MNG-1002 : Starting : RMI Registry : Listening on port 8999 + * + * Constraints: + * The RMI ConnectorServer and Registry log messages do not have a prescribed order + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The specified port is the correct '8999' + * + * Description: + * Using the default configuration validate that the RMI ConnectorServer + * socket is correctly reported as being opened + * + * Input: + * The default configuration file + * Output: + * + * <date> MESSAGE MNG-1002 : Starting : RMI ConnectorServer : Listening on port 9099 + * + * Constraints: + * The RMI ConnectorServer and Registry log messages do not have a prescribed order + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The specified port is the correct '9099' + */ + public void testManagementStartupRMIEntries() throws Exception + { + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(true, false); + + List<String> results = waitAndFindMatches("MNG-1002"); + // Validation + + //There will be 4 startup messages (two via SystemOut, and two via Log4J) + assertEquals("Unexpected MNG-1002 message count", 4, results.size()); + + String log = getLogMessage(results, 0); + + //1 + validateMessageID("MNG-1002", log); + + //Check the RMI Registry port is as expected + int mPort = getManagementPort(getPort()); + assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log), + getMessageString(log).endsWith(String.valueOf(mPort))); + + log = getLogMessage(results, 2); + + //1 + validateMessageID("MNG-1002", log); + + // We expect the RMI Registry port (the defined 'management port') to be + // 100 lower than the JMX RMIConnector Server Port (the actual JMX server) + int jmxPort = mPort + JMXPORT_CONNECTORSERVER_OFFSET; + assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log), + getMessageString(log).endsWith(String.valueOf(jmxPort))); + } + } + + /** + * Description: + * Using the default configuration with SSL enabled for the management port the SSL Keystore path should be reported via MNG-1006 + * Input: + * Management SSL enabled default configuration. + * Output: + * + * <date> MESSAGE MNG-1006 : Using SSL Keystore : test_resources/ssl/keystore.jks + * + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The keystore path is as specified in the configuration + */ + public void testManagementStartupSSLKeystore() throws Exception + { + if (isJavaBroker()) + { + setSystemProperty("javax.net.debug", "ssl"); + startBrokerAndCreateMonitor(true, true); + + List<String> results = waitAndFindMatches("MNG-1006"); + + assertTrue("MNGer message not logged", results.size() > 0); + + String log = getLogMessage(results, 0); + + //1 + validateMessageID("MNG-1006", log); + + // Validate we only have two MNG-1002 (one via stdout, one via log4j) + results = findMatches("MNG-1006"); + assertEquals("Upexpected SSL Keystore message count", + 2, results.size()); + + // Validate the keystore path is as expected + assertTrue("SSL Keystore entry expected.:" + getMessageString(log), + getMessageString(log).endsWith(TestSSLConstants.BROKER_KEYSTORE)); + } + } + + /** + * Description: Tests the management connection open/close are logged correctly. + * + * Output: + * + * <date> MESSAGE MNG-1007 : Open : User <username> + * <date> MESSAGE MNG-1008 : Close : User <username> + * + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The message and username are correct + */ + public void testManagementUserOpenClose() throws Exception + { + if (isJavaBroker()) + { + setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false"); + startBrokerAndCreateMonitor(true, false); + + final JMXTestUtils jmxUtils = new JMXTestUtils(this); + List<String> openResults = null; + List<String> closeResults = null; + try + { + jmxUtils.setUp(); + jmxUtils.open(); + openResults = waitAndFindMatches("MNG-1007"); + } + finally + { + if (jmxUtils != null) + { + jmxUtils.close(); + closeResults = waitAndFindMatches("MNG-1008"); + } + } + + assertNotNull("Management Open results null", openResults.size()); + assertEquals("Management Open logged unexpected number of times", 1, openResults.size()); + + assertNotNull("Management Close results null", closeResults.size()); + assertEquals("Management Close logged unexpected number of times", 1, closeResults.size()); + + final String openMessage = getMessageString(getLogMessage(openResults, 0)); + assertTrue("Unexpected open message " + openMessage, openMessage.endsWith("Open : User admin")); + final String closeMessage = getMessageString(getLogMessage(closeResults, 0)); + assertTrue("Unexpected close message " + closeMessage, closeMessage.endsWith("Close : User admin")); + } + } + + private void startBrokerAndCreateMonitor(boolean managementEnabled, boolean useManagementSSL) throws Exception + { + TestBrokerConfiguration config = getBrokerConfiguration(); + + if (managementEnabled) + { + config.addJmxManagementConfiguration(); + } + + if(useManagementSSL) + { + // This test requires we have an ssl connection + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + + setSystemProperty("javax.net.ssl.keyStore", "test-profiles/test_resources/ssl/java_broker_keystore.jks"); + setSystemProperty("javax.net.ssl.keyStorePassword", "password"); + } + + startBroker(); + + // Now we can create the monitor as _outputFile will now be defined + _monitor = new LogMonitor(_outputFile); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java new file mode 100644 index 0000000000..0d3289d1bd --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java @@ -0,0 +1,778 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.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.framing.AMQShortString; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.NotificationCheckTest; +import org.apache.qpid.server.queue.SimpleAMQQueueTest; +import org.apache.qpid.test.client.destination.AddressBasedDestinationTest; +import org.apache.qpid.test.utils.JMXTestUtils; +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.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; +import javax.naming.NamingException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +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; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Tests the JMX API for the Managed Queue. + * + */ +public class QueueManagementTest extends QpidBrokerTestCase +{ + + private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class); + + private static final String VIRTUAL_HOST = "test"; + private static final String TEST_QUEUE_DESCRIPTION = "my description"; + + 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"; + + createConnectionAndSession(); + + _sourceQueue = _session.createQueue(_sourceQueueName); + _destinationQueue = _session.createQueue(_destinationQueueName); + createQueueOnBroker(_sourceQueue); + createQueueOnBroker(_destinationQueue); + + _jmxUtils.open(); + + createManagementInterfacesForQueues(); + } + + public void tearDown() throws Exception + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + super.tearDown(); + } + + public void testQueueAttributes() throws Exception + { + Queue queue = _session.createQueue(getTestQueueName()); + createQueueOnBroker(queue); + + final String queueName = queue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Unexpected name", queueName, managedQueue.getName()); + assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType()); + } + + public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception + { + Queue tmpQueue = _session.createTemporaryQueue(); + + final String queueName = tmpQueue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertNotNull(_connection.getClientID()); + assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner()); + } + + public void testNonExclusiveQueueHasNoOwner() throws Exception + { + Queue nonExclusiveQueue = _session.createQueue(getTestQueueName()); + createQueueOnBroker(nonExclusiveQueue); + + final String queueName = nonExclusiveQueue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertNull("Unexpected owner", managedQueue.getOwner()); + } + + public void testSetNewQueueDescriptionOnExistingQueue() throws Exception + { + Queue queue = _session.createQueue(getTestQueueName()); + createQueueOnBroker(queue); + + final String queueName = queue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertNull("Unexpected description", managedQueue.getDescription()); + + managedQueue.setDescription(TEST_QUEUE_DESCRIPTION); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + } + + public void testNewQueueWithDescription() throws Exception + { + String queueName = getTestQueueName(); + Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); + ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + } + + /** + * Requires persistent store. + */ + public void testQueueDescriptionSurvivesRestart() throws Exception + { + String queueName = getTestQueueName(); + Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); + + ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); + + ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + + restartBroker(); + + managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + } + + /** + * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests + * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}. + */ + public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception + { + final String queueName = getName(); + final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + + final Integer deliveryCount = 1; + final Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount); + managedBroker.createNewQueue(queueName, null, true, arguments); + + // Ensure the queue exists + assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName)); + assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount()); + } + + public void testCreateQueueWithAlertingThresholdsSet() throws Exception + { + final String queueName = getName(); + final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + + final Long maximumMessageCount = 100l; + final Long maximumMessageSize = 200l; + final Long maximumQueueDepth = 300l; + final Long maximumMessageAge = 400l; + final Map<String, Object> arguments = new HashMap<String, Object>(); + arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_COUNT, maximumMessageCount); + arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_SIZE, maximumMessageSize); + arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_QUEUE_DEPTH, maximumQueueDepth); + arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_AGE, maximumMessageAge); + + managedBroker.createNewQueue(queueName, null, true, arguments); + + // Ensure the queue exists + assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName)); + assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); + + ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Unexpected maximum message count", maximumMessageCount, managedQueue.getMaximumMessageCount()); + assertEquals("Unexpected maximum message size", maximumMessageSize, managedQueue.getMaximumMessageSize()); + assertEquals("Unexpected maximum queue depth", maximumQueueDepth, managedQueue.getMaximumQueueDepth()); + assertEquals("Unexpected maximum message age", maximumMessageAge, managedQueue.getMaximumMessageAge()); + } + + /** + * Requires 0-10 as relies on ADDR addresses. + * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange + */ + public void testGetSetAlternateExchange() throws Exception + { + String queueName = getTestQueueName(); + String altExchange = "amq.fanout"; + String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); + Queue queue = _session.createQueue(addrWithAltExch); + + createQueueOnBroker(queue); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); + + String newAltExch = "amq.topic"; + managedQueue.setAlternateExchange(newAltExch); + assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange()); + } + + /** + * Requires 0-10 as relies on ADDR addresses. + */ + public void testRemoveAlternateExchange() throws Exception + { + String queueName = getTestQueueName(); + String altExchange = "amq.fanout"; + String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); + Queue queue = _session.createQueue(addrWithAltExch); + + createQueueOnBroker(queue); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); + + managedQueue.setAlternateExchange(""); + assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange()); + } + + /** + * Requires persistent store + * Requires 0-10 as relies on ADDR addresses. + */ + public void testAlternateExchangeSurvivesRestart() throws Exception + { + String nonMandatoryExchangeName = "exch" + getName(); + + final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true); + + String queueName1 = getTestQueueName() + "1"; + String altExchange1 = "amq.fanout"; + String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1); + Queue queue1 = _session.createQueue(addr1WithAltExch); + + String queueName2 = getTestQueueName() + "2"; + String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2); + Queue queue2 = _session.createQueue(addr2WithoutAltExch); + + createQueueOnBroker(queue1); + createQueueOnBroker(queue2); + + ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1); + assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange()); + + ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2); + assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange()); + + String altExchange2 = nonMandatoryExchangeName; + managedQueue2.setAlternateExchange(altExchange2); + + restartBroker(); + + managedQueue1 = _jmxUtils.getManagedQueue(queueName1); + assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange()); + + managedQueue2 = _jmxUtils.getManagedQueue(queueName2); + assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange()); + } + + /** + * Tests the ability to receive queue alerts as JMX notifications. + * + * @see NotificationCheckTest + * @see SimpleAMQQueueTest#testNotificationFiredAsync() + * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue() + */ + public void testQueueNotification() throws Exception + { + final String queueName = getName(); + final long maximumMessageCount = 3; + + Queue queue = _session.createQueue(queueName); + createQueueOnBroker(queue); + + ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + managedQueue.setMaximumMessageCount(maximumMessageCount); + + RecordingNotificationListener listener = new RecordingNotificationListener(1); + + _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null); + + // Send two messages - this should *not* trigger the notification + sendMessage(_session, queue, 2); + + assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived()); + + // A further message should trigger the message count alert + sendMessage(_session, queue, 1); + + listener.awaitExpectedNotifications(5, TimeUnit.SECONDS); + + assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived()); + + Notification notification = listener.getLastNotification(); + assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage()); + } + + /** + * Tests {@link ManagedQueue#viewMessages(long, long)} interface. + */ + public void testViewSingleMessage() throws Exception + { + final List<Message> sentMessages = sendMessage(_session, _sourceQueue, 1); + syncSession(_session); + final Message sentMessage = sentMessages.get(0); + + assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue()); + + // Check the contents of the message + final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l); + assertEquals("Unexpected number of rows in table", 1, tab.size()); + final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator(); + + 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)); + + // Check the contents of header (encoded in a string array) + final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER); + assertNotNull("Expected message header array", headerArray); + final Map<String, String> headers = headerArrayToMap(headerArray); + + final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID(); + final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp()); + assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID")); + assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority")); + 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<Long> 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<Long> 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<Long> 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 predicted. 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<Long> 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()); + } + + /** + * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface. + */ + public void testMoveMessageBetweenQueuesWithBrokerRestart() throws Exception + { + final int numberOfMessagesToSend = 1; + + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + restartBroker(); + + createManagementInterfacesForQueues(); + createConnectionAndSession(); + + List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + // Move messages to destination + long messageId = amqMessagesIds.get(0); + _managedSourceQueue.moveMessages(messageId, messageId, _destinationQueueName); + + assertEquals("Unexpected queue depth on destination queue after move", 1, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after move", 0, _managedSourceQueue.getMessageCount().intValue()); + + assertMessageIndicesOn(_destinationQueue, 0); + } + + /** + * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface. + */ + public void testCopyMessageBetweenQueuesWithBrokerRestart() throws Exception + { + final int numberOfMessagesToSend = 1; + + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + restartBroker(); + + createManagementInterfacesForQueues(); + createConnectionAndSession(); + + List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + // Move messages to destination + long messageId = amqMessagesIds.get(0); + _managedSourceQueue.copyMessages(messageId, messageId, _destinationQueueName); + + assertEquals("Unexpected queue depth on destination queue after copy", 1, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after copy", 1, _managedSourceQueue.getMessageCount().intValue()); + + assertMessageIndicesOn(_destinationQueue, 0); + } + + /** + * Tests {@link ManagedQueue#deleteMessages(long, long)} interface. + */ + public void testDeleteMessages() throws Exception + { + final int numberOfMessagesToSend = 15; + + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + // Current expected queue state, in terms of message header indices: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] + + // Delete the first message (Remember the amqMessagesIds list, and the message indices added as a property when sending, are both 0-based index) + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = fromMessageId; + _managedSourceQueue.deleteMessages(fromMessageId, toMessageId); + assertEquals("Unexpected message count after first deletion", numberOfMessagesToSend - 1, _managedSourceQueue.getMessageCount().intValue()); + // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,7,8,9,10,11,12,13,14] + + // Delete the 9th-10th messages, in the middle of the queue + fromMessageId = amqMessagesIds.get(8); + toMessageId = amqMessagesIds.get(9); + _managedSourceQueue.deleteMessages(fromMessageId, toMessageId); + assertEquals("Unexpected message count after third deletion", numberOfMessagesToSend - 3, _managedSourceQueue.getMessageCount().intValue()); + // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,7,X,X,10,11,12,13,14] + + // Delete the 11th and 12th messages, but still include the IDs for the 9th and 10th messages in the + // range to ensure their IDs are 'skipped' until the matching messages are found + fromMessageId = amqMessagesIds.get(8); + toMessageId = amqMessagesIds.get(11); + _managedSourceQueue.deleteMessages(fromMessageId, toMessageId); + assertEquals("Unexpected message count after fourth deletion", numberOfMessagesToSend - 5, _managedSourceQueue.getMessageCount().intValue()); + // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,7,X,X,X,X,12,13,14] + + // Delete the 8th message and the 13th message, including the IDs for the 9th-12th messages in the + // range to ensure their IDs are 'skipped' and the other matching message is found + fromMessageId = amqMessagesIds.get(7); + toMessageId = amqMessagesIds.get(12); + _managedSourceQueue.deleteMessages(fromMessageId, toMessageId); + assertEquals("Unexpected message count after fourth deletion", numberOfMessagesToSend - 7, _managedSourceQueue.getMessageCount().intValue()); + // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,X,X,X,X,X,X,13,14] + + // Delete the last message message + fromMessageId = amqMessagesIds.get(numberOfMessagesToSend -1); + toMessageId = fromMessageId; + _managedSourceQueue.deleteMessages(fromMessageId, toMessageId); + assertEquals("Unexpected message count after second deletion", numberOfMessagesToSend - 8, _managedSourceQueue.getMessageCount().intValue()); + // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,X,X,X,X,X,X,13,X] + + // Verify the message indices with a consumer + assertMessageIndicesOn(_sourceQueue, 1,2,3,4,5,6,13); + } + + @Override + public Message createNextMessage(Session session, int messageNumber) throws JMSException + { + Message message = session.createTextMessage(getContentForMessageNumber(messageNumber)); + message.setIntProperty(INDEX, messageNumber); + return message; + } + + 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) + { + TextMessage message = (TextMessage)consumer.receive(1000); + assertNotNull("Expected message with index " + i, message); + assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX)); + assertEquals("Expected message content", getContentForMessageNumber(i), message.getText()); + } + + assertNull("Unexpected message encountered", consumer.receive(1000)); + } + + private List<Long> getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception + { + final SortedSet<Long> messageIds = new TreeSet<Long>(); + + final TabularData tab = managedQueue.viewMessages(startIndex, endIndex); + final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) 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<Long>(messageIds); + } + + /** + * + * Utility method to convert array of Strings in the form x = y into a + * map with key/value x => y. + * + */ + private Map<String,String> headerArrayToMap(final String[] headerArray) + { + final Map<String, String> headerMap = new HashMap<String, String>(); + final List<String> headerList = Arrays.asList(headerArray); + for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();) + { + final String nameValuePair = iterator.next(); + final String[] nameValue = nameValuePair.split(" *= *", 2); + headerMap.put(nameValue[0], nameValue[1]); + } + 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(); + } + + private void createConnectionAndSession() throws JMSException, + NamingException + { + _connection = getConnection(); + _connection.start(); + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + } + + private void createManagementInterfacesForQueues() + { + _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName); + _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName); + } + + private String getContentForMessageNumber(int msgCount) + { + return "Message count " + msgCount; + } + + private final class RecordingNotificationListener implements NotificationListener + { + private final CountDownLatch _notificationReceivedLatch; + private final AtomicInteger _numberOfNotifications; + private final AtomicReference<Notification> _lastNotification; + + private RecordingNotificationListener(int expectedNumberOfNotifications) + { + _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications); + _numberOfNotifications = new AtomicInteger(0); + _lastNotification = new AtomicReference<Notification>(); + } + + @Override + public void handleNotification(Notification notification, Object handback) + { + _lastNotification.set(notification); + _numberOfNotifications.incrementAndGet(); + _notificationReceivedLatch.countDown(); + } + + public int getNumberOfNotificationsReceived() + { + return _numberOfNotifications.get(); + } + + public Notification getLastNotification() + { + return _lastNotification.get(); + } + + public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException + { + _notificationReceivedLatch.await(timeout, timeunit); + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java new file mode 100644 index 0000000000..72fbd65acc --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.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.systest.management.jmx; + +import java.util.List; + +import javax.jms.Connection; +import javax.jms.MessageConsumer; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; +import org.apache.qpid.management.common.mbeans.ServerInformation; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class StatisticsTest extends QpidBrokerTestCase +{ + private static final String TEST_VIRTUALHOST1 = "test1"; + private static final String TEST_VIRTUALHOST2 = "test2"; + + private static final String TEST_USER = "admin"; + private static final String TEST_PASSWORD = "admin"; + private static final int MESSAGE_COUNT_TEST = 5; + private static final int MESSAGE_COUNT_DEV = 9; + + private JMXTestUtils _jmxUtils; + private Connection _vhost1Connection, _vhost2Connection; + private Session _vhost1Session, _vhost2Session; + private Queue _vhost1Queue, _vhost2Queue; + protected String _brokerUrl; + + @Override + public void setUp() throws Exception + { + createTestVirtualHost(0, TEST_VIRTUALHOST1); + createTestVirtualHost(0, TEST_VIRTUALHOST2); + + _jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD); + _jmxUtils.setUp(); + + super.setUp(); + + _brokerUrl = getBroker().toString(); + _vhost1Connection = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", TEST_VIRTUALHOST1); + _vhost2Connection = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", TEST_VIRTUALHOST2); + _vhost1Connection.start(); + _vhost2Connection.start(); + + _vhost1Session = _vhost1Connection.createSession(true, Session.SESSION_TRANSACTED); + _vhost2Session = _vhost2Connection.createSession(true, Session.SESSION_TRANSACTED); + + _vhost1Queue = _vhost2Session.createQueue(getTestQueueName()); + _vhost2Queue = _vhost1Session.createQueue(getTestQueueName()); + + //Create queues by opening and closing consumers + final MessageConsumer vhost1Consumer = _vhost1Session.createConsumer(_vhost2Queue); + vhost1Consumer.close(); + final MessageConsumer vhost2Consumer = _vhost2Session.createConsumer(_vhost1Queue); + vhost2Consumer.close(); + + _jmxUtils.open(); + } + + @Override + public void tearDown() throws Exception + { + _jmxUtils.close(); + + super.tearDown(); + } + + public void testInitialStatisticValues() throws Exception + { + //Check initial values + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, 0, 0, 0, 0); + checkVHostStatistics(TEST_VIRTUALHOST1, 0, 0, 0, 0); + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0); + checkVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0); + checkBrokerStatistics(0, 0, 0, 0); + } + + public void testSendOnSingleVHost() throws Exception + { + sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST); + + //Check values + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); + checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0); + checkVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0); + checkBrokerStatistics(MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); + } + + public void testSendOnTwoVHosts() throws Exception + { + sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST); + sendMessagesAndSync(_vhost2Session, _vhost1Queue, MESSAGE_COUNT_DEV); + + //Check values + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); + checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0); + checkVHostStatistics(TEST_VIRTUALHOST2, MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0); + checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, 0, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, 0); + } + + public void testSendAndConsumeOnSingleVHost() throws Exception + { + sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST); + consumeMessages(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST); + + //Check values + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); + checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0); + checkVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0); + checkBrokerStatistics(MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); + } + + public void testSendAndConsumeOnTwoVHosts() throws Exception + { + sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST); + sendMessagesAndSync(_vhost2Session, _vhost1Queue, MESSAGE_COUNT_DEV); + consumeMessages(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST); + consumeMessages(_vhost2Session, _vhost1Queue, MESSAGE_COUNT_DEV); + + //Check values + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); + checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); + checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE); + checkVHostStatistics(TEST_VIRTUALHOST2, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE); + checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE); + } + + private void sendMessagesAndSync(Session session, Queue queue, int numberOfMessages) throws Exception + { + //Send messages via connection on and sync + sendMessage(session, queue, numberOfMessages); + ((AMQSession<?,?>)session).sync(); + } + + private void consumeMessages(Session session, Queue queue, int numberOfMessages) throws Exception + { + //consume the messages on the virtual host + final MessageConsumer consumer = session.createConsumer(queue); + for (int i = 0 ; i < numberOfMessages ; i++) + { + assertNotNull("an expected message was not received", consumer.receive(1500)); + } + session.commit(); + consumer.close(); + } + + private void checkSingleConnectionOnVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) + { + List<ManagedConnection> managedConnections = _jmxUtils.getManagedConnections(vHostName); + assertEquals(1, managedConnections.size()); + + ManagedConnection managedConnection = managedConnections.get(0); + + assertEquals(messagesSent, managedConnection.getTotalMessagesReceived()); + assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered()); + + assertEquals(dataSent, managedConnection.getTotalDataReceived()); + assertEquals(dataReceived, managedConnection.getTotalDataDelivered()); + } + + private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) + { + ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName); + + assertEquals(messagesSent, vhost.getTotalMessagesReceived()); + assertEquals(messagesReceived, vhost.getTotalMessagesDelivered()); + + assertEquals(dataSent, vhost.getTotalDataReceived()); + assertEquals(dataReceived, vhost.getTotalDataDelivered()); + } + + private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived) + { + ServerInformation broker = _jmxUtils.getServerInformation(); + + assertEquals(messagesSent, broker.getTotalMessagesReceived()); + assertEquals(messagesReceived, broker.getTotalMessagesDelivered()); + + assertEquals(dataSent, broker.getTotalDataReceived()); + assertEquals(dataReceived, broker.getTotalDataDelivered()); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java new file mode 100644 index 0000000000..7eff1c89ee --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java @@ -0,0 +1,260 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.jmx; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.JMSException; + +import org.apache.qpid.management.common.mbeans.UserManagement; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory; +import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.tools.security.Passwd; + +/** + * System test for User Management. + * + */ +public class UserManagementTest extends QpidBrokerTestCase +{ + private static final String TEST_NEWPASSWORD = "newpassword"; + private static final String TEST_PASSWORD = "password"; + private JMXTestUtils _jmxUtils; + private String _testUserName; + private File _passwordFile; + private UserManagement _userManagement; + private Passwd _passwd; + + public void setUp() throws Exception + { + _passwd = createPasswordEncodingUtility(); + _passwordFile = createTemporaryPasswordFileWithJmxAdminUser(); + + Map<String, Object> newAttributes = new HashMap<String, Object>(); + newAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, getAuthenticationManagerType()); + newAttributes.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _passwordFile.getAbsolutePath()); + getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, newAttributes); + + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + + super.setUp(); + _jmxUtils.open(); + + _testUserName = getTestName() + System.currentTimeMillis(); + + _userManagement = _jmxUtils.getUserManagement(); + } + + + public void tearDown() throws Exception + { + try + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testCreateUser() throws Exception + { + final int initialNumberOfUsers = _userManagement.viewUsers().size(); + assertFileDoesNotContainsPasswordForUser(_testUserName); + + boolean success = _userManagement.createUser(_testUserName, TEST_PASSWORD); + assertTrue("Should have been able to create new user " + _testUserName, success); + assertEquals("Unexpected number of users after add", initialNumberOfUsers + 1, _userManagement.viewUsers().size()); + + assertFileContainsPasswordForUser(_testUserName); + } + + public void testJmsLoginForNewUser() throws Exception + { + assertJmsConnectionFails(_testUserName, TEST_PASSWORD); + testCreateUser(); + + assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD); + } + + public void testDeleteUser() throws Exception + { + final int initialNumberOfUsers = _userManagement.viewUsers().size(); + + testCreateUser(); + + boolean success = _userManagement.deleteUser(_testUserName); + assertTrue("Should have been able to delete new user " + _testUserName, success); + assertEquals("Unexpected number of users after delete", initialNumberOfUsers, _userManagement.viewUsers().size()); + assertFileDoesNotContainsPasswordForUser(_testUserName); + } + + public void testJmsLoginNotPossibleForDeletedUser() throws Exception + { + testDeleteUser(); + + assertJmsConnectionFails(_testUserName, TEST_PASSWORD); + } + + public void testSetPassword() throws Exception + { + testCreateUser(); + + _userManagement.setPassword(_testUserName, TEST_NEWPASSWORD); + + assertFileContainsPasswordForUser(_testUserName); + } + + public void testJmsLoginForPasswordChangedUser() throws Exception + { + testSetPassword(); + + assertJmsConnectionSucceeds(_testUserName, TEST_NEWPASSWORD); + assertJmsConnectionFails(_testUserName, TEST_PASSWORD); + } + + public void testReload() throws Exception + { + writePasswordFile(_passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD, _testUserName, TEST_PASSWORD); + + assertJmsConnectionFails(_testUserName, TEST_PASSWORD); + + _userManagement.reloadData(); + + assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD); + } + + protected Passwd createPasswordEncodingUtility() + { + return new Passwd() + { + @Override + public String getOutput(String username, String password) + { + return username + ":" + password; + } + }; + } + + protected String getAuthenticationManagerType() + { + return PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE; + } + + private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception + { + File passwordFile = File.createTempFile("passwd", "pwd"); + passwordFile.deleteOnExit(); + writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD); + return passwordFile; + } + + private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception + { + FileWriter writer = null; + try + { + writer = new FileWriter(passwordFile); + for (int i = 0; i < userNamePasswordPairs.length; i=i+2) + { + String username = userNamePasswordPairs[i]; + String password = userNamePasswordPairs[i+1]; + writer.append(_passwd.getOutput(username, password) + "\n"); + } + } + finally + { + writer.close(); + } + } + + + private void assertFileContainsPasswordForUser(String username) throws IOException + { + assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); + } + + private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException + { + assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); + } + + private boolean passwordFileContainsUser(String username) throws IOException + { + BufferedReader reader = null; + try + { + reader = new BufferedReader(new FileReader(_passwordFile)); + String line = reader.readLine(); + while(line != null) + { + if (line.startsWith(username)) + { + return true; + } + line = reader.readLine(); + } + + return false; + } + finally + { + reader.close(); + } + } + + private void assertJmsConnectionSucceeds(String username, String password) throws Exception + { + Connection connection = getConnection(username, password); + assertNotNull(connection); + } + + private void assertJmsConnectionFails(String username, String password) throws Exception + { + try + { + getConnection(username, password); + fail("Exception not thrown"); + } + catch (JMSException e) + { + // PASS + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java new file mode 100644 index 0000000000..1423bc557e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.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.systest.management.jmx; + +import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory; +import org.apache.qpid.tools.security.Passwd; + +public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest +{ + @Override + protected Passwd createPasswordEncodingUtility() + { + return new Passwd(); + } + + @Override + protected String getAuthenticationManagerType() + { + return Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java new file mode 100644 index 0000000000..16253139ce --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java @@ -0,0 +1,270 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; + +import javax.jms.JMSException; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; + +public class Asserts +{ + public static final String STATISTICS_ATTRIBUTE = "statistics"; + + public static void assertVirtualHost(String virtualHostName, Map<String, Object> virtualHost) + { + assertNotNull("Virtualhost " + virtualHostName + " data are not found", virtualHost); + assertAttributesPresent(virtualHost, VirtualHost.AVAILABLE_ATTRIBUTES, VirtualHost.TIME_TO_LIVE, + VirtualHost.CREATED, VirtualHost.UPDATED, VirtualHost.SUPPORTED_QUEUE_TYPES, VirtualHost.STORE_PATH, VirtualHost.CONFIG_PATH); + + assertEquals("Unexpected value of attribute " + VirtualHost.NAME, virtualHostName, virtualHost.get(VirtualHost.NAME)); + assertNotNull("Unexpected value of attribute " + VirtualHost.ID, virtualHost.get(VirtualHost.ID)); + assertEquals("Unexpected value of attribute " + VirtualHost.STATE, State.ACTIVE.name(), + virtualHost.get(VirtualHost.STATE)); + assertEquals("Unexpected value of attribute " + VirtualHost.DURABLE, Boolean.TRUE, + virtualHost.get(VirtualHost.DURABLE)); + assertEquals("Unexpected value of attribute " + VirtualHost.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), + virtualHost.get(VirtualHost.LIFETIME_POLICY)); + assertEquals("Unexpected value of attribute " + VirtualHost.DEAD_LETTER_QUEUE_ENABLED, Boolean.FALSE, + virtualHost.get(VirtualHost.DEAD_LETTER_QUEUE_ENABLED)); + + @SuppressWarnings("unchecked") + Collection<String> exchangeTypes = (Collection<String>) virtualHost.get(VirtualHost.SUPPORTED_EXCHANGE_TYPES); + assertEquals("Unexpected value of attribute " + VirtualHost.SUPPORTED_EXCHANGE_TYPES, + new HashSet<String>(Arrays.asList("headers", "topic", "direct", "fanout")), + new HashSet<String>(exchangeTypes)); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) virtualHost.get(STATISTICS_ATTRIBUTE); + Asserts.assertAttributesPresent(statistics, VirtualHost.AVAILABLE_STATISTICS, VirtualHost.BYTES_RETAINED, + VirtualHost.LOCAL_TRANSACTION_BEGINS, VirtualHost.LOCAL_TRANSACTION_ROLLBACKS, + VirtualHost.MESSAGES_RETAINED, VirtualHost.STATE_CHANGED, VirtualHost.XA_TRANSACTION_BRANCH_ENDS, + VirtualHost.XA_TRANSACTION_BRANCH_STARTS, VirtualHost.XA_TRANSACTION_BRANCH_SUSPENDS); + + } + + public static void assertQueue(String queueName, String queueType, Map<String, Object> queueData) + { + assertQueue(queueName, queueType, queueData, null); + } + + public static void assertQueue(String queueName, String queueType, Map<String, Object> queueData, Map<String, Object> expectedAttributes) + { + assertNotNull("Queue " + queueName + " is not found!", queueData); + Asserts.assertAttributesPresent(queueData, Queue.AVAILABLE_ATTRIBUTES, Queue.CREATED, Queue.UPDATED, + Queue.DESCRIPTION, Queue.TIME_TO_LIVE, Queue.ALTERNATE_EXCHANGE, Queue.OWNER, Queue.NO_LOCAL, Queue.LVQ_KEY, + Queue.SORT_KEY, Queue.MESSAGE_GROUP_KEY, Queue.MESSAGE_GROUP_DEFAULT_GROUP, + Queue.MESSAGE_GROUP_SHARED_GROUPS, Queue.PRIORITIES); + + assertEquals("Unexpected value of queue attribute " + Queue.NAME, queueName, queueData.get(Queue.NAME)); + assertNotNull("Unexpected value of queue attribute " + Queue.ID, queueData.get(Queue.ID)); + assertEquals("Unexpected value of queue attribute " + Queue.STATE, State.ACTIVE.name(), queueData.get(Queue.STATE)); + assertEquals("Unexpected value of queue attribute " + Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), + queueData.get(Queue.LIFETIME_POLICY)); + assertEquals("Unexpected value of queue attribute " + Queue.TYPE, queueType, queueData.get(Queue.TYPE)); + if (expectedAttributes == null) + { + assertEquals("Unexpected value of queue attribute " + Queue.EXCLUSIVE, Boolean.FALSE, queueData.get(Queue.EXCLUSIVE)); + assertEquals("Unexpected value of queue attribute " + Queue.MAXIMUM_DELIVERY_ATTEMPTS, 0, + queueData.get(Queue.MAXIMUM_DELIVERY_ATTEMPTS)); + assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 0, + queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES)); + assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 0, + queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES)); + assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_STOPPED, Boolean.FALSE, + queueData.get(Queue.QUEUE_FLOW_STOPPED)); + } + else + { + for (Map.Entry<String, Object> attribute : expectedAttributes.entrySet()) + { + assertEquals("Unexpected value of " + queueName + " queue attribute " + attribute.getKey(), + attribute.getValue(), queueData.get(attribute.getKey())); + } + } + + assertNotNull("Unexpected value of queue attribute statistics", queueData.get(Asserts.STATISTICS_ATTRIBUTE)); + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) queueData.get(Asserts.STATISTICS_ATTRIBUTE); + Asserts.assertAttributesPresent(statistics, Queue.AVAILABLE_STATISTICS, Queue.DISCARDS_TTL_BYTES, + Queue.DISCARDS_TTL_MESSAGES, Queue.STATE_CHANGED); + } + + public static void assertAttributesPresent(Map<String, Object> data, String[] attributes) + { + for (String name : attributes) + { + assertNotNull("Attribute " + name + " is not present", data.get(name)); + } + } + + public static void assertAttributesPresent(Map<String, Object> data, Collection<String> attributes, + String... unsupportedAttributes) + { + for (String name : attributes) + { + boolean unsupported = false; + for (String unsupportedAttribute : unsupportedAttributes) + { + if (unsupportedAttribute.equals(name)) + { + unsupported = true; + break; + } + } + if (unsupported) + { + continue; + } + assertNotNull("Attribute " + name + " is not present", data.get(name)); + } + } + + public static void assertConnection(Map<String, Object> connectionData, AMQConnection connection) throws JMSException + { + assertNotNull("Unexpected connection data", connectionData); + assertAttributesPresent(connectionData, Connection.AVAILABLE_ATTRIBUTES, Connection.STATE, Connection.DURABLE, + Connection.LIFETIME_POLICY, Connection.TIME_TO_LIVE, Connection.CREATED, Connection.UPDATED, + Connection.INCOMING, Connection.REMOTE_PROCESS_NAME, Connection.REMOTE_PROCESS_PID, + Connection.LOCAL_ADDRESS, Connection.PROPERTIES); + + assertEquals("Unexpected value of connection attribute " + Connection.SESSION_COUNT_LIMIT, + (int) connection.getMaximumChannelCount(), connectionData.get(Connection.SESSION_COUNT_LIMIT)); + assertEquals("Unexpected value of connection attribute " + Connection.CLIENT_ID, "clientid", + connectionData.get(Connection.CLIENT_ID)); + assertEquals("Unexpected value of connection attribute " + Connection.PRINCIPAL, "guest", + connectionData.get(Connection.PRINCIPAL)); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) connectionData.get(STATISTICS_ATTRIBUTE); + assertAttributesPresent(statistics, Connection.AVAILABLE_STATISTICS, Connection.LOCAL_TRANSACTION_BEGINS, + Connection.LOCAL_TRANSACTION_ROLLBACKS, Connection.STATE_CHANGED, Connection.XA_TRANSACTION_BRANCH_ENDS, + Connection.XA_TRANSACTION_BRANCH_STARTS, Connection.XA_TRANSACTION_BRANCH_SUSPENDS); + assertEquals("Unexpected value of connection statistics attribute " + Connection.SESSION_COUNT, 1, + statistics.get(Connection.SESSION_COUNT)); + } + + public static void assertPortAttributes(Map<String, Object> port) + { + + assertNotNull("Unexpected value of attribute " + Port.ID, port.get(Port.ID)); + assertEquals("Unexpected value of attribute " + Port.DURABLE, Boolean.FALSE, port.get(Port.DURABLE)); + assertEquals("Unexpected value of attribute " + Port.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), + port.get(Broker.LIFETIME_POLICY)); + assertEquals("Unexpected value of attribute " + Port.STATE, State.ACTIVE.name(), port.get(Port.STATE)); + assertEquals("Unexpected value of attribute " + Port.TIME_TO_LIVE, 0, port.get(Port.TIME_TO_LIVE)); + + @SuppressWarnings("unchecked") + Collection<String> protocols = (Collection<String>) port.get(Port.PROTOCOLS); + assertNotNull("Unexpected value of attribute " + Port.PROTOCOLS, protocols); + boolean isAMQPPort = false; + for (String protocolName : protocols) + { + if (Protocol.valueOf(protocolName).isAMQP()) + { + isAMQPPort = true; + break; + } + } + if (isAMQPPort) + { + assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_MANAGER); + assertNotNull("Unexpected value of attribute " + Port.BINDING_ADDRESS, port.get(Port.BINDING_ADDRESS)); + } + else + { + assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_MANAGER, + Port.BINDING_ADDRESS, Port.TCP_NO_DELAY, Port.SEND_BUFFER_SIZE, Port.RECEIVE_BUFFER_SIZE, + Port.NEED_CLIENT_AUTH, Port.WANT_CLIENT_AUTH); + } + + @SuppressWarnings("unchecked") + Collection<String> transports = (Collection<String>) port.get(Port.TRANSPORTS); + assertEquals("Unexpected value of attribute " + Port.TRANSPORTS, new HashSet<String>(Arrays.asList("TCP")), + new HashSet<String>(transports)); + } + + public static void assertDurableExchange(String exchangeName, String type, Map<String, Object> exchangeData) + { + assertExchange(exchangeName, type, exchangeData); + + assertEquals("Unexpected value of exchange attribute " + Exchange.DURABLE, Boolean.TRUE, + exchangeData.get(Exchange.DURABLE)); + } + + public static void assertExchange(String exchangeName, String type, Map<String, Object> exchangeData) + { + assertNotNull("Exchange " + exchangeName + " is not found!", exchangeData); + assertAttributesPresent(exchangeData, Exchange.AVAILABLE_ATTRIBUTES, Exchange.CREATED, Exchange.UPDATED, + Exchange.ALTERNATE_EXCHANGE, Exchange.TIME_TO_LIVE); + + assertEquals("Unexpected value of exchange attribute " + Exchange.NAME, exchangeName, + exchangeData.get(Exchange.NAME)); + assertNotNull("Unexpected value of exchange attribute " + Exchange.ID, exchangeData.get(VirtualHost.ID)); + assertEquals("Unexpected value of exchange attribute " + Exchange.STATE, State.ACTIVE.name(), + exchangeData.get(Exchange.STATE)); + + assertEquals("Unexpected value of exchange attribute " + Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), + exchangeData.get(Exchange.LIFETIME_POLICY)); + assertEquals("Unexpected value of exchange attribute " + Exchange.TYPE, type, exchangeData.get(Exchange.TYPE)); + assertNotNull("Unexpected value of exchange attribute statistics", exchangeData.get(STATISTICS_ATTRIBUTE)); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) exchangeData.get(STATISTICS_ATTRIBUTE); + assertAttributesPresent(statistics, Exchange.AVAILABLE_STATISTICS, Exchange.STATE_CHANGED, Exchange.PRODUCER_COUNT); + } + + public static void assertBinding(String bindingName, String queueName, String exchange, Map<String, Object> binding) + { + assertNotNull("Binding map should not be null", binding); + assertAttributesPresent(binding, Binding.AVAILABLE_ATTRIBUTES, Binding.STATE, Binding.TIME_TO_LIVE, + Binding.CREATED, Binding.UPDATED); + + assertEquals("Unexpected binding attribute " + Binding.NAME, bindingName, binding.get(Binding.NAME)); + assertEquals("Unexpected binding attribute " + Binding.QUEUE, queueName, binding.get(Binding.QUEUE)); + assertEquals("Unexpected binding attribute " + Binding.EXCHANGE, exchange, binding.get(Binding.EXCHANGE)); + assertEquals("Unexpected binding attribute " + Binding.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), + binding.get(Binding.LIFETIME_POLICY)); + } + + public static void assertBinding(String queueName, String exchange, Map<String, Object> binding) + { + assertBinding(queueName, queueName, exchange, binding); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java new file mode 100644 index 0000000000..a171b4459b --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.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.systest.rest; + +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.User; + +public class AuthenticationProviderRestTest extends QpidRestTestCase +{ + + public void testGet() throws Exception + { + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider"); + assertNotNull("Providers details cannot be null", providerDetails); + assertEquals("Unexpected number of providers", 1, providerDetails.size()); + for (Map<String, Object> provider : providerDetails) + { + assertProvider("PrincipalDatabaseAuthenticationManager", provider); + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/authenticationprovider/" + + provider.get(AuthenticationProvider.NAME)); + assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data); + assertProvider("PrincipalDatabaseAuthenticationManager", data); + } + } + + private void assertProvider(String type, Map<String, Object> provider) + { + Asserts.assertAttributesPresent(provider, AuthenticationProvider.AVAILABLE_ATTRIBUTES, + AuthenticationProvider.CREATED, AuthenticationProvider.UPDATED, AuthenticationProvider.DESCRIPTION, + AuthenticationProvider.TIME_TO_LIVE); + assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.STATE, State.ACTIVE.name(), + provider.get(AuthenticationProvider.STATE)); + assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.LIFETIME_POLICY, + LifetimePolicy.PERMANENT.name(), provider.get(AuthenticationProvider.LIFETIME_POLICY)); + assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.DURABLE, Boolean.TRUE, + provider.get(AuthenticationProvider.DURABLE)); + assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.TYPE, type, + provider.get(AuthenticationProvider.TYPE)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> users = (List<Map<String, Object>>) provider.get("users"); + assertNotNull("Users are not found", users); + assertTrue("Unexpected number of users", users.size() > 1); + for (Map<String, Object> user : users) + { + assertNotNull("Attribute " + User.ID, user.get(User.ID)); + assertNotNull("Attribute " + User.NAME, user.get(User.NAME)); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java new file mode 100644 index 0000000000..0574b6cc24 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java @@ -0,0 +1,121 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.Collections; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class BasicAuthRestTest extends QpidRestTestCase +{ + private static final String USERNAME = "admin"; + + @Override + public void setUp() throws Exception + { + setSystemProperty("javax.net.debug", "ssl"); + + //don't call super method, we will configure the broker in the test before doing so + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + //do nothing, we will configure this locally + } + + private void configure(boolean useSsl) throws ConfigurationException, IOException + { + getRestTestHelper().setUseSsl(useSsl); + if (useSsl) + { + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PROTOCOLS, Collections.singleton(Protocol.HTTPS)); + } + super.customizeConfiguration(); + } + + private void verifyGetBrokerAttempt(int responseCode) throws IOException + { + HttpURLConnection conn = getRestTestHelper().openManagementConnection("/rest/broker", "GET"); + assertEquals(responseCode, conn.getResponseCode()); + } + + public void testDefaultEnabledWithHttps() throws Exception + { + configure(true); + super.setUp(); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + + // Try the attempt with authentication, it should succeed because + // BASIC auth is enabled by default on secure connections. + getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME); + verifyGetBrokerAttempt(HttpServletResponse.SC_OK); + } + + public void testDefaultDisabledWithHttp() throws Exception + { + configure(false); + super.setUp(); + + // Try the attempt with authentication, it should fail because + // BASIC auth is disabled by default on non-secure connections. + getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME); + verifyGetBrokerAttempt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + public void testEnablingForHttp() throws Exception + { + configure(false); + + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true); + super.setUp(); + + // Try the attempt with authentication, it should succeed because + // BASIC auth is now enabled on non-secure connections. + getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME); + verifyGetBrokerAttempt(HttpServletResponse.SC_OK); + } + + public void testDisablingForHttps() throws Exception + { + configure(true); + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpsBasicAuthenticationEnabled", false); + super.setUp(); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + + // Try the attempt with authentication, it should fail because + // BASIC auth is now disabled on secure connections. + getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME); + verifyGetBrokerAttempt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java new file mode 100644 index 0000000000..372db8f560 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java @@ -0,0 +1,130 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.Binding; + +public class BindingRestTest extends QpidRestTestCase +{ + + public void testGetAllBindings() throws Exception + { + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding"); + assertNotNull("Bindings cannot be null", bindings); + assertTrue("Unexpected number of bindings: " + bindings.size(), + bindings.size() >= EXPECTED_VIRTUALHOSTS.length * EXPECTED_QUEUES.length); + for (Map<String, Object> binding : bindings) + { + Asserts.assertBinding((String) binding.get(Binding.NAME), (String) binding.get(Binding.EXCHANGE), binding); + } + } + + public void testGetVirtualHostBindings() throws Exception + { + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test"); + assertNotNull("Bindings cannot be null", bindings); + assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length * 2, bindings.size()); + for (String queueName : EXPECTED_QUEUES) + { + Map<String, Object> searchAttributes = new HashMap<String, Object>(); + searchAttributes.put(Binding.NAME, queueName); + searchAttributes.put(Binding.EXCHANGE, "amq.direct"); + + Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); + Asserts.assertBinding(queueName, "amq.direct", binding); + + searchAttributes.put(Binding.EXCHANGE, "<<default>>"); + + binding = getRestTestHelper().find(searchAttributes, bindings); + Asserts.assertBinding(queueName, "<<default>>", binding); + } + } + + public void testGetVirtualHostExchangeBindings() throws Exception + { + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct"); + assertNotNull("Bindings cannot be null", bindings); + assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size()); + for (String queueName : EXPECTED_QUEUES) + { + Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); + Asserts.assertBinding(queueName, "amq.direct", binding); + } + } + + public void testGetVirtualHostExchangeQueueBindings() throws Exception + { + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); + assertNotNull("Bindings cannot be null", bindings); + assertEquals("Unexpected number of bindings", 1, bindings.size()); + Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); + } + + + public void testDeleteBinding() throws Exception + { + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + assertEquals("Unexpected number of bindings", 1, bindings.size()); + Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + + bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + assertEquals("Binding should be deleted", 0, bindings.size()); + } + + public void testDeleteBindingById() throws Exception + { + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); + assertEquals("Binding should be deleted", 0, bindings.size()); + } + + public void testCreateBinding() throws Exception + { + String bindingName = getTestName(); + Map<String, Object> bindingData = new HashMap<String, Object>(); + bindingData.put(Binding.NAME, bindingName); + bindingData.put(Binding.QUEUE, "queue"); + bindingData.put(Binding.EXCHANGE, "amq.direct"); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); + connection.connect(); + getRestTestHelper().writeJsonRequest(connection, bindingData); + int responseCode = connection.getResponseCode(); + connection.disconnect(); + assertEquals("Unexpected response code", 201, responseCode); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); + + Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java new file mode 100644 index 0000000000..13e0c1e819 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.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.systest.rest; + +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class BrokerRestHttpsTest extends QpidRestTestCase +{ + @Override + public void setUp() throws Exception + { + setSystemProperty("javax.net.debug", "ssl"); + super.setUp(); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getRestTestHelper().setUseSsl(true); + Map<String, Object> newAttributes = new HashMap<String, Object>(); + newAttributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTPS)); + newAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT,newAttributes); + } + + public void testGetWithHttps() throws Exception + { + Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); + + Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, + Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, + Broker.ACL_FILE, Broker.KEY_STORE_CERT_ALIAS, Broker.TRUST_STORE_PATH, Broker.TRUST_STORE_PASSWORD, + Broker.GROUP_FILE); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java new file mode 100644 index 0000000000..d479d39287 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java @@ -0,0 +1,120 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class BrokerRestTest extends QpidRestTestCase +{ + + private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders"; + private static final String BROKER_PORTS_ATTRIBUTE = "ports"; + private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts"; + private static final String BROKER_STATISTICS_ATTRIBUTE = "statistics"; + + public void testGet() throws Exception + { + Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); + + assertBrokerAttributes(brokerDetails); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE); + Asserts.assertAttributesPresent(statistics, new String[]{ "bytesIn", "messagesOut", "bytesOut", "messagesIn" }); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE); + assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); + + Asserts.assertVirtualHost(TEST3_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST3_VIRTUALHOST, virtualhosts)); + Asserts.assertVirtualHost(TEST2_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST2_VIRTUALHOST, virtualhosts)); + Asserts.assertVirtualHost(TEST1_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST1_VIRTUALHOST, virtualhosts)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> ports = (List<Map<String, Object>>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE); + assertEquals("Unexpected number of ports", 4, ports.size()); + + for (Map<String, Object> port : ports) + { + Asserts.assertPortAttributes(port); + } + + Map<String, Object> amqpPort = getRestTestHelper().find(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, ports); + Map<String, Object> httpPort = getRestTestHelper().find(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, ports); + + assertEquals("Unexpected binding address", "*", amqpPort.get(Port.BINDING_ADDRESS)); + assertNotNull("Cannot find AMQP port", amqpPort); + assertNotNull("Cannot find HTTP port", httpPort); + + @SuppressWarnings("unchecked") + Collection<String> port1Protocols = (Collection<String>) amqpPort.get(Port.PROTOCOLS); + assertFalse("AMQP protocol list cannot contain HTTP", port1Protocols.contains("HTTP")); + + @SuppressWarnings("unchecked") + Collection<String> port2Protocols = (Collection<String>) httpPort.get(Port.PROTOCOLS); + assertEquals("Unexpected value of attribute " + Port.PROTOCOLS, new HashSet<String>(Arrays.asList("HTTP")), + new HashSet<String>(port2Protocols)); + } + + protected void assertBrokerAttributes(Map<String, Object> brokerDetails) + { + Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, + Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, + Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, Broker.ACL_FILE, + Broker.KEY_STORE_PATH, Broker.KEY_STORE_PASSWORD, Broker.KEY_STORE_CERT_ALIAS, + Broker.TRUST_STORE_PATH, Broker.TRUST_STORE_PASSWORD, Broker.GROUP_FILE); + + assertEquals("Unexpected value of attribute " + Broker.BUILD_VERSION, QpidProperties.getBuildVersion(), + brokerDetails.get(Broker.BUILD_VERSION)); + assertEquals("Unexpected value of attribute " + Broker.OPERATING_SYSTEM, System.getProperty("os.name") + " " + + System.getProperty("os.version") + " " + System.getProperty("os.arch"), + brokerDetails.get(Broker.OPERATING_SYSTEM)); + assertEquals( + "Unexpected value of attribute " + Broker.PLATFORM, + System.getProperty("java.vendor") + " " + + System.getProperty("java.runtime.version", System.getProperty("java.version")), + brokerDetails.get(Broker.PLATFORM)); + assertEquals("Unexpected value of attribute " + Broker.DURABLE, Boolean.TRUE, brokerDetails.get(Broker.DURABLE)); + assertEquals("Unexpected value of attribute " + Broker.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), + brokerDetails.get(Broker.LIFETIME_POLICY)); + assertEquals("Unexpected value of attribute " + Broker.NAME, "QpidBroker", brokerDetails.get(Broker.NAME)); + assertEquals("Unexpected value of attribute " + Broker.STATE, State.ACTIVE.name(), brokerDetails.get(Broker.STATE)); + + assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID)); + assertNotNull("Unexpected value of attribute statistics", brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE)); + assertNotNull("Unexpected value of attribute virtualhosts", brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE)); + assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE)); + assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE)); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java new file mode 100644 index 0000000000..05c8e362a1 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java @@ -0,0 +1,213 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.IOException; +import java.net.URLDecoder; +import java.util.List; +import java.util.Map; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Session; + +public class ConnectionRestTest extends QpidRestTestCase +{ + /** + * Message number to publish into queue + */ + private static final int MESSAGE_NUMBER = 5; + private static final int MESSAGE_SIZE = 6; + + private static final String SESSIONS_ATTRIBUTE = "sessions"; + + private javax.jms.Connection _connection; + private javax.jms.Session _session; + + public void setUp() throws Exception + { + super.setUp(); + + _connection = getConnection(); + _session = _connection.createSession(true, javax.jms.Session.SESSION_TRANSACTED); + String queueName = getTestQueueName(); + Destination queue = _session.createQueue(queueName); + MessageConsumer consumer = _session.createConsumer(queue); + MessageProducer producer = _session.createProducer(queue); + _connection.start(); + + // send messages + for (int i = 0; i < MESSAGE_NUMBER; i++) + { + producer.send(_session.createTextMessage("Test-" + i)); + } + _session.commit(); + + Message m = consumer.receive(1000l); + assertNotNull("Message was not received", m); + _session.commit(); + + // receive the rest of messages for rollback + for (int i = 0; i < MESSAGE_NUMBER - 1; i++) + { + m = consumer.receive(1000l); + assertNotNull("Message was not received", m); + } + _session.rollback(); + + // receive them again + for (int i = 0; i < MESSAGE_NUMBER - 1; i++) + { + m = consumer.receive(1000l); + assertNotNull("Message was not received", m); + } + } + + public void testGetAllConnections() throws Exception + { + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection"); + assertEquals("Unexpected number of connections", 1, connections.size()); + Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); + } + + public void testGetVirtualHostConnections() throws Exception + { + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection/test"); + assertEquals("Unexpected number of connections", 1, connections.size()); + Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); + } + + public void testGetConnectionByName() throws Exception + { + // get connection name + String connectionName = getConnectionName(); + + Map<String, Object> connectionDetails = getRestTestHelper().getJsonAsSingletonList("/rest/connection/test/" + + URLDecoder.decode(connectionName, "UTF-8")); + assertConnection(connectionDetails); + } + + public void testGetAllSessions() throws Exception + { + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session"); + assertEquals("Unexpected number of sessions", 1, sessions.size()); + assertSession(sessions.get(0), (AMQSession<?, ?>) _session); + } + + public void testGetVirtualHostSessions() throws Exception + { + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test"); + assertEquals("Unexpected number of sessions", 1, sessions.size()); + assertSession(sessions.get(0), (AMQSession<?, ?>) _session); + } + + public void testGetConnectionSessions() throws Exception + { + // get connection name + String connectionName = getConnectionName(); + + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + + URLDecoder.decode(connectionName, "UTF-8")); + assertEquals("Unexpected number of sessions", 1, sessions.size()); + assertSession(sessions.get(0), (AMQSession<?, ?>) _session); + } + + public void testGetSessionByName() throws Exception + { + // get connection name + String connectionName = getConnectionName(); + + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession<?, ?>) _session).getChannelId()); + assertEquals("Unexpected number of sessions", 1, sessions.size()); + assertSession(sessions.get(0), (AMQSession<?, ?>) _session); + } + + private void assertConnection(Map<String, Object> connectionDetails) throws JMSException + { + Asserts.assertConnection(connectionDetails, (AMQConnection) _connection); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) connectionDetails.get(Asserts.STATISTICS_ATTRIBUTE); + assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_IN, MESSAGE_NUMBER + * MESSAGE_SIZE, statistics.get(Connection.BYTES_IN)); + assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_OUT, MESSAGE_SIZE + + ((MESSAGE_NUMBER - 1) * MESSAGE_SIZE) * 2, statistics.get(Connection.BYTES_OUT)); + assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_IN, MESSAGE_NUMBER, + statistics.get(Connection.MESSAGES_IN)); + assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_OUT, + MESSAGE_NUMBER * 2 - 1, statistics.get(Connection.MESSAGES_OUT)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> sessions = (List<Map<String, Object>>) connectionDetails.get(SESSIONS_ATTRIBUTE); + assertNotNull("Sessions cannot be found", sessions); + assertEquals("Unexpected number of sessions", 1, sessions.size()); + assertSession(sessions.get(0), (AMQSession<?, ?>) _session); + } + + private void assertSession(Map<String, Object> sessionData, AMQSession<?, ?> session) + { + assertNotNull("Session map cannot be null", sessionData); + Asserts.assertAttributesPresent(sessionData, Session.AVAILABLE_ATTRIBUTES, Session.STATE, Session.DURABLE, + Session.LIFETIME_POLICY, Session.TIME_TO_LIVE, Session.CREATED, Session.UPDATED); + assertEquals("Unexpecte value of attribute " + Session.NAME, session.getChannelId() + "", + sessionData.get(Session.NAME)); + assertEquals("Unexpecte value of attribute " + Session.PRODUCER_FLOW_BLOCKED, Boolean.FALSE, + sessionData.get(Session.PRODUCER_FLOW_BLOCKED)); + assertEquals("Unexpecte value of attribute " + Session.CHANNEL_ID, session.getChannelId(), + sessionData.get(Session.CHANNEL_ID)); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) sessionData.get(Asserts.STATISTICS_ATTRIBUTE); + Asserts.assertAttributesPresent(statistics, Session.AVAILABLE_STATISTICS, Session.BYTES_IN, Session.BYTES_OUT, + Session.STATE_CHANGED, Session.UNACKNOWLEDGED_BYTES, Session.LOCAL_TRANSACTION_OPEN, + Session.XA_TRANSACTION_BRANCH_ENDS, Session.XA_TRANSACTION_BRANCH_STARTS, + Session.XA_TRANSACTION_BRANCH_SUSPENDS); + + assertEquals("Unexpecte value of statistic attribute " + Session.UNACKNOWLEDGED_MESSAGES, MESSAGE_NUMBER - 1, + statistics.get(Session.UNACKNOWLEDGED_MESSAGES)); + assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_BEGINS, 4, + statistics.get(Session.LOCAL_TRANSACTION_BEGINS)); + assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_ROLLBACKS, 1, + statistics.get(Session.LOCAL_TRANSACTION_ROLLBACKS)); + assertEquals("Unexpecte value of statistic attribute " + Session.CONSUMER_COUNT, 1, + statistics.get(Session.CONSUMER_COUNT)); + } + + private String getConnectionName() throws IOException + { + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + @SuppressWarnings("unchecked") + List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails + .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE); + assertEquals("Unexpected number of connections", 1, connections.size()); + Map<String, Object> connection = connections.get(0); + String connectionName = (String) connection.get(Connection.NAME); + return connectionName; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java new file mode 100644 index 0000000000..ec9791db13 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java @@ -0,0 +1,87 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.net.URLDecoder; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Exchange; + +public class ExchangeRestTest extends QpidRestTestCase +{ + public void testGet() throws Exception + { + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange"); + assertNotNull("Exchanges cannot be null", exchanges); + assertTrue("Unexpected number of exchanges", exchanges.size() >= EXPECTED_VIRTUALHOSTS.length * EXPECTED_EXCHANGES.length); + for (Map<String, Object> exchange : exchanges) + { + Asserts.assertExchange((String) exchange.get(Exchange.NAME), (String) exchange.get(Exchange.TYPE), exchange); + } + } + + public void testGetHostExchanges() throws Exception + { + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange/test"); + assertNotNull("Users cannot be null", exchanges); + assertEquals("Unexpected number of exchanges", exchanges.size(), EXPECTED_EXCHANGES.length); + for (String exchangeName : EXPECTED_EXCHANGES) + { + Map<String, Object> exchange = getRestTestHelper().find(Exchange.NAME, exchangeName, exchanges); + assertExchange(exchangeName, exchange); + } + } + + public void testGetHostExchangeByName() throws Exception + { + for (String exchangeName : EXPECTED_EXCHANGES) + { + Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + + URLDecoder.decode(exchangeName, "UTF-8")); + assertExchange(exchangeName, exchange); + } + } + + private void assertExchange(String exchangeName, Map<String, Object> exchange) + { + assertNotNull("Exchange with name " + exchangeName + " is not found", exchange); + String type = (String) exchange.get(Exchange.TYPE); + Asserts.assertExchange(exchangeName, type, exchange); + if ("direct".equals(type)) + { + assertBindings(exchange); + } + } + + private void assertBindings(Map<String, Object> exchange) + { + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); + for (String queueName : EXPECTED_QUEUES) + { + Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); + Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding); + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java new file mode 100644 index 0000000000..861bf8cb71 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java @@ -0,0 +1,160 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.UUIDGenerator; + +public class GroupProviderRestTest extends QpidRestTestCase +{ + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + public void testGet() throws Exception + { + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/groupprovider"); + assertNotNull("Providers details cannot be null", providerDetails); + assertEquals("Unexpected number of providers", 1, providerDetails.size()); + for (Map<String, Object> provider : providerDetails) + { + assertProvider(FILE_GROUP_MANAGER, provider); + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + + provider.get(GroupProvider.NAME)); + assertNotNull("Cannot load data for " + provider.get(GroupProvider.NAME), data); + assertProvider(FILE_GROUP_MANAGER, data); + } + } + + public void testCreateNewGroup() throws Exception + { + String groupName = "newGroup"; + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 1); + + getRestTestHelper().createGroup(groupName, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 2); + } + + public void testRemoveGroup() throws Exception + { + String groupName = "myGroup"; + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 1); + + getRestTestHelper().removeGroup(groupName, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 0); + } + + + private void assertProvider(String type, Map<String, Object> provider) + { + Asserts.assertAttributesPresent(provider, GroupProvider.AVAILABLE_ATTRIBUTES, + GroupProvider.CREATED, GroupProvider.UPDATED, GroupProvider.DESCRIPTION, + GroupProvider.TIME_TO_LIVE); + assertEquals("Unexpected value of provider attribute " + GroupProvider.STATE, State.ACTIVE.name(), + provider.get(GroupProvider.STATE)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.LIFETIME_POLICY, + LifetimePolicy.PERMANENT.name(), provider.get(GroupProvider.LIFETIME_POLICY)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.DURABLE, Boolean.TRUE, + provider.get(GroupProvider.DURABLE)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.TYPE, type, + provider.get(GroupProvider.TYPE)); + + final String name = (String) provider.get(GroupProvider.NAME); + assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, type, + name); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) provider.get("groups"); + assertNotNull("Groups were not found", groups); + assertEquals("Unexpected number of groups", 1, groups.size()); + for (Map<String, Object> group : groups) + { + + final String groupName = (String) group.get(Group.NAME); + assertNotNull("Attribute " + Group.NAME, groupName); + + assertNotNull("Attribute " + Group.ID, group.get(Group.ID)); + assertEquals("Attribute " + Group.ID, UUIDGenerator.generateGroupUUID(name, groupName).toString(), group.get(Group.ID)); + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put("myGroup.users", "guest"); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java new file mode 100644 index 0000000000..d3f93cc0fe --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupMember; + +public class GroupRestTest extends QpidRestTestCase +{ + private static final String GROUP_NAME = "myGroup"; + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private static final String EXISTING_MEMBER = "user1"; + private static final String NEW_MEMBER = "user2"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + public void testGet() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + List<Map<String, Object>> groupmembers = (List<Map<String, Object>>) group.get("groupmembers"); + assertEquals(1, groupmembers.size()); + + Map<String, Object> member1 = groupmembers.get(0); + assertEquals(EXISTING_MEMBER, (String)member1.get(GroupMember.NAME)); + } + + public void testCreateNewMemberOfGroup() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER); + + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 2); + } + + public void testRemoveMemberFromGroup() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, GROUP_NAME, EXISTING_MEMBER); + + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 0); + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(GROUP_NAME + ".users", EXISTING_MEMBER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java new file mode 100644 index 0000000000..a2f9d3189c --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.util.List; +import java.util.Map; + +public class LogRecordsRestTest extends QpidRestTestCase +{ + public void testGet() throws Exception + { + List<Map<String, Object>> logs = getRestTestHelper().getJsonAsList("/rest/logrecords"); + assertNotNull("Logs data cannot be null", logs); + assertTrue("Logs are not found", logs.size() > 0); + Map<String, Object> record = getRestTestHelper().find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs); + + assertNotNull("BRK-1004 message is not found", record); + assertNotNull("Message id cannot be null", record.get("id")); + assertNotNull("Message timestamp cannot be null", record.get("timestamp")); + assertEquals("Unexpected log level", "INFO", record.get("level")); + assertEquals("Unexpected thread", "main", record.get("thread")); + assertEquals("Unexpected logger", "qpid.message.broker.ready", record.get("logger")); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java new file mode 100644 index 0000000000..fb6bfca1d8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java @@ -0,0 +1,354 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +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.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; + +public class MessagesRestTest extends QpidRestTestCase +{ + + /** + * Message number to publish into queue + */ + private static final int MESSAGE_NUMBER = 12; + + private Connection _connection; + private Session _session; + private MessageProducer _producer; + private long _startTime; + private long _ttl; + + public void setUp() throws Exception + { + super.setUp(); + _startTime = System.currentTimeMillis(); + _connection = getConnection(); + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + String queueName = getTestQueueName(); + Destination queue = _session.createQueue(queueName); + _session.createConsumer(queue); + _producer = _session.createProducer(queue); + + _ttl = TimeUnit.DAYS.toMillis(1); + for (int i = 0; i < MESSAGE_NUMBER; i++) + { + Message m = _session.createTextMessage("Test-" + i); + m.setIntProperty("index", i); + if (i % 2 == 0) + { + _producer.send(m); + } + else + { + _producer.send(m, DeliveryMode.NON_PERSISTENT, 5, _ttl); + } + } + _session.commit(); + } + + public void testGet() throws Exception + { + String queueName = getTestQueueName(); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); + assertNotNull("Messages are not found", messages); + assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); + int position = 0; + for (Map<String, Object> message : messages) + { + assertMessage(position, message); + position++; + } + } + + public void testGetMessageContent() throws Exception + { + String queueName = getTestQueueName(); + + // add bytes message + BytesMessage byteMessage = _session.createBytesMessage(); + byte[] messageBytes = "Test".getBytes(); + byteMessage.writeBytes(messageBytes); + byteMessage.setStringProperty("test", "value"); + _producer.send(byteMessage); + _session.commit(); + + // get message IDs + List<Long> ids = getMesssageIds(queueName); + + Map<String, Object> message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0)); + assertMessageAttributes(message); + assertMessageAttributeValues(message, true); + + @SuppressWarnings("unchecked") + Map<String, Object> headers = (Map<String, Object>) message.get("headers"); + assertNotNull("Message headers are not found", headers); + assertEquals("Unexpected message header", 0, headers.get("index")); + + Long lastMessageId = ids.get(ids.size() - 1); + message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId); + assertMessageAttributes(message); + assertEquals("Unexpected message attribute mimeType", "application/octet-stream", message.get("mimeType")); + assertEquals("Unexpected message attribute size", 4, message.get("size")); + + @SuppressWarnings("unchecked") + Map<String, Object> bytesMessageHeader = (Map<String, Object>) message.get("headers"); + assertNotNull("Message headers are not found", bytesMessageHeader); + assertEquals("Unexpected message header", "value", bytesMessageHeader.get("test")); + + // get content + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message-content/test/" + queueName + "/" + + lastMessageId, "GET"); + connection.connect(); + byte[] data = getRestTestHelper().readConnectionInputStream(connection); + assertTrue("Unexpected message", Arrays.equals(messageBytes, data)); + + } + + public void testPostMoveMessages() throws Exception + { + String queueName = getTestQueueName(); + String queueName2 = queueName + "_2"; + Destination queue2 = _session.createQueue(queueName2); + _session.createConsumer(queue2); + + // get message IDs + List<Long> ids = getMesssageIds(queueName); + + // move half of the messages + int movedNumber = ids.size() / 2; + List<Long> movedMessageIds = new ArrayList<Long>(); + for (int i = 0; i < movedNumber; i++) + { + movedMessageIds.add(ids.remove(i)); + } + + // move messages + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST"); + + Map<String, Object> messagesData = new HashMap<String, Object>(); + messagesData.put("messages", movedMessageIds); + messagesData.put("destinationQueue", queueName2); + messagesData.put("move", Boolean.TRUE); + + getRestTestHelper().writeJsonRequest(connection, messagesData); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + + // check messages on target queue + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2); + assertNotNull("Messages are not found", messages); + assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size()); + for (Long id : movedMessageIds) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertMessageAttributes(message); + } + + // check messages on original queue + messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); + assertNotNull("Messages are not found", messages); + assertEquals("Unexpected number of messages", ids.size(), messages.size()); + for (Long id : ids) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertMessageAttributes(message); + } + for (Long id : movedMessageIds) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertNull("Moved message " + id + " is found on original queue", message); + } + } + + public void testPostCopyMessages() throws Exception + { + String queueName = getTestQueueName(); + String queueName2 = queueName + "_2"; + Destination queue2 = _session.createQueue(queueName2); + _session.createConsumer(queue2); + + // get message IDs + List<Long> ids = getMesssageIds(queueName); + + // copy half of the messages + int copyNumber = ids.size() / 2; + List<Long> copyMessageIds = new ArrayList<Long>(); + for (int i = 0; i < copyNumber; i++) + { + copyMessageIds.add(ids.remove(i)); + } + + // copy messages + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST"); + + Map<String, Object> messagesData = new HashMap<String, Object>(); + messagesData.put("messages", copyMessageIds); + messagesData.put("destinationQueue", queueName2); + + getRestTestHelper().writeJsonRequest(connection, messagesData); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + + // check messages on target queue + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2); + assertNotNull("Messages are not found", messages); + assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size()); + for (Long id : copyMessageIds) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertMessageAttributes(message); + } + + // check messages on original queue + messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); + assertNotNull("Messages are not found", messages); + assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); + for (Long id : ids) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertMessageAttributes(message); + } + for (Long id : copyMessageIds) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertMessageAttributes(message); + } + } + + public void testDeleteMessages() throws Exception + { + String queueName = getTestQueueName(); + + // get message IDs + List<Long> ids = getMesssageIds(queueName); + + // delete half of the messages + int deleteNumber = ids.size() / 2; + StringBuilder queryString = new StringBuilder(); + List<Long> deleteMessageIds = new ArrayList<Long>(); + for (int i = 0; i < deleteNumber; i++) + { + Long id = ids.remove(i); + deleteMessageIds.add(id); + if (queryString.length() > 0) + { + queryString.append("&"); + } + queryString.append("id=").append(id); + } + + // delete messages + HttpURLConnection connection = getRestTestHelper().openManagementConnection( + "/rest/message/test/" + queueName + "?" + queryString.toString(), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + + // check messages on queue + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); + assertNotNull("Messages are not found", messages); + assertEquals("Unexpected number of messages", ids.size(), messages.size()); + for (Long id : ids) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertMessageAttributes(message); + } + for (Long id : deleteMessageIds) + { + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); + assertNull("Message with id " + id + " was not deleted", message); + } + } + + private List<Long> getMesssageIds(String queueName) throws IOException, JsonParseException, JsonMappingException + { + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); + List<Long> ids = new ArrayList<Long>(); + for (Map<String, Object> message : messages) + { + ids.add(((Number) message.get("id")).longValue()); + } + return ids; + } + + private void assertMessage(int position, Map<String, Object> message) + { + assertMessageAttributes(message); + + assertEquals("Unexpected message attribute position", position, message.get("position")); + assertEquals("Unexpected message attribute size", position < 10 ? 6 : 7, message.get("size")); + boolean even = position % 2 == 0; + assertMessageAttributeValues(message, even); + } + + private void assertMessageAttributeValues(Map<String, Object> message, boolean even) + { + if (even) + { + assertEquals("Unexpected message attribute expirationTime", 0, message.get("expirationTime")); + assertEquals("Unexpected message attribute priority", 4, message.get("priority")); + assertEquals("Unexpected message attribute persistent", Boolean.TRUE, message.get("persistent")); + } + else + { + assertEquals("Unexpected message attribute expirationTime", ((Number) message.get("timestamp")).longValue() + + _ttl, message.get("expirationTime")); + assertEquals("Unexpected message attribute priority", 5, message.get("priority")); + assertEquals("Unexpected message attribute persistent", Boolean.FALSE, message.get("persistent")); + } + assertEquals("Unexpected message attribute mimeType", "text/plain", message.get("mimeType")); + assertEquals("Unexpected message attribute userId", "guest", message.get("userId")); + assertEquals("Unexpected message attribute deliveryCount", 0, message.get("deliveryCount")); + assertEquals("Unexpected message attribute state", "Available", message.get("state")); + } + + private void assertMessageAttributes(Map<String, Object> message) + { + assertNotNull("Message map cannot be null", message); + assertNotNull("Unexpected message attribute deliveryCount", message.get("deliveryCount")); + assertNotNull("Unexpected message attribute state", message.get("state")); + assertNotNull("Unexpected message attribute id", message.get("id")); + assertNotNull("Message arrivalTime cannot be null", message.get("arrivalTime")); + assertNotNull("Message timestamp cannot be null", message.get("timestamp")); + assertTrue("Message arrivalTime cannot be null", ((Number) message.get("arrivalTime")).longValue() > _startTime); + assertNotNull("Message messageId cannot be null", message.get("messageId")); + assertNotNull("Unexpected message attribute mimeType", message.get("mimeType")); + assertNotNull("Unexpected message attribute userId", message.get("userId")); + assertNotNull("Message priority cannot be null", message.get("priority")); + assertNotNull("Message expirationTime cannot be null", message.get("expirationTime")); + assertNotNull("Message persistent cannot be null", message.get("persistent")); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java new file mode 100644 index 0000000000..578565be05 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.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.systest.rest; + +import java.net.URLDecoder; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.Port; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class PortRestTest extends QpidRestTestCase +{ + public void testGet() throws Exception + { + List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/"); + assertNotNull("Port data cannot be null", ports); + assertEquals("Unexpected number of ports", 4, ports.size()); + + String httpPortName = TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT; + Map<String, Object> portData = getRestTestHelper().find(Port.NAME, httpPortName, ports); + assertNotNull("Http port " + httpPortName + " is not found", portData); + Asserts.assertPortAttributes(portData); + + String amqpPortName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; + Map<String, Object> amqpPortData = getRestTestHelper().find(Port.NAME, amqpPortName, ports); + assertNotNull("Amqp port " + amqpPortName + " is not found", amqpPortData); + Asserts.assertPortAttributes(amqpPortData); + } + + public void testGetPort() throws Exception + { + List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/"); + assertNotNull("Ports data cannot be null", ports); + assertEquals("Unexpected number of ports", 4, ports.size()); + for (Map<String, Object> portMap : ports) + { + String portName = (String) portMap.get(Port.NAME); + assertNotNull("Port name attribute is not found", portName); + Map<String, Object> portData = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8")); + assertNotNull("Port " + portName + " is not found", portData); + Asserts.assertPortAttributes(portData); + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java new file mode 100644 index 0000000000..671bdd7eb8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java @@ -0,0 +1,84 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.IOException; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class QpidRestTestCase extends QpidBrokerTestCase +{ + public static final String TEST1_VIRTUALHOST = "test"; + public static final String TEST2_VIRTUALHOST = "test2"; + public static final String TEST3_VIRTUALHOST = "test3"; + + public static final String[] EXPECTED_VIRTUALHOSTS = { TEST1_VIRTUALHOST, TEST2_VIRTUALHOST, TEST3_VIRTUALHOST}; + public static final String[] EXPECTED_QUEUES = { "queue", "ping" }; + public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct","amq.topic","<<default>>" }; + + private RestTestHelper _restTestHelper = new RestTestHelper(findFreePort()); + + @Override + public void setUp() throws Exception + { + // Set up virtualhost config with queues and bindings to the amq.direct + for (String virtualhost : EXPECTED_VIRTUALHOSTS) + { + createTestVirtualHost(0, virtualhost); + for (String queue : EXPECTED_QUEUES) + { + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.exchange", "amq.direct"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.queue(-1).name", queue); + } + } + + customizeConfiguration(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + getRestTestHelper().tearDown(); + } + } + + protected void customizeConfiguration() throws ConfigurationException, IOException + { + TestBrokerConfiguration config = getBrokerConfiguration(); + config.addHttpManagementConfiguration(); + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PORT, _restTestHelper.getHttpPort()); + } + + public RestTestHelper getRestTestHelper() + { + return _restTestHelper; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java new file mode 100644 index 0000000000..1f441e7cbb --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java @@ -0,0 +1,225 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; + +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Consumer; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Queue; + +public class QueueRestTest extends QpidRestTestCase +{ + private static final String QUEUE_ATTRIBUTE_CONSUMERS = "consumers"; + private static final String QUEUE_ATTRIBUTE_BINDINGS = "bindings"; + + /** + * Message number to publish into queue + */ + private static final int MESSAGE_NUMBER = 2; + private static final int MESSAGE_PAYLOAD_SIZE = 6; + private static final int ENQUEUED_MESSAGES = 1; + private static final int DEQUEUED_MESSAGES = 1; + private static final int ENQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE; + private static final int DEQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE; + + private Connection _connection; + + public void setUp() throws Exception + { + super.setUp(); + _connection = getConnection(); + Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); + String queueName = getTestQueueName(); + Destination queue = session.createQueue(queueName); + MessageConsumer consumer = session.createConsumer(queue); + MessageProducer producer = session.createProducer(queue); + + for (int i = 0; i < MESSAGE_NUMBER; i++) + { + producer.send(session.createTextMessage("Test-" + i)); + } + session.commit(); + _connection.start(); + Message m = consumer.receive(1000l); + assertNotNull("Message is not received", m); + session.commit(); + } + + public void testGetVirtualHostQueues() throws Exception + { + String queueName = getTestQueueName(); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test"); + assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size()); + String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1]; + System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length); + expectedQueues[EXPECTED_QUEUES.length] = queueName; + + for (String name : expectedQueues) + { + Map<String, Object> queueDetails = getRestTestHelper().find(Queue.NAME, name, queues); + Asserts.assertQueue(name, "standard", queueDetails); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS); + assertNotNull("Queue bindings are not found", bindings); + assertEquals("Unexpected number of bindings", 2, bindings.size()); + + Map<String, Object> defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<<default>>", bindings); + Map<String, Object> directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings); + Asserts.assertBinding(name, "<<default>>", defaultExchangeBinding); + Asserts.assertBinding(name, "amq.direct", directExchangeBinding); + } + } + + public void testGetByName() throws Exception + { + String queueName = getTestQueueName(); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Asserts.assertQueue(queueName, "standard", queueDetails); + assertStatistics(queueDetails); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS); + assertNotNull("Queue bindings are not found", bindings); + assertEquals("Unexpected number of bindings", 2, bindings.size()); + + Map<String, Object> defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<<default>>", bindings); + Map<String, Object> directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings); + Asserts.assertBinding(queueName, "<<default>>", defaultExchangeBinding); + Asserts.assertBinding(queueName, "amq.direct", directExchangeBinding); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> consumers = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_CONSUMERS); + assertNotNull("Queue consumers are not found", consumers); + assertEquals("Unexpected number of consumers", 1, consumers.size()); + assertConsumer(consumers.get(0)); + } + + public void testPutCreateBinding() throws Exception + { + String queueName = getTestQueueName(); + String bindingName = queueName + 2; + String[] exchanges = { "amq.direct", "amq.fanout", "amq.topic", "amq.match", "<<default>>" }; + + for (int i = 0; i < exchanges.length; i++) + { + createBinding(bindingName, exchanges[i], queueName); + } + + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Asserts.assertQueue(queueName, "standard", queueDetails); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS); + assertNotNull("Queue bindings are not found", bindings); + assertEquals("Unexpected number of bindings", exchanges.length + 2, bindings.size()); + + Map<String, Object> searchAttributes = new HashMap<String, Object>(); + searchAttributes.put(Binding.NAME, bindingName); + + for (int i = 0; i < exchanges.length; i++) + { + searchAttributes.put(Binding.EXCHANGE, exchanges[i]); + Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); + Asserts.assertBinding(bindingName, queueName, exchanges[i], binding); + } + } + + private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException + { + HttpURLConnection connection = getRestTestHelper().openManagementConnection( + "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName, + "PUT"); + + Map<String, Object> bindingData = new HashMap<String, Object>(); + bindingData.put(Binding.NAME, bindingName); + bindingData.put(Binding.EXCHANGE, exchangeName); + bindingData.put(Binding.QUEUE, queueName); + + getRestTestHelper().writeJsonRequest(connection, bindingData); + assertEquals("Unexpected response code", 201, connection.getResponseCode()); + + connection.disconnect(); + } + + private void assertConsumer(Map<String, Object> consumer) + { + assertNotNull("Consumer map should not be null", consumer); + Asserts.assertAttributesPresent(consumer, Consumer.AVAILABLE_ATTRIBUTES, Consumer.STATE, Consumer.TIME_TO_LIVE, + Consumer.CREATED, Consumer.UPDATED, Consumer.SETTLEMENT_MODE, Consumer.EXCLUSIVE, Consumer.SELECTOR, + Consumer.NO_LOCAL); + + assertEquals("Unexpected binding attribute " + Consumer.NAME, "1", consumer.get(Consumer.NAME)); + assertEquals("Unexpected binding attribute " + Consumer.DURABLE, Boolean.FALSE, consumer.get(Consumer.DURABLE)); + assertEquals("Unexpected binding attribute " + Consumer.LIFETIME_POLICY, LifetimePolicy.AUTO_DELETE.name(), + consumer.get(Consumer.LIFETIME_POLICY)); + assertEquals("Unexpected binding attribute " + Consumer.DISTRIBUTION_MODE, "MOVE", + consumer.get(Consumer.DISTRIBUTION_MODE)); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) consumer.get(Asserts.STATISTICS_ATTRIBUTE); + assertNotNull("Consumer statistics is not present", statistics); + Asserts.assertAttributesPresent(statistics, Consumer.AVAILABLE_STATISTICS, Consumer.STATE_CHANGED); + } + + private void assertStatistics(Map<String, Object> queueDetails) + { + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) queueDetails.get(Asserts.STATISTICS_ATTRIBUTE); + assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES, + statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES)); + assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_MESSAGES, ENQUEUED_MESSAGES, + statistics.get(Queue.QUEUE_DEPTH_MESSAGES)); + assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT, 1, + statistics.get(Queue.CONSUMER_COUNT)); + assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT_WITH_CREDIT, 1, + statistics.get(Queue.CONSUMER_COUNT_WITH_CREDIT)); + assertEquals("Unexpected queue statistics attribute " + Queue.BINDING_COUNT, 2, statistics.get(Queue.BINDING_COUNT)); + assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES, + statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES)); + assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES, + statistics.get(Queue.TOTAL_DEQUEUED_MESSAGES)); + assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_BYTES, DEQUEUED_BYTES, + statistics.get(Queue.TOTAL_DEQUEUED_BYTES)); + assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_BYTES, DEQUEUED_BYTES, + statistics.get(Queue.TOTAL_DEQUEUED_BYTES)); + assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_ENQUEUED_BYTES, ENQUEUED_BYTES + + DEQUEUED_BYTES, statistics.get(Queue.PERSISTENT_ENQUEUED_BYTES)); + assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_ENQUEUED_BYTES, ENQUEUED_BYTES + DEQUEUED_BYTES, + statistics.get(Queue.TOTAL_ENQUEUED_BYTES)); + assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_BYTES, ENQUEUED_BYTES, + statistics.get(Queue.QUEUE_DEPTH_BYTES)); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java new file mode 100644 index 0000000000..0db1f7e50d --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -0,0 +1,452 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import javax.servlet.http.HttpServletResponse; + +import junit.framework.Assert; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory; +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; + +public class RestTestHelper +{ + private static final Logger LOGGER = Logger.getLogger(RestTestHelper.class); + + private int _httpPort; + + private boolean _useSsl; + + private String _username; + + private String _password; + + private File _passwdFile; + + public RestTestHelper(int httpPort) + { + _httpPort = httpPort; + } + + public int getHttpPort() + { + return _httpPort; + } + + private String getHostName() + { + return "localhost"; + } + + private String getProtocol() + { + return _useSsl ? "https" : "http"; + } + + public String getManagementURL() + { + return getProtocol() + "://" + getHostName() + ":" + getHttpPort(); + } + + public URL getManagementURL(String path) throws MalformedURLException + { + return new URL(getManagementURL() + path); + } + + public HttpURLConnection openManagementConnection(String path, String method) throws IOException + { + URL url = getManagementURL(path); + HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); + if(_useSsl) + { + try + { + // We have to use a SSLSocketFactory from a new SSLContext so that we don't re-use + // the JVM's defaults that may have been initialised in previous tests. + + SSLContext sslContext = SSLContextFactory.buildClientContext( + TRUSTSTORE, TRUSTSTORE_PASSWORD, + KeyStore.getDefaultType(), + TrustManagerFactory.getDefaultAlgorithm(), + null, null, null, null, null); + + SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + + ((HttpsURLConnection) httpCon).setSSLSocketFactory(sslSocketFactory); + } + catch (GeneralSecurityException e) + { + throw new RuntimeException(e); + } + } + + if(_username != null) + { + String encoded = new String(new Base64().encode((_username + ":" + _password).getBytes())); + httpCon.setRequestProperty("Authorization", "Basic " + encoded); + } + + httpCon.setDoOutput(true); + httpCon.setRequestMethod(method); + return httpCon; + } + + public List<Map<String, Object>> readJsonResponseAsList(HttpURLConnection connection) throws IOException, + JsonParseException, JsonMappingException + { + byte[] data = readConnectionInputStream(connection); + + ObjectMapper mapper = new ObjectMapper(); + + TypeReference<List<LinkedHashMap<String, Object>>> typeReference = new TypeReference<List<LinkedHashMap<String, Object>>>() + { + }; + List<Map<String, Object>> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); + return providedObject; + } + + public Map<String, Object> readJsonResponseAsMap(HttpURLConnection connection) throws IOException, + JsonParseException, JsonMappingException + { + byte[] data = readConnectionInputStream(connection); + + ObjectMapper mapper = new ObjectMapper(); + + TypeReference<LinkedHashMap<String, Object>> typeReference = new TypeReference<LinkedHashMap<String, Object>>() + { + }; + Map<String, Object> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); + return providedObject; + } + + public byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException + { + InputStream is = connection.getInputStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = -1; + while ((len = is.read(buffer)) != -1) + { + baos.write(buffer, 0, len); + } + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("RESPONSE:" + new String(baos.toByteArray())); + } + return baos.toByteArray(); + } + + public void writeJsonRequest(HttpURLConnection connection, Map<String, Object> data) throws JsonGenerationException, + JsonMappingException, IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(connection.getOutputStream(), data); + } + + public Map<String, Object> find(String name, Object value, List<Map<String, Object>> data) + { + for (Map<String, Object> map : data) + { + Object mapValue = map.get(name); + if (value.equals(mapValue)) + { + return map; + } + } + return null; + } + + public Map<String, Object> find(Map<String, Object> searchAttributes, List<Map<String, Object>> data) + { + for (Map<String, Object> map : data) + { + boolean equals = true; + for (Map.Entry<String, Object> entry : searchAttributes.entrySet()) + { + Object mapValue = map.get(entry.getKey()); + if (!entry.getValue().equals(mapValue)) + { + equals = false; + break; + } + } + if (equals) + { + return map; + } + } + return null; + } + + public Map<String, Object> getJsonAsSingletonList(String path) throws IOException + { + List<Map<String, Object>> response = getJsonAsList(path); + + Assert.assertNotNull("Response cannot be null", response); + Assert.assertEquals("Unexpected response", 1, response.size()); + return response.get(0); + } + + public List<Map<String, Object>> getJsonAsList(String path) throws IOException, JsonParseException, + JsonMappingException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + List<Map<String, Object>> response = readJsonResponseAsList(connection); + return response; + } + + public Map<String, Object> getJsonAsMap(String path) throws IOException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + Map<String, Object> response = readJsonResponseAsMap(connection); + return response; + } + + public void createNewGroupMember(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" + URLDecoder.decode(memberName, "UTF-8"), + "PUT"); + + Map<String, Object> groupMemberData = new HashMap<String, Object>(); + // TODO add type + writeJsonRequest(connection, groupMemberData); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void createNewGroupMember(String groupProviderName, String groupName, String memberName) throws IOException + { + createNewGroupMember(groupProviderName, groupName, memberName, HttpServletResponse.SC_CREATED); + } + + public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" + URLDecoder.decode(memberName, "UTF-8"), + "DELETE"); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName) throws IOException + { + removeMemberFromGroup(groupProviderName, groupName, memberName, HttpServletResponse.SC_OK); + } + + public void assertNumberOfGroupMembers(Map<String, Object> data, int expectedNumberOfGroupMembers) + { + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groupmembers"); + if (groups == null) + { + groups = Collections.emptyList(); + } + + Assert.assertEquals("Unexpected number of group members", expectedNumberOfGroupMembers, groups.size()); + } + + public void createGroup(String groupName, String groupProviderName) throws IOException + { + createGroup(groupName, groupProviderName, HttpServletResponse.SC_CREATED); + } + + public void createGroup(String groupName, String groupProviderName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"), + "PUT"); + + Map<String, Object> groupData = new HashMap<String, Object>(); + writeJsonRequest(connection, groupData); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void createOrUpdateUser(String username, String password) throws IOException + { + createOrUpdateUser(username, password, HttpServletResponse.SC_CREATED); + } + + public void createOrUpdateUser(String username, String password, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + username, "PUT"); + + Map<String, Object> data = new HashMap<String, Object>(); + data.put("password", password); + writeJsonRequest(connection, data); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void removeGroup(String groupName, String groupProviderName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"), + "DELETE"); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeGroup(String groupName, String groupProviderName) throws IOException + { + removeGroup(groupName, groupProviderName, HttpServletResponse.SC_OK); + } + + public void removeUserById(String id) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "?id=" + id, "DELETE"); + Assert.assertEquals("Unexpected response code", HttpServletResponse.SC_OK, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeUser(String username, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + username, "DELETE"); + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeUser(String username) throws IOException + { + removeUser(username, HttpServletResponse.SC_OK); + } + + public void assertNumberOfGroups(Map<String, Object> data, int expectedNumberOfGroups) + { + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups"); + if (groups == null) + { + groups = Collections.emptyList(); + } + Assert.assertEquals("Unexpected number of groups", expectedNumberOfGroups, groups.size()); + } + + public void setUseSsl(boolean useSsl) + { + _useSsl = useSsl; + } + + public void setUsernameAndPassword(String username, String password) + { + _username = username; + _password = password; + } + + /** + * Create password file that follows the convention username=password, which is deleted by {@link #tearDown()} + */ + public void configureTemporaryPasswordFile(QpidBrokerTestCase testCase, String... users) throws ConfigurationException, IOException + { + _passwdFile = createTemporaryPasswdFile(users); + + testCase.getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, + AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _passwdFile.getAbsolutePath()); + } + + public void tearDown() + { + if (_passwdFile != null) + { + if (_passwdFile.exists()) + { + _passwdFile.delete(); + } + } + } + + private File createTemporaryPasswdFile(String[] users) throws IOException + { + BufferedWriter writer = null; + try + { + File testFile = File.createTempFile(this.getClass().getName(),"tmp"); + testFile.deleteOnExit(); + + writer = new BufferedWriter(new FileWriter(testFile)); + for (int i = 0; i < users.length; i++) + { + String username = users[i]; + writer.write(username + ":" + username); + writer.newLine(); + } + + return testFile; + + } + finally + { + if (writer != null) + { + writer.close(); + } + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java new file mode 100644 index 0000000000..856fda9419 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java @@ -0,0 +1,435 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory; +import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.tools.security.Passwd; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; + +public class SaslRestTest extends QpidRestTestCase +{ + @Override + public void startBroker() + { + // prevent broker from starting in setUp + } + + public void startBrokerNow() throws Exception + { + super.startBroker(); + } + + public void testGetMechanismsWithBrokerPlainPasswordPrincipalDatabase() throws Exception + { + startBrokerNow(); + + Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/rest/sasl"); + assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms")); + + @SuppressWarnings("unchecked") + List<String> mechanisms = (List<String>) saslData.get("mechanisms"); + String[] expectedMechanisms = { "AMQPLAIN", "PLAIN", "CRAM-MD5" }; + for (String mechanism : expectedMechanisms) + { + assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism)); + } + assertNull("Unexpected user was returned", saslData.get("user")); + } + + public void testGetMechanismsWithBrokerBase64MD5FilePrincipalDatabase() throws Exception + { + configureBase64MD5FilePrincipalDatabase(); + startBrokerNow(); + + Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/rest/sasl"); + assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms")); + + @SuppressWarnings("unchecked") + List<String> mechanisms = (List<String>) saslData.get("mechanisms"); + String[] expectedMechanisms = { "CRAM-MD5-HEX", "CRAM-MD5-HASHED" }; + for (String mechanism : expectedMechanisms) + { + assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism)); + } + assertNull("Unexpected user was returned", saslData.get("user")); + } + + public void testPlainSaslAuthenticationForValidCredentials() throws Exception + { + startBrokerNow(); + + byte[] responseBytes = generatePlainClientResponse("admin", "admin"); + String responseData = Base64.encodeBase64String(responseBytes); + String parameters= "mechanism=PLAIN&response=" + responseData; + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST"); + OutputStream os = connection.getOutputStream(); + os.write(parameters.getBytes()); + os.flush(); + + int code = connection.getResponseCode(); + assertEquals("Unexpected response code", 200, code); + + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertEquals("Unexpected user", "admin", response2.get("user")); + } + + public void testPlainSaslAuthenticationForIncorrectPassword() throws Exception + { + startBrokerNow(); + + byte[] responseBytes = generatePlainClientResponse("admin", "incorrect"); + String responseData = Base64.encodeBase64String(responseBytes); + String parameters= "mechanism=PLAIN&response=" + responseData; + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST"); + OutputStream os = connection.getOutputStream(); + os.write(parameters.getBytes()); + os.flush(); + + int code = connection.getResponseCode(); + assertEquals("Unexpected response code", 403, code); + + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertNull("Unexpected user", response2.get("user")); + } + + public void testPlainSaslAuthenticationForNonExistingUser() throws Exception + { + startBrokerNow(); + + byte[] responseBytes = generatePlainClientResponse("nonexisting", "admin"); + String responseData = Base64.encodeBase64String(responseBytes); + String parameters= "mechanism=PLAIN&response=" + responseData; + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST"); + OutputStream os = connection.getOutputStream(); + os.write(parameters.getBytes()); + os.flush(); + + int code = connection.getResponseCode(); + assertEquals("Unexpected response code", 403, code); + + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertNull("Unexpected user", response2.get("user")); + } + + public void testCramMD5SaslAuthenticationForValidCredentials() throws Exception + { + startBrokerNow(); + + // request the challenge for CRAM-MD5 + HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5"); + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // authenticate user with correct credentials + int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5"); + assertEquals("Unexpected response code", 200, code); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertEquals("Unexpected user", "admin", response2.get("user")); + } + + public void testCramMD5SaslAuthenticationForIncorrectPassword() throws Exception + { + startBrokerNow(); + + // request the challenge for CRAM-MD5 + HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5"); + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // authenticate user with correct credentials + int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5"); + assertEquals("Unexpected response code", 403, code); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertNull("Unexpected user", response2.get("user")); + } + + public void testCramMD5SaslAuthenticationForNonExistingUser() throws Exception + { + startBrokerNow(); + + // request the challenge for CRAM-MD5 + HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5"); + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // authenticate user with correct credentials + int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5"); + assertEquals("Unexpected response code", 403, code); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertNull("Unexpected user", response2.get("user")); + } + + public void testCramMD5HexSaslAuthenticationForValidCredentials() throws Exception + { + configureBase64MD5FilePrincipalDatabase(); + startBrokerNow(); + + // request the challenge for CRAM-MD5-HEX + HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX"); + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // authenticate user with correct credentials + int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5-HEX"); + assertEquals("Unexpected response code", 200, code); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertEquals("Unexpected user", "admin", response2.get("user")); + } + + public void testCramMD5HexSaslAuthenticationForIncorrectPassword() throws Exception + { + configureBase64MD5FilePrincipalDatabase(); + startBrokerNow(); + + HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX"); + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // try to authenticate user with incorrect passowrd + int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5-HEX"); + assertEquals("Unexpected response code", 403, code); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertNull("Unexpected user", response2.get("user")); + } + + public void testCramMD5HexSaslAuthenticationForNonExistingUser() throws Exception + { + configureBase64MD5FilePrincipalDatabase(); + startBrokerNow(); + + HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX"); + List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); + + // try to authenticate non-existing user + int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5-HEX"); + assertEquals("Unexpected response code", 403, code); + + // request authenticated user details + connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET"); + applyCookiesToConnection(cookies, connection); + Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection); + assertNull("Unexpected user", response2.get("user")); + } + + private HttpURLConnection requestSasServerChallenge(String mechanism) throws IOException + { + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST"); + OutputStream os = connection.getOutputStream(); + os.write(("mechanism=" + mechanism).getBytes()); + os.flush(); + return connection; + } + + private int authenticateUser(HttpURLConnection requestChallengeConnection, String userName, String userPassword, String mechanism) + throws IOException, JsonParseException, JsonMappingException, Exception + { + // get the response + Map<String, Object> response = getRestTestHelper().readJsonResponseAsMap(requestChallengeConnection); + String challenge = (String) response.get("challenge"); + assertNotNull("Challenge is not found", challenge); + + // preserve cookies to have the same server session + List<String> cookies = requestChallengeConnection.getHeaderFields().get("Set-Cookie"); + + // generate the authentication response for the challenge received + byte[] challengeBytes = Base64.decodeBase64(challenge); + byte[] responseBytes = generateClientResponse(mechanism, userName, userPassword, challengeBytes); + String responseData = Base64.encodeBase64String(responseBytes); + String requestParameters = ("id=" + response.get("id") + "&response=" + responseData); + + // re-open connection + HttpURLConnection authenticateConnection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST"); + + // set cookies to use the same server session + applyCookiesToConnection(cookies, authenticateConnection); + OutputStream os = authenticateConnection.getOutputStream(); + os.write(requestParameters.getBytes()); + os.flush(); + return authenticateConnection.getResponseCode(); + } + + private byte[] generateClientResponse(String mechanism, String userName, String userPassword, byte[] challengeBytes) throws Exception + { + byte[] responseBytes = null; + if ("CRAM-MD5-HEX".equalsIgnoreCase(mechanism)) + { + responseBytes = generateCramMD5HexClientResponse(userName, userPassword, challengeBytes); + } + else if ("CRAM-MD5".equalsIgnoreCase(mechanism)) + { + responseBytes = generateCramMD5ClientResponse(userName, userPassword, challengeBytes); + } + else + { + throw new RuntimeException("Not implemented test mechanism " + mechanism); + } + return responseBytes; + } + + private void applyCookiesToConnection(List<String> cookies, HttpURLConnection connection) + { + for (String cookie : cookies) + { + connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]); + } + } + + private static byte SEPARATOR = 0; + + private byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception + { + byte[] password = userPassword.getBytes("UTF8"); + byte user[] = userName.getBytes("UTF8"); + byte response[] = new byte[password.length + user.length + 2 ]; + int size = 0; + response[size++] = SEPARATOR; + System.arraycopy(user, 0, response, size, user.length); + size += user.length; + response[size++] = SEPARATOR; + System.arraycopy(password, 0, response, size, password.length); + return response; + } + + private byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception + { + String macAlgorithm = "HmacMD5"; + byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8")); + byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8"); + Mac mac = Mac.getInstance(macAlgorithm); + mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm)); + final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); + String responseAsString = userName + " " + toHex(messageAuthenticationCode); + return responseAsString.getBytes(); + } + + private byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception + { + String macAlgorithm = "HmacMD5"; + Mac mac = Mac.getInstance(macAlgorithm); + mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm)); + final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); + String responseAsString = userName + " " + toHex(messageAuthenticationCode); + return responseAsString.getBytes(); + } + + private String toHex(byte[] data) + { + StringBuffer hash = new StringBuffer(); + for (int i = 0; i < data.length; i++) + { + String hex = Integer.toHexString(0xFF & data[i]); + if (hex.length() == 1) + { + hash.append('0'); + } + hash.append(hex); + } + return hash.toString(); + } + + private void configureBase64MD5FilePrincipalDatabase() throws IOException, ConfigurationException + { + // generate user password entry + String passwordFileEntry; + try + { + passwordFileEntry = new Passwd().getOutput("admin", "admin"); + } + catch (NoSuchAlgorithmException e) + { + throw new ConfigurationException(e); + } + + // store the entry in the file + File passwordFile = File.createTempFile("passwd", "pwd"); + passwordFile.deleteOnExit(); + + FileWriter writer = null; + try + { + writer = new FileWriter(passwordFile); + writer.write(passwordFileEntry); + } + finally + { + writer.close(); + } + + // configure broker to use Base64MD5PasswordFilePrincipalDatabase + Map<String, Object> newAttributes = new HashMap<String, Object>(); + newAttributes.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, passwordFile.getAbsolutePath()); + newAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, newAttributes); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java new file mode 100644 index 0000000000..427934fac2 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.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.systest.rest; + +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.Port; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class StructureRestTest extends QpidRestTestCase +{ + + public void testGet() throws Exception + { + Map<String, Object> structure = getRestTestHelper().getJsonAsMap("/rest/structure"); + assertNotNull("Structure data cannot be null", structure); + assertNode(structure, "QpidBroker"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) structure.get("virtualhosts"); + assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> ports = (List<Map<String, Object>>) structure.get("ports"); + assertEquals("Unexpected number of ports", 4, ports.size()); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> providers = (List<Map<String, Object>>) structure.get("authenticationproviders"); + assertEquals("Unexpected number of authentication providers", 1, providers.size()); + + for (String hostName : EXPECTED_VIRTUALHOSTS) + { + Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); + assertNotNull("Host " + hostName + " is not found ", host); + assertNode(host, hostName); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) host.get("queues"); + assertNotNull("Host " + hostName + " queues are not found ", queues); + for (String queueName : EXPECTED_QUEUES) + { + Map<String, Object> queue = getRestTestHelper().find("name", queueName, queues); + assertNotNull(hostName + " queue " + queueName + " is not found ", queue); + assertNode(queue, queueName); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) queue.get("bindings"); + assertNotNull(hostName + " queue " + queueName + " bindings are not found ", queues); + for (Map<String, Object> binding : bindings) + { + assertNode(binding, queueName); + } + } + + @SuppressWarnings("unchecked") + List<Map<String, Object>> exchanges = (List<Map<String, Object>>) host.get("exchanges"); + assertNotNull("Host " + hostName + " exchanges are not found ", exchanges); + for (String exchangeName : EXPECTED_EXCHANGES) + { + Map<String, Object> exchange = getRestTestHelper().find("name", exchangeName, exchanges); + assertNotNull("Exchange " + exchangeName + " is not found ", exchange); + assertNode(exchange, exchangeName); + if ("amq.direct".equalsIgnoreCase(exchangeName) || "<<default>>".equalsIgnoreCase(exchangeName)) + { + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); + assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings); + for (String queueName : EXPECTED_QUEUES) + { + Map<String, Object> binding = getRestTestHelper().find("name", queueName, bindings); + assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding); + assertNode(binding, queueName); + } + } + } + } + + + String httpPortName = TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT; + Map<String, Object> portData = getRestTestHelper().find(Port.NAME, httpPortName, ports); + assertNotNull("Http Port " + httpPortName + " is not found", portData); + assertNode(portData, httpPortName); + + String amqpPortName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; + Map<String, Object> amqpPortData = getRestTestHelper().find(Port.NAME, amqpPortName, ports); + assertNotNull("Amqp port " + amqpPortName + " is not found", amqpPortData); + assertNode(amqpPortData, amqpPortName); + } + + private void assertNode(Map<String, Object> node, String name) + { + assertEquals("Unexpected name", name, node.get("name")); + assertNotNull("Unexpected id", node.get("id")); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java new file mode 100644 index 0000000000..017467a8be --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.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.systest.rest; + +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.User; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class UserRestTest extends QpidRestTestCase +{ + @Override + public void setUp() throws Exception + { + getRestTestHelper().configureTemporaryPasswordFile(this, "user1", "user2"); + + super.setUp(); // do this last because it starts the broker, using the modified config + } + + public void testGet() throws Exception + { + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user"); + assertNotNull("Users cannot be null", users); + assertTrue("Unexpected number of users", users.size() > 1); + for (Map<String, Object> user : users) + { + assertUser(user); + } + } + + public void testGetUserByName() throws Exception + { + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user"); + assertNotNull("Users cannot be null", users); + assertTrue("Unexpected number of users", users.size() > 1); + for (Map<String, Object> user : users) + { + assertNotNull("Attribute " + User.ID, user.get(User.ID)); + String userName = (String) user.get(User.NAME); + assertNotNull("Attribute " + User.NAME, userName); + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName); + assertUser(userDetails); + assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); + } + } + + public void testPut() throws Exception + { + String userName = getTestName(); + getRestTestHelper().createOrUpdateUser(userName, "newPassword"); + + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName); + assertUser(userDetails); + assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); + } + + public void testDelete() throws Exception + { + String userName = getTestName(); + getRestTestHelper().createOrUpdateUser(userName, "newPassword"); + + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName); + String id = (String) userDetails.get(User.ID); + + getRestTestHelper().removeUserById(id); + + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName); + assertEquals("User should be deleted", 0, users.size()); + } + + private void assertUser(Map<String, Object> user) + { + assertNotNull("Attribute " + User.ID, user.get(User.ID)); + assertNotNull("Attribute " + User.NAME, user.get(User.NAME)); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java new file mode 100644 index 0000000000..fb2c941203 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java @@ -0,0 +1,576 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest; + +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jms.Session; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; + +public class VirtualHostRestTest extends QpidRestTestCase +{ + private static final String VIRTUALHOST_EXCHANGES_ATTRIBUTE = "exchanges"; + public static final String VIRTUALHOST_QUEUES_ATTRIBUTE = "queues"; + public static final String VIRTUALHOST_CONNECTIONS_ATTRIBUTE = "connections"; + + private AMQConnection _connection; + + public void testGet() throws Exception + { + List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/"); + assertNotNull("Hosts data cannot be null", hosts); + assertEquals("Unexpected number of hosts", EXPECTED_VIRTUALHOSTS.length, hosts.size()); + for (String hostName : EXPECTED_VIRTUALHOSTS) + { + Map<String, Object> host = getRestTestHelper().find("name", hostName, hosts); + Asserts.assertVirtualHost(hostName, host); + } + } + + public void testGetHost() throws Exception + { + // create AMQP connection to get connection JSON details + _connection = (AMQConnection) getConnection(); + _connection.createSession(true, Session.SESSION_TRANSACTED); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + Asserts.assertVirtualHost("test", hostDetails); + + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE); + assertEquals("Unexpected number of exchanges in statistics", EXPECTED_EXCHANGES.length, statistics.get(VirtualHost.EXCHANGE_COUNT)); + assertEquals("Unexpected number of queues in statistics", EXPECTED_QUEUES.length, statistics.get(VirtualHost.QUEUE_COUNT)); + assertEquals("Unexpected number of connections in statistics", 1, statistics.get(VirtualHost.CONNECTION_COUNT)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE); + assertEquals("Unexpected number of exchanges", EXPECTED_EXCHANGES.length, exchanges.size()); + Asserts.assertDurableExchange("amq.fanout", "fanout", getRestTestHelper().find(Exchange.NAME, "amq.fanout", exchanges)); + Asserts.assertDurableExchange("amq.topic", "topic", getRestTestHelper().find(Exchange.NAME, "amq.topic", exchanges)); + Asserts.assertDurableExchange("amq.direct", "direct", getRestTestHelper().find(Exchange.NAME, "amq.direct", exchanges)); + Asserts.assertDurableExchange("amq.match", "headers", getRestTestHelper().find(Exchange.NAME, "amq.match", exchanges)); + Asserts.assertDurableExchange("<<default>>", "direct", getRestTestHelper().find(Exchange.NAME, "<<default>>", exchanges)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE); + assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length, queues.size()); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, "queue", queues); + Map<String, Object> ping = getRestTestHelper().find(Queue.NAME, "ping", queues); + Asserts.assertQueue("queue", "standard", queue); + Asserts.assertQueue("ping", "standard", ping); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, ping.get(Queue.DURABLE)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails + .get(VIRTUALHOST_CONNECTIONS_ATTRIBUTE); + assertEquals("Unexpected number of connections", 1, connections.size()); + Asserts.assertConnection(connections.get(0), _connection); + } + + public void testPutCreateVirtualHostUsingStoreType() throws Exception + { + String hostName = getTestName(); + String storeType = getTestProfileMessageStoreType(); + String storeLocation = createHost(hostName, storeType, null); + try + { + // make sure that the host is saved in the broker store + restartBroker(); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName); + Asserts.assertVirtualHost(hostName, hostDetails); + assertEquals("Unexpected store type", storeType, hostDetails.get(VirtualHost.STORE_TYPE)); + + assertNewVirtualHost(hostDetails); + } + finally + { + if (storeLocation != null) + { + FileUtils.delete(new File(storeLocation), true); + } + } + } + + public void testPutCreateVirtualHostUsingConfigPath() throws Exception + { + String hostName = getTestName(); + File configFile = TestFileUtils.createTempFile(this, hostName + "-config.xml"); + String configPath = configFile.getAbsolutePath(); + String storeLocation = getStoreLocation(hostName); + createAndSaveVirtualHostConfiguration(hostName, configFile, storeLocation); + createHost(hostName, null, configPath); + try + { + // make sure that the host is saved in the broker store + restartBroker(); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName); + Asserts.assertVirtualHost(hostName, hostDetails); + assertEquals("Unexpected config path", configPath, hostDetails.get(VirtualHost.CONFIG_PATH)); + + assertNewVirtualHost(hostDetails); + } + finally + { + if (storeLocation != null) + { + FileUtils.delete(new File(storeLocation), true); + } + configFile.delete(); + } + } + + public void testDeleteHost() throws Exception + { + String hostToDelete = TEST3_VIRTUALHOST; + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostToDelete, "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + + // make sure that changes are saved in the broker store + restartBroker(); + + List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/" + hostToDelete); + assertEquals("Host should be deleted", 0, hosts.size()); + } + + public void testPutCreateQueue() throws Exception + { + String queueName = getTestQueueName(); + + createQueue(queueName + "-standard", "standard", null); + + Map<String, Object> sortedQueueAttributes = new HashMap<String, Object>(); + sortedQueueAttributes.put(Queue.SORT_KEY, "sortme"); + createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes); + + Map<String, Object> priorityQueueAttributes = new HashMap<String, Object>(); + priorityQueueAttributes.put(Queue.PRIORITIES, 10); + createQueue(queueName + "-priority", "priority", priorityQueueAttributes); + + Map<String, Object> lvqQueueAttributes = new HashMap<String, Object>(); + lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); + createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues); + Map<String, Object> sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues); + + Asserts.assertQueue(queueName + "-standard", "standard", standardQueue); + Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue); + Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue); + Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue); + + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, standardQueue.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, sortedQueue.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); + + assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY)); + assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY)); + assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES)); + } + + public void testPutCreateExchange() throws Exception + { + String exchangeName = getTestName(); + + createExchange(exchangeName + "-direct", "direct"); + createExchange(exchangeName + "-topic", "topic"); + createExchange(exchangeName + "-headers", "headers"); + createExchange(exchangeName + "-fanout", "fanout"); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); + Map<String, Object> directExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-direct" , exchanges); + Map<String, Object> topicExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-topic" , exchanges); + Map<String, Object> headersExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-headers" , exchanges); + Map<String, Object> fanoutExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-fanout" , exchanges); + + Asserts.assertDurableExchange(exchangeName + "-direct", "direct", directExchange); + Asserts.assertDurableExchange(exchangeName + "-topic", "topic", topicExchange); + Asserts.assertDurableExchange(exchangeName + "-headers", "headers", headersExchange); + Asserts.assertDurableExchange(exchangeName + "-fanout", "fanout", fanoutExchange); + + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, directExchange.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, topicExchange.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, headersExchange.get(Queue.DURABLE)); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, fanoutExchange.get(Queue.DURABLE)); + + } + + public void testPutCreateLVQWithoutKey() throws Exception + { + String queueName = getTestQueueName()+ "-lvq"; + createQueue(queueName, "lvq", null); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); + + Asserts.assertQueue(queueName , "lvq", lvqQueue); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); + assertEquals("Unexpected lvq key attribute", AMQQueueFactory.QPID_LVQ_KEY, lvqQueue.get(Queue.LVQ_KEY)); + } + + public void testPutCreateSortedQueueWithoutKey() throws Exception + { + String queueName = getTestQueueName() + "-sorted"; + int responseCode = tryCreateQueue(queueName, "sorted", null); + assertEquals("Unexpected response code", HttpServletResponse.SC_CONFLICT, responseCode); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> testQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); + + assertNull("Sorted queue without a key was created ", testQueue); + } + + public void testPutCreatePriorityQueueWithoutKey() throws Exception + { + String queueName = getTestQueueName()+ "-priority"; + createQueue(queueName, "priority", null); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); + + Asserts.assertQueue(queueName , "priority", priorityQueue); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE)); + assertEquals("Unexpected number of priorities", 10, priorityQueue.get(Queue.PRIORITIES)); + } + + public void testPutCreateStandardQueueWithoutType() throws Exception + { + String queueName = getTestQueueName(); + createQueue(queueName, null, null); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); + + Asserts.assertQueue(queueName , "standard", queue); + } + + public void testPutCreateQueueOfUnsupportedType() throws Exception + { + String queueName = getTestQueueName(); + int responseCode = tryCreateQueue(queueName, "unsupported", null); + assertEquals("Unexpected response code", HttpServletResponse.SC_CONFLICT, responseCode); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); + + assertNull("Queue of unsupported type was created", queue); + } + + public void testDeleteQueue() throws Exception + { + String queueName = getTestQueueName(); + createQueue(queueName, null, null); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); + assertEquals("Queue should be deleted", 0, queues.size()); + } + + public void testDeleteQueueById() throws Exception + { + String queueName = getTestQueueName(); + createQueue(queueName, null, null); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); + assertEquals("Queue should be deleted", 0, queues.size()); + } + + public void testDeleteExchange() throws Exception + { + String exchangeName = getTestName(); + createExchange(exchangeName, "direct"); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); + assertEquals("Exchange should be deleted", 0, queues.size()); + } + + public void testDeleteExchangeById() throws Exception + { + String exchangeName = getTestName(); + createExchange(exchangeName, "direct"); + Map<String, Object> echangeDetails = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); + assertEquals("Exchange should be deleted", 0, queues.size()); + } + + public void testPutCreateQueueWithAttributes() throws Exception + { + String queueName = getTestQueueName(); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(Queue.ALERT_REPEAT_GAP, 1000); + attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, 3600000); + attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1000000000); + attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 800); + attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 15); + attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 2000000000); + attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 1500000000); + + createQueue(queueName + "-standard", "standard", attributes); + + Map<String, Object> sortedQueueAttributes = new HashMap<String, Object>(); + sortedQueueAttributes.putAll(attributes); + sortedQueueAttributes.put(Queue.SORT_KEY, "sortme"); + createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes); + + Map<String, Object> priorityQueueAttributes = new HashMap<String, Object>(); + priorityQueueAttributes.putAll(attributes); + priorityQueueAttributes.put(Queue.PRIORITIES, 10); + createQueue(queueName + "-priority", "priority", priorityQueueAttributes); + + Map<String, Object> lvqQueueAttributes = new HashMap<String, Object>(); + lvqQueueAttributes.putAll(attributes); + lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); + createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + Map<String, Object> standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues); + Map<String, Object> sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues); + + attributes.put(Queue.DURABLE, Boolean.TRUE); + Asserts.assertQueue(queueName + "-standard", "standard", standardQueue, attributes); + Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue, attributes); + Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue, attributes); + Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue, attributes); + + assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY)); + assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY)); + assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES)); + } + + @SuppressWarnings("unchecked") + public void testCreateQueueWithDLQEnabled() throws Exception + { + String queueName = getTestQueueName(); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); + + //verify the starting state + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); + + assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName , queues)); + assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues)); + assertNull("exchange should not have already been present", getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges)); + + //create the queue + createQueue(queueName, "standard", attributes); + + //verify the new queue, as well as the DLQueue and DLExchange have been created + hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); + exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); + + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); + Map<String, Object> dlqQueue = getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues); + Map<String, Object> dlExchange = getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges); + assertNotNull("queue should not have been present", queue); + assertNotNull("queue should not have been present", dlqQueue); + assertNotNull("exchange should not have been present", dlExchange); + + //verify that the alternate exchange is set as expected on the new queue + Map<String, Object> queueAttributes = new HashMap<String, Object>(); + queueAttributes.put(Queue.ALTERNATE_EXCHANGE, queueName + "_DLE"); + + Asserts.assertQueue(queueName, "standard", queue, queueAttributes); + Asserts.assertQueue(queueName, "standard", queue, null); + } + + private void createExchange(String exchangeName, String exchangeType) throws IOException + { + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "PUT"); + + Map<String, Object> queueData = new HashMap<String, Object>(); + queueData.put(Exchange.NAME, exchangeName); + queueData.put(Exchange.DURABLE, Boolean.TRUE); + queueData.put(Exchange.TYPE, exchangeType); + + getRestTestHelper().writeJsonRequest(connection, queueData); + assertEquals("Unexpected response code", 201, connection.getResponseCode()); + + connection.disconnect(); + } + + private void createQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException, + JsonGenerationException, JsonMappingException + { + int responseCode = tryCreateQueue(queueName, queueType, attributes); + assertEquals("Unexpected response code", 201, responseCode); + } + + private int tryCreateQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException, + JsonGenerationException, JsonMappingException + { + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "PUT"); + + Map<String, Object> queueData = new HashMap<String, Object>(); + queueData.put(Queue.NAME, queueName); + queueData.put(Queue.DURABLE, Boolean.TRUE); + if (queueType != null) + { + queueData.put(Queue.TYPE, queueType); + } + if (attributes != null) + { + queueData.putAll(attributes); + } + + getRestTestHelper().writeJsonRequest(connection, queueData); + int responseCode = connection.getResponseCode(); + connection.disconnect(); + return responseCode; + } + + private String createHost(String hostName, String storeType, String configPath) throws IOException, JsonGenerationException, + JsonMappingException + { + String storePath = getStoreLocation(hostName); + int responseCode = tryCreateVirtualHost(hostName, storeType, storePath, configPath); + assertEquals("Unexpected response code", 201, responseCode); + return storePath; + } + + private String getStoreLocation(String hostName) + { + return new File(TMP_FOLDER, "store-" + hostName + "-" + System.currentTimeMillis()).getAbsolutePath(); + } + + private int tryCreateVirtualHost(String hostName, String storeType, String storePath, String configPath) throws IOException, + JsonGenerationException, JsonMappingException + { + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostName, "PUT"); + + Map<String, Object> hostData = new HashMap<String, Object>(); + hostData.put(VirtualHost.NAME, hostName); + if (storeType == null) + { + hostData.put(VirtualHost.CONFIG_PATH, configPath); + } + else + { + hostData.put(VirtualHost.STORE_PATH, storePath); + hostData.put(VirtualHost.STORE_TYPE, storeType); + } + + getRestTestHelper().writeJsonRequest(connection, hostData); + int responseCode = connection.getResponseCode(); + connection.disconnect(); + return responseCode; + } + + private XMLConfiguration createAndSaveVirtualHostConfiguration(String hostName, File configFile, String storeLocation) + throws ConfigurationException + { + XMLConfiguration testConfiguration = new XMLConfiguration(); + testConfiguration.setProperty("virtualhosts.virtualhost." + hostName + ".store.class", + getTestProfileMessageStoreClassName()); + testConfiguration.setProperty("virtualhosts.virtualhost." + hostName + ".store.environment-path", storeLocation); + testConfiguration.save(configFile); + return testConfiguration; + } + + private void assertNewVirtualHost(Map<String, Object> hostDetails) + { + @SuppressWarnings("unchecked") + Map<String, Object> statistics = (Map<String, Object>) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE); + assertEquals("Unexpected number of exchanges in statistics", EXPECTED_EXCHANGES.length, + statistics.get(VirtualHost.EXCHANGE_COUNT)); + assertEquals("Unexpected number of queues in statistics", 0, statistics.get(VirtualHost.QUEUE_COUNT)); + assertEquals("Unexpected number of connections in statistics", 0, statistics.get(VirtualHost.CONNECTION_COUNT)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE); + assertEquals("Unexpected number of exchanges", EXPECTED_EXCHANGES.length, exchanges.size()); + RestTestHelper restTestHelper = getRestTestHelper(); + Asserts.assertDurableExchange("amq.fanout", "fanout", restTestHelper.find(Exchange.NAME, "amq.fanout", exchanges)); + Asserts.assertDurableExchange("amq.topic", "topic", restTestHelper.find(Exchange.NAME, "amq.topic", exchanges)); + Asserts.assertDurableExchange("amq.direct", "direct", restTestHelper.find(Exchange.NAME, "amq.direct", exchanges)); + Asserts.assertDurableExchange("amq.match", "headers", restTestHelper.find(Exchange.NAME, "amq.match", exchanges)); + Asserts.assertDurableExchange("<<default>>", "direct", restTestHelper.find(Exchange.NAME, "<<default>>", exchanges)); + + assertNull("Unexpected queues", hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE)); + assertNull("Unexpected connections", hostDetails.get(VIRTUALHOST_CONNECTIONS_ATTRIBUTE)); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java new file mode 100644 index 0000000000..40ea723b1e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java @@ -0,0 +1,197 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest.acl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.apache.qpid.systest.rest.QpidRestTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class GroupRestACLTest extends QpidRestTestCase +{ + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + + private static final String ALLOWED_GROUP = "allowedGroup"; + private static final String DENIED_GROUP = "deniedGroup"; + private static final String OTHER_GROUP = "otherGroup"; + + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String OTHER_USER = "admin"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + + //DONT call super.setUp(), the tests will start the broker after configuring it + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(ALLOWED_GROUP + ".users", ALLOWED_USER); + props.put(DENIED_GROUP + ".users", DENIED_USER); + props.put(OTHER_GROUP + ".users", OTHER_USER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } + + public void testCreateGroup() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " CREATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().createGroup("newGroup", FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 4); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + getRestTestHelper().createGroup("anotherNewGroup", FILE_GROUP_MANAGER, HttpServletResponse.SC_FORBIDDEN); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 4); + } + + public void testDeleteGroup() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " DELETE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER, HttpServletResponse.SC_FORBIDDEN); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 2); + } + + public void testUpdateGroupAddMember() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember", HttpServletResponse.SC_FORBIDDEN); + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember"); + assertNumberOfGroupMembers(OTHER_GROUP, 2); + } + + public void testUpdateGroupDeleteMember() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER, HttpServletResponse.SC_FORBIDDEN); + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER); + assertNumberOfGroupMembers(OTHER_GROUP, 0); + } + + private void assertNumberOfGroupMembers(String groupName, int expectedNumberOfMembers) throws IOException + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/" + groupName); + getRestTestHelper().assertNumberOfGroupMembers(group, expectedNumberOfMembers); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java new file mode 100644 index 0000000000..12973113d8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.rest.acl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.apache.qpid.systest.rest.QpidRestTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; + +public class UserRestACLTest extends QpidRestTestCase +{ + private static final String ALLOWED_GROUP = "allowedGroup"; + private static final String DENIED_GROUP = "deniedGroup"; + private static final String OTHER_GROUP = "otherGroup"; + + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String OTHER_USER = "other"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + + getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER); + + //DONT call super.setUp(), the tests will start the broker after configuring it + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(ALLOWED_GROUP + ".users", ALLOWED_USER); + props.put(DENIED_GROUP + ".users", DENIED_USER); + props.put(OTHER_GROUP + ".users", OTHER_USER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } + + public void testAddUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE USER", + "ACL DENY-LOG " + DENIED_GROUP + " CREATE USER"); + + //Start the broker with the custom config + super.setUp(); + + String newUser = "newUser"; + String password = "password"; + + assertUserDoesNotExist(newUser); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + getRestTestHelper().createOrUpdateUser(newUser, password, HttpServletResponse.SC_FORBIDDEN); + assertUserDoesNotExist(newUser); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createOrUpdateUser(newUser, password); + assertUserExists(newUser); + } + + public void testDeleteUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE USER", + "ACL DENY-LOG " + DENIED_GROUP + " DELETE USER"); + + //Start the broker with the custom config + super.setUp(); + + assertUserExists(OTHER_USER); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + getRestTestHelper().removeUser(OTHER_USER, HttpServletResponse.SC_FORBIDDEN); + assertUserExists(OTHER_USER); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().removeUser(OTHER_USER); + assertUserDoesNotExist(OTHER_USER); + } + + public void testUpdateUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE USER", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE USER"); + + //Start the broker with the custom config + super.setUp(); + + String newPassword = "newPassword"; + + checkPassword(OTHER_USER, OTHER_USER, true); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_FORBIDDEN); + + checkPassword(OTHER_USER, newPassword, false); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_OK); // expect SC_OK rather than the default SC_CREATED + + checkPassword(OTHER_USER, newPassword, true); + checkPassword(OTHER_USER, OTHER_USER, false); + } + + private void checkPassword(String username, String password, boolean passwordExpectedToBeCorrect) throws IOException + { + getRestTestHelper().setUsernameAndPassword(username, password); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/user/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/", "GET"); + + boolean passwordIsCorrect = connection.getResponseCode() == HttpServletResponse.SC_OK; + + connection.disconnect(); + + assertEquals(passwordExpectedToBeCorrect, passwordIsCorrect); + } + + private void assertUserDoesNotExist(String newUser) throws JsonParseException, JsonMappingException, IOException + { + String path = "/rest/user/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + newUser; + List<Map<String, Object>> userDetailsList = getRestTestHelper().getJsonAsList(path); + assertTrue(userDetailsList.isEmpty()); + } + + private void assertUserExists(String username) throws IOException + { + String path = "/rest/user/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + username; + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList(path); + + assertEquals( + "User returned by " + path + " should have name=" + username + ". The returned JSON was: " + userDetails, + username, + userDetails.get("name")); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java index a53c3d3ee0..2ed3f356d3 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java @@ -40,19 +40,19 @@ import java.util.concurrent.atomic.AtomicBoolean; * Description: * * The problem that this test is exposing is that the dispatcher used to be capable - * of holding on to a message when stopped. This ment that when the rollback was + * of holding on to a message when stopped. This meant that when the rollback was * called and the dispatcher stopped it may have hold of a message. So after all * the local queues(preDeliveryQueue, SynchronousQueue, PostDeliveryTagQueue) * have been cleared the client still had a single message, the one the * dispatcher was holding on to. * * As a result the TxRollback operation would run and then release the dispatcher. - * Whilst the dispatcher would then proceed to reject the message it was holiding + * Whilst the dispatcher would then proceed to reject the message it was holding * the Broker would already have resent that message so the rejection would silently * fail. * - * And the client would receieve that single message 'early', depending on the - * number of messages already recevied when rollback was called. + * And the client would receive that single message 'early', depending on the + * number of messages already received when rollback was called. * * * Aims: @@ -78,7 +78,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * as expected. * * We are testing a race condition here but we can check through the log file if - * the race condition occured. However, performing that check will only validate + * the race condition occurred. However, performing that check will only validate * the problem exists and will not be suitable as part of a system test. * */ @@ -183,18 +183,8 @@ public class RollbackOrderTest extends QpidBrokerTestCase } } -// _consumer.close(); _connection.close(); assertFalse("Exceptions thrown during test run, Check Std.err.", failed.get()); } - - @Override public void tearDown() throws Exception - { - - drainQueue(_queue); - - super.tearDown(); - } - } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java index e1f93b975b..22a98b6f42 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java @@ -29,8 +29,6 @@ import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQSession_0_10; import org.apache.qpid.client.message.QpidMessageProperties; -import org.apache.qpid.client.messaging.address.Node.ExchangeNode; -import org.apache.qpid.client.messaging.address.Node.QueueNode; import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; import org.apache.qpid.messaging.Address; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -98,7 +96,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertFalse("Queue should not be created",( - (AMQSession_0_10)jmsSession).isQueueExist(dest, (QueueNode)dest.getSourceNode() ,true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest,false)); // create always ------------------------------------------- @@ -107,10 +105,10 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase cons = jmsSession.createConsumer(dest); assertTrue("Queue not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, true)); assertTrue("Queue not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", - dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs())); + dest.getAddressName(),dest.getAddressName(), dest.getNode().getDeclareArgs())); // create receiver ----------------------------------------- addr1 = "ADDR:testQueue2; { create: receiver }"; @@ -126,16 +124,16 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertFalse("Queue should not be created",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, false)); cons = jmsSession.createConsumer(dest); assertTrue("Queue not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, true)); assertTrue("Queue not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", - dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs())); + dest.getAddressName(),dest.getAddressName(), dest.getNode().getDeclareArgs())); // create never -------------------------------------------- addr1 = "ADDR:testQueue3; { create: never }"; @@ -161,7 +159,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertFalse("Queue should not be created",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, false)); // create sender ------------------------------------------ addr1 = "ADDR:testQueue3; { create: sender }"; @@ -177,14 +175,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "doesn't resolve to an exchange or a queue")); } assertFalse("Queue should not be created",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, false)); prod = jmsSession.createProducer(dest); assertTrue("Queue not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, true)); assertTrue("Queue not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", - dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs())); + dest.getAddressName(),dest.getAddressName(), dest.getNode().getDeclareArgs())); } @@ -221,7 +219,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase // Even if the consumer is closed the queue and the bindings should be intact. assertTrue("Queue not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, true)); assertTrue("Queue not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", @@ -326,7 +324,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertTrue("Exchange not created as expected",( - (AMQSession_0_10)jmsSession).isExchangeExist(dest, (ExchangeNode)dest.getTargetNode() , true)); + (AMQSession_0_10)jmsSession).isExchangeExist(dest,true)); // The existence of the queue is implicitly tested here assertTrue("Queue not bound as expected",( @@ -367,7 +365,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase public void checkQueueForBindings(Session jmsSession, AMQDestination dest,String headersBinding) throws Exception { assertTrue("Queue not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, true)); assertTrue("Queue not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", @@ -506,14 +504,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase MessageConsumer cons3 = jmsSession.createConsumer(dest3); assertTrue("Destination1 was not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest1,(QueueNode)dest1.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest1, true)); assertTrue("Destination1 was not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", dest1.getAddressName(),dest1.getAddressName(), null)); assertTrue("Destination2 was not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest2,(QueueNode)dest2.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest2,true)); assertTrue("Destination2 was not bound as expected",( (AMQSession_0_10)jmsSession).isQueueBound("", @@ -602,14 +600,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase cons.close(); // Using the ADDR method to create a more complicated queue - String addr = "ADDR:amq.direct/x512; {create: receiver, " + + String addr = "ADDR:amq.direct/x512; {" + "link : {name : 'MY.RESP.QUEUE', " + "x-declare : { auto-delete: true, exclusive: true, " + "arguments : {'qpid.max_size': 1000, 'qpid.policy_type': ring} } } }"; queue = ssn.createQueue(addr); - prod = ssn.createProducer(queue); cons = ssn.createConsumer(queue); + prod = ssn.createProducer(queue); assertTrue("MY.RESP.QUEUE was not created as expected",( (AMQSession_0_10)ssn).isQueueBound("amq.direct", "MY.RESP.QUEUE","x512", null)); @@ -677,8 +675,8 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase // Using the ADDR method to create a more complicated topic topic = ssn.createTopic(addr); - prod = ssn.createProducer(topic); cons = ssn.createConsumer(topic); + prod = ssn.createProducer(topic); assertTrue("The queue was not bound to vehicle exchange using bus as the binding key",( (AMQSession_0_10)ssn).isQueueBound("vehicles", @@ -778,7 +776,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase public void testSubscriptionForSameDestination() throws Exception { Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); - Destination dest = ssn.createTopic("ADDR:amq.topic/foo; {link:{durable:true}}"); + Destination dest = ssn.createTopic("ADDR:amq.topic/foo"); MessageConsumer consumer1 = ssn.createConsumer(dest); MessageConsumer consumer2 = ssn.createConsumer(dest); MessageProducer prod = ssn.createProducer(dest); @@ -840,7 +838,8 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "}"; // Using the ADDR method to create a more complicated topic - MessageConsumer cons = ssn.createConsumer(new AMQAnyDestination(addr)); + Topic topic = ssn.createTopic(addr); + MessageConsumer cons = ssn.createConsumer(topic); assertTrue("The queue was not bound to MRKT exchange using NYSE.# as the binding key",( (AMQSession_0_10)ssn).isQueueBound("MRKT", @@ -854,7 +853,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase (AMQSession_0_10)ssn).isQueueBound("MRKT", "my-topic","CNTL.#", null)); - MessageProducer prod = ssn.createProducer(ssn.createTopic(addr)); + MessageProducer prod = ssn.createProducer(topic); Message msg = ssn.createTextMessage("test"); msg.setStringProperty("qpid.subject", "NASDAQ.ABCD"); prod.send(msg); @@ -909,32 +908,31 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase { Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); + String bindingStr = "x-bindings:[{key:'NYSE.#'},{key:'NASDAQ.#'},{key:'CNTL.#'}]}}"; + Properties props = new Properties(); props.setProperty("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"); - props.setProperty("destination.address1", "ADDR:amq.topic"); - props.setProperty("destination.address2", "ADDR:amq.direct/test"); - String addrStr = "ADDR:amq.topic/test; {link:{name: my-topic," + - "x-bindings:[{key:'NYSE.#'},{key:'NASDAQ.#'},{key:'CNTL.#'}]}}"; - props.setProperty("destination.address3", addrStr); - props.setProperty("topic.address4", "hello.world"); - addrStr = "ADDR:my_queue; {create:always,link: {x-subscribes:{exclusive: true, arguments: {a:b,x:y}}}}"; + props.setProperty("destination.address1", "ADDR:amq.topic/test"); + props.setProperty("destination.address2", "ADDR:amq.topic/test; {node:{" + bindingStr); + props.setProperty("destination.address3", "ADDR:amq.topic/test; {link:{" + bindingStr); + String addrStr = "ADDR:my_queue; {create:always,link: {x-subscribes:{exclusive: true, arguments: {a:b,x:y}}}}"; props.setProperty("destination.address5", addrStr); Context ctx = new InitialContext(props); - for (int i=1; i < 5; i++) + for (int i=1; i < 4; i++) { Topic topic = (Topic) ctx.lookup("address"+i); - createDurableSubscriber(ctx,ssn,"address"+i,topic); + createDurableSubscriber(ctx,ssn,"address"+i,topic,"ADDR:amq.topic/test"); } Topic topic = ssn.createTopic("ADDR:news.us"); - createDurableSubscriber(ctx,ssn,"my-dest",topic); + createDurableSubscriber(ctx,ssn,"my-dest",topic,"ADDR:news.us"); Topic namedQueue = (Topic) ctx.lookup("address5"); try { - createDurableSubscriber(ctx,ssn,"my-queue",namedQueue); + createDurableSubscriber(ctx,ssn,"my-queue",namedQueue,"ADDR:amq.topic/test"); fail("Exception should be thrown. Durable subscribers cannot be created for Queues"); } catch(JMSException e) @@ -943,16 +941,74 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase e.getMessage()); } } - - private void createDurableSubscriber(Context ctx,Session ssn,String destName,Topic topic) throws Exception + + public void testDurableSubscription() throws Exception + { + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Topic topic = session.createTopic("ADDR:amq.topic/" + getTestQueueName()); + MessageProducer publisher = session.createProducer(topic); + MessageConsumer subscriber = session.createDurableSubscriber(topic, getTestQueueName()); + + TextMessage messageToSend = session.createTextMessage("Test0"); + publisher.send(messageToSend); + ((AMQSession<?,?>)session).sync(); + + Message receivedMessage = subscriber.receive(1000); + assertNotNull("Message has not been received", receivedMessage); + assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText()); + + subscriber.close(); + + messageToSend = session.createTextMessage("Test1"); + publisher.send(messageToSend); + ((AMQSession<?,?>)session).sync(); + + subscriber = session.createDurableSubscriber(topic, getTestQueueName()); + receivedMessage = subscriber.receive(1000); + assertNotNull("Message has not been received", receivedMessage); + assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText()); + } + + public void testDurableSubscriptionnWithSelector() throws Exception + { + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Topic topic = session.createTopic("ADDR:amq.topic/" + getTestQueueName()); + MessageProducer publisher = session.createProducer(topic); + MessageConsumer subscriber = session.createDurableSubscriber(topic, getTestQueueName(), "id=1", false); + + TextMessage messageToSend = session.createTextMessage("Test0"); + messageToSend.setIntProperty("id", 1); + publisher.send(messageToSend); + ((AMQSession<?,?>)session).sync(); + + Message receivedMessage = subscriber.receive(1000); + assertNotNull("Message has not been received", receivedMessage); + assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText()); + assertEquals("Unexpected id", 1, receivedMessage.getIntProperty("id")); + + subscriber.close(); + + messageToSend = session.createTextMessage("Test1"); + messageToSend.setIntProperty("id", 1); + publisher.send(messageToSend); + ((AMQSession<?,?>)session).sync(); + + subscriber = session.createDurableSubscriber(topic, getTestQueueName(), "id=1", false); + receivedMessage = subscriber.receive(1000); + assertNotNull("Message has not been received", receivedMessage); + assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText()); + assertEquals("Unexpected id", 1, receivedMessage.getIntProperty("id")); + } + + private void createDurableSubscriber(Context ctx,Session ssn,String destName,Topic topic, String producerAddr) throws Exception { MessageConsumer cons = ssn.createDurableSubscriber(topic, destName); - MessageProducer prod = ssn.createProducer(topic); + MessageProducer prod = ssn.createProducer(ssn.createTopic(producerAddr)); Message m = ssn.createTextMessage(destName); prod.send(m); Message msg = cons.receive(1000); - assertNotNull(msg); + assertNotNull("Message not received as expected when using Topic : " + topic,msg); assertEquals(destName,((TextMessage)msg).getText()); ssn.unsubscribe(destName); } @@ -977,7 +1033,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertFalse("Queue not deleted as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, false)); String addr2 = "ADDR:testQueue2;{create: always, delete: receiver}"; @@ -993,7 +1049,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertFalse("Queue not deleted as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + (AMQSession_0_10)jmsSession).isQueueExist(dest, false)); String addr3 = "ADDR:testQueue3;{create: always, delete: sender}"; @@ -1010,9 +1066,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } assertFalse("Queue not deleted as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); - - + (AMQSession_0_10)jmsSession).isQueueExist(dest, false)); } /** @@ -1094,7 +1148,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase MessageConsumer cons = ssn.createConsumer(ssn.createTopic("ADDR:amq.topic/test")); MessageProducer prod = ssn.createProducer(null); - Queue queue = ssn.createQueue("ADDR:amq.topic/test"); + Topic queue = ssn.createTopic("ADDR:amq.topic/test"); prod.send(queue,ssn.createTextMessage("A")); Message msg = cons.receive(1000); @@ -1307,4 +1361,62 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase assertNotNull("message should be re-received by consumer after rollback", receivedMessage); jmsSession.commit(); } + + /** + * Test Goals : + * + * 1. Verify that link bindings are created and destroyed after creating and closing a subscriber. + * 2. Verify that link bindings are created and destroyed after creating and closing a subscriber. + */ + public void testLinkBindingBehavior() throws Exception + { + Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); + String addr = "ADDR:my-queue; {create: always, " + + "link: " + + "{" + + "x-bindings: [{exchange : 'amq.direct', key : test}]," + + "}" + + "}"; + + AMQDestination dest = (AMQDestination)jmsSession.createQueue(addr); + MessageConsumer cons = jmsSession.createConsumer(dest); + AMQSession_0_10 ssn = (AMQSession_0_10)jmsSession; + + assertTrue("Queue not created as expected",ssn.isQueueExist(dest, true)); + assertTrue("Queue not bound as expected",ssn.isQueueBound("amq.direct","my-queue","test", null)); + + cons.close(); // closing consumer, link binding should be removed now. + assertTrue("Queue should still be there",ssn.isQueueExist(dest, true)); + assertFalse("Binding should not exist anymore",ssn.isQueueBound("amq.direct","my-queue","test", null)); + + MessageProducer prod = jmsSession.createProducer(dest); + assertTrue("Queue not bound as expected",ssn.isQueueBound("amq.direct","my-queue","test", null)); + prod.close(); + assertFalse("Binding should not exist anymore",ssn.isQueueBound("amq.direct","my-queue","test", null)); + } + + /** + * Test Goals : Verifies that the subscription queue created is as specified under link properties. + */ + public void testCustomizingSubscriptionQueue() throws Exception + { + Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); + String xDeclareArgs = "x-declare: { exclusive: false, auto-delete: false," + + "alternate-exchange: 'amq.fanout'," + + "arguments: {'qpid.max_size': 1000,'qpid.max_count': 100}" + + "}"; + + String addr = "ADDR:amq.topic/test; {link: {name:my-queue, durable:true," + xDeclareArgs + "}}"; + Destination dest = ssn.createTopic(addr); + MessageConsumer cons = ssn.createConsumer(dest); + + String verifyAddr = "ADDR:my-queue;{ node: {durable:true, " + xDeclareArgs + "}}"; + AMQDestination verifyDest = (AMQDestination)ssn.createQueue(verifyAddr); + ((AMQSession_0_10)ssn).isQueueExist(verifyDest, true); + + // Verify that the producer does not delete the subscription queue. + MessageProducer prod = ssn.createProducer(dest); + prod.close(); + ((AMQSession_0_10)ssn).isQueueExist(verifyDest, true); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java index b82c3756f2..2875e2c6b1 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java @@ -24,6 +24,7 @@ package org.apache.qpid.test.client.failover; import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQSession; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.test.utils.FailoverBaseCase; @@ -35,7 +36,6 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; -import javax.naming.NamingException; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -75,7 +75,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener failoverComplete = new CountDownLatch(1); } - protected void init(boolean transacted, int mode) throws JMSException, NamingException + private void init(boolean transacted, int mode) throws Exception { consumerSession = connection.createSession(transacted, mode); queue = consumerSession.createQueue(getName()+System.currentTimeMillis()); @@ -125,7 +125,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener } } - private void sendMessages(int startIndex,int endIndex, boolean transacted) throws JMSException + private void sendMessages(int startIndex,int endIndex, boolean transacted) throws Exception { _logger.debug("**************** Send (Start: " + startIndex + ", End:" + endIndex + ")***********************"); @@ -144,6 +144,10 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener { producerSession.commit(); } + else + { + ((AMQSession<?, ?>)producerSession).sync(); + } } public void testP2PFailover() throws Exception @@ -163,13 +167,13 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener { if (CLUSTERED) { - testP2PFailover(numMessages, false,true, false); + testP2PFailover(numMessages, false, true, false); } } public void testP2PFailoverTransacted() throws Exception { - testP2PFailover(numMessages, true,true, false); + testP2PFailover(numMessages, true,true, true); } public void testP2PFailoverTransactedWithMessagesLeftToConsumeAndProduce() throws Exception @@ -177,17 +181,16 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener // Currently the cluster does not support transactions that span a failover if (CLUSTERED) { - testP2PFailover(numMessages, false,false, false); + testP2PFailover(numMessages, false, false, false); } } - - private void testP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws JMSException, NamingException + private void testP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws Exception { init(transacted, Session.AUTO_ACKNOWLEDGE); runP2PFailover(totalMessages,consumeAll, produceAll , transacted); } - - protected void runP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws JMSException, NamingException + + private void runP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws Exception { int toProduce = totalMessages; @@ -254,7 +257,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener //evil ignore IE. } } - + public void testClientAckFailover() throws Exception { init(false, Session.CLIENT_ACKNOWLEDGE); diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java index 5b350d2d89..3cc15d5e9d 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java @@ -63,8 +63,7 @@ public class JMSDestinationTest extends QpidBrokerTestCase public void setUp() throws Exception { - //Ensure JMX management is enabled for MovedToQueue test - setConfigurationProperty("management.enabled", "true"); + getBrokerConfiguration().addJmxManagementConfiguration(); super.setUp(); 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..9bf7dbd62a 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,11 +54,9 @@ 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.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY)); - setConfigurationProperty("management.enabled", "false"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY)); - super.setUp(); //Set the syncWrite timeout to be just larger than the delay on the commitTran. diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java index 53f37cd915..8961574d1e 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java @@ -21,16 +21,23 @@ package org.apache.qpid.test.unit.basic; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - +import java.util.Collections; +import java.util.Map; +import javax.jms.Connection; import javax.jms.InvalidDestinationException; +import javax.jms.JMSException; +import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.jms.Session; import javax.jms.TextMessage; +import javax.jms.Topic; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.test.utils.QpidBrokerTestCase; public class InvalidDestinationTest extends QpidBrokerTestCase { @@ -48,21 +55,23 @@ public class InvalidDestinationTest extends QpidBrokerTestCase super.tearDown(); } - - public void testInvalidDestination() throws Exception { - Queue invalidDestination = new AMQQueue("amq.direct","unknownQ"); - AMQQueue validDestination = new AMQQueue("amq.direct","knownQ"); QueueSession queueSession = _connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + Queue invalidDestination = queueSession.createQueue("unknownQ"); + + Queue validDestination = queueSession.createQueue(getTestQueueName()); + // This is the only easy way to create and bind a queue from the API :-( queueSession.createConsumer(validDestination); + QueueSender sender; + TextMessage msg= queueSession.createTextMessage("Hello"); - QueueSender sender = queueSession.createSender(invalidDestination); - TextMessage msg = queueSession.createTextMessage("Hello"); try { + sender = queueSession.createSender(invalidDestination); + sender.send(msg); fail("Expected InvalidDestinationException"); } @@ -70,10 +79,8 @@ public class InvalidDestinationTest extends QpidBrokerTestCase { // pass } - sender.close(); sender = queueSession.createSender(null); - invalidDestination = new AMQQueue("amq.direct","unknownQ"); try { @@ -86,19 +93,79 @@ public class InvalidDestinationTest extends QpidBrokerTestCase } sender.send(validDestination,msg); sender.close(); - validDestination = new AMQQueue("amq.direct","knownQ"); sender = queueSession.createSender(validDestination); sender.send(msg); + } + /** + * Tests that specifying the {@value ClientProperties#VERIFY_QUEUE_ON_SEND} system property + * results in an exception when sending to an invalid queue destination. + */ + public void testInvalidDestinationOnMessageProducer() throws Exception + { + setTestSystemProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "true"); + final AMQConnection connection = (AMQConnection) getConnection(); + doInvalidDestinationOnMessageProducer(connection); + } + /** + * Tests that specifying the {@value ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND} + * connection URL option property results in an exception when sending to an + * invalid queue destination. + */ + public void testInvalidDestinationOnMessageProducerURL() throws Exception + { + Map<String, String> options = Collections.singletonMap(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND, "true"); + doInvalidDestinationOnMessageProducer(getConnectionWithOptions(options)); + } + private void doInvalidDestinationOnMessageProducer(Connection connection) throws JMSException + { + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - } + String invalidQueueName = getTestQueueName() + "UnknownQ"; + Queue invalidDestination = session.createQueue(invalidQueueName); + String validQueueName = getTestQueueName() + "KnownQ"; + Queue validDestination = session.createQueue(validQueueName); - public static junit.framework.Test suite() - { + // This is the only easy way to create and bind a queue from the API :-( + session.createConsumer(validDestination); + + MessageProducer sender; + TextMessage msg = session.createTextMessage("Hello"); + try + { + sender = session.createProducer(invalidDestination); + sender.send(msg); + fail("Expected InvalidDestinationException"); + } + catch (InvalidDestinationException ex) + { + // pass + } - return new junit.framework.TestSuite(InvalidDestinationTest.class); + sender = session.createProducer(null); + invalidDestination = new AMQQueue("amq.direct",invalidQueueName); + + try + { + sender.send(invalidDestination,msg); + fail("Expected InvalidDestinationException"); + } + catch (InvalidDestinationException ex) + { + // pass + } + sender.send(validDestination, msg); + sender.close(); + sender = session.createProducer(validDestination); + sender.send(msg); + + //Verify sending to an 'invalid' Topic doesn't throw an exception + String invalidTopic = getTestQueueName() + "UnknownT"; + Topic topic = session.createTopic(invalidTopic); + sender = session.createProducer(topic); + sender.send(msg); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java index 8577fb5b6a..4e9477f4b6 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java @@ -20,26 +20,59 @@ */ package org.apache.qpid.test.unit.client; +import java.io.IOException; + import org.apache.qpid.AMQException; +import org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.url.BindingURL; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Queue; import javax.jms.Session; -/** - * QPID-155 - * - * Test to validate that setting the respective qpid.declare_queues, - * qpid.declare_exchanges system properties functions as expected. - */ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase { - public void testQueueDeclare() throws Exception + private JMXTestUtils _jmxUtils; + + @Override + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + + super.setUp(); + _jmxUtils.open(); + } + + @Override + public void tearDown() throws Exception { - setSystemProperty("qpid.declare_queues", "false"); + try + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + } + finally + { + super.tearDown(); + } + } + + /* + * Tests to validate that setting the respective qpid.declare_queues, + * qpid.declare_exchanges system properties functions as expected. + */ + + public void testQueueNotDeclaredDuringConsumerCreation() throws Exception + { + setSystemProperty(ClientProperties.QPID_DECLARE_QUEUES_PROP_NAME, "false"); Connection connection = getConnection(); @@ -58,16 +91,16 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase } } - public void testExchangeDeclare() throws Exception + public void testExchangeNotDeclaredDuringConsumerCreation() throws Exception { - setSystemProperty("qpid.declare_exchanges", "false"); + setSystemProperty(ClientProperties.QPID_DECLARE_EXCHANGES_PROP_NAME, "false"); Connection connection = getConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - String EXCHANGE_TYPE = "test.direct"; - Queue queue = session.createQueue("direct://" + EXCHANGE_TYPE + "/queue/queue"); + String exchangeName = getTestQueueName(); + Queue queue = session.createQueue("direct://" + exchangeName + "/queue/queue"); try { @@ -78,6 +111,50 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase { checkExceptionErrorCode(e, AMQConstant.NOT_FOUND); } + + //verify the exchange was not declared + String exchangeObjectName = _jmxUtils.getExchangeObjectName("test", exchangeName); + assertFalse("exchange should not exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName)); + } + + /** + * Checks that setting {@value ClientProperties#QPID_DECLARE_EXCHANGES_PROP_NAME} false results in + * disabling implicit ExchangeDeclares during producer creation when using a {@link BindingURL} + */ + public void testExchangeNotDeclaredDuringProducerCreation() throws Exception + { + Connection connection = getConnection(); + Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + String exchangeName1 = getTestQueueName() + "1"; + + + Queue queue = session1.createQueue("direct://" + exchangeName1 + "/queue/queue"); + session1.createProducer(queue); + + //close the session to ensure any previous commands were fully processed by + //the broker before observing their effect + session1.close(); + + //verify the exchange was declared + String exchangeObjectName = _jmxUtils.getExchangeObjectName("test", exchangeName1); + assertTrue("exchange should exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName)); + + //Now disable the implicit exchange declares and try again + setSystemProperty(ClientProperties.QPID_DECLARE_EXCHANGES_PROP_NAME, "false"); + + Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + String exchangeName2 = getTestQueueName() + "2"; + + Queue queue2 = session2.createQueue("direct://" + exchangeName2 + "/queue/queue"); + session2.createProducer(queue2); + + //close the session to ensure any previous commands were fully processed by + //the broker before observing their effect + session2.close(); + + //verify the exchange was not declared + String exchangeObjectName2 = _jmxUtils.getExchangeObjectName("test", exchangeName2); + assertFalse("exchange should not exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName2)); } private void checkExceptionErrorCode(JMSException original, AMQConstant code) @@ -87,4 +164,71 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase assertTrue("Linked exception should be an AMQException", linked instanceof AMQException); assertEquals("Error code should be " + code.getCode(), code, ((AMQException) linked).getErrorCode()); } + + /* + * Tests to validate that the custom exchanges declared by the client during + * consumer and producer creation have the expected properties. + */ + + public void testPropertiesOfCustomExchangeDeclaredDuringProducerCreation() throws Exception + { + implTestPropertiesOfCustomExchange(true, false); + } + + public void testPropertiesOfCustomExchangeDeclaredDuringConsumerCreation() throws Exception + { + implTestPropertiesOfCustomExchange(false, true); + } + + private void implTestPropertiesOfCustomExchange(boolean createProducer, boolean createConsumer) throws Exception + { + Connection connection = getConnection(); + + Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + String exchangeName1 = getTestQueueName() + "1"; + String queueName1 = getTestQueueName() + "1"; + + Queue queue = session1.createQueue("direct://" + exchangeName1 + "/" + queueName1 + "/" + queueName1 + "?" + BindingURL.OPTION_EXCHANGE_AUTODELETE + "='true'"); + if(createProducer) + { + session1.createProducer(queue); + } + + if(createConsumer) + { + session1.createConsumer(queue); + } + session1.close(); + + //verify the exchange was declared to expectation + verifyDeclaredExchange(exchangeName1, true, false); + + Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + String exchangeName2 = getTestQueueName() + "2"; + String queueName2 = getTestQueueName() + "2"; + + Queue queue2 = session2.createQueue("direct://" + exchangeName2 + "/" + queueName2 + "/" + queueName2 + "?" + BindingURL.OPTION_EXCHANGE_DURABLE + "='true'"); + if(createProducer) + { + session2.createProducer(queue2); + } + + if(createConsumer) + { + session2.createConsumer(queue2); + } + session2.close(); + + //verify the exchange was declared to expectation + verifyDeclaredExchange(exchangeName2, false, true); + } + + private void verifyDeclaredExchange(String exchangeName, boolean isAutoDelete, boolean isDurable) throws IOException + { + String exchangeObjectName = _jmxUtils.getExchangeObjectName("test", exchangeName); + assertTrue("exchange should exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName)); + ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName); + assertEquals(isAutoDelete, exchange.isAutoDelete()); + assertEquals(isDurable,exchange.isDurable()); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java index bc1eead8b4..40db17f799 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java @@ -74,19 +74,20 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase public void setUp() throws Exception { //enable DLQ/maximumDeliveryCount support for all queues at the vhost level - setConfigurationProperty("virtualhosts.virtualhost.test.queues.maximumDeliveryCount", + setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.queues.maximumDeliveryCount", String.valueOf(MAX_DELIVERY_COUNT)); - setConfigurationProperty("virtualhosts.virtualhost.test.queues.deadLetterQueues", + setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.queues.deadLetterQueues", String.valueOf(true)); //Ensure management is on - setConfigurationProperty("management.enabled", "true"); - setConfigurationProperty("management.ssl.enabled", "false"); + getBrokerConfiguration().addJmxManagementConfiguration(); // Set client-side flag to allow the server to determine if messages // dead-lettered or requeued. - setTestClientSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, "server"); - + if (!isBroker010()) + { + setTestClientSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, "server"); + } super.setUp(); boolean durableSub = isDurSubTest(); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java deleted file mode 100644 index 1c9ee27b94..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java +++ /dev/null @@ -1,236 +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.client.channelclose; - -import junit.textui.TestRunner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Destination; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.TextMessage; -import java.util.ArrayList; -import java.util.List; - -/** - * Due to bizarre exception handling all sessions are closed if you get - * a channel close request and no exception listener is registered. - * <p/> - * JIRA issue IBTBLZ-10. - * <p/> - * Simulate by: - * <p/> - * 0. Create two sessions with no exception listener. - * 1. Publish message to queue/topic that does not exist (wrong routing key). - * 2. This will cause a channel close. - * 3. Since client does not have an exception listener, currently all sessions are - * closed. - */ -public class ChannelCloseOkTest extends QpidBrokerTestCase -{ - private AMQConnection _connection; - private Destination _destination1; - private Destination _destination2; - private Session _session1; - private Session _session2; - private final List<Message> _received1 = new ArrayList<Message>(); - private final List<Message> _received2 = new ArrayList<Message>(); - - private static final Logger _log = LoggerFactory.getLogger(ChannelCloseOkTest.class); - - protected void setUp() throws Exception - { - super.setUp(); - - _connection = (AMQConnection) getConnection("guest", "guest"); - - _destination1 = new AMQQueue(_connection, "q1", true); - _destination2 = new AMQQueue(_connection, "q2", true); - _session1 = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _session1.createConsumer(_destination1).setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _log.debug("consumer 1 got message [" + getTextMessage(message) + "]"); - synchronized (_received1) - { - _received1.add(message); - _received1.notify(); - } - } - }); - _session2 = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _session2.createConsumer(_destination2).setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _log.debug("consumer 2 got message [" + getTextMessage(message) + "]"); - synchronized (_received2) - { - _received2.add(message); - _received2.notify(); - } - } - }); - - _connection.start(); - } - - private String getTextMessage(Message message) - { - TextMessage tm = (TextMessage) message; - try - { - return tm.getText(); - } - catch (JMSException e) - { - return "oops " + e; - } - } - - protected void tearDown() throws Exception - { - closeConnection(); - super.tearDown(); - } - - public void closeConnection() throws JMSException - { - if (_connection != null) - { - _log.info(">>>>>>>>>>>>>>.. closing"); - _connection.close(); - } - } - - public void testWithoutExceptionListener() throws Exception - { - doTest(); - } - - public void testWithExceptionListener() throws Exception - { - _connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException jmsException) - { - _log.warn("onException - " + jmsException.getMessage()); - } - }); - - doTest(); - } - - public void doTest() throws Exception - { - // Check both sessions are ok. - sendAndWait(_session1, _destination1, "first", _received1, 1); - sendAndWait(_session2, _destination2, "second", _received2, 1); - assertEquals(1, _received1.size()); - assertEquals(1, _received2.size()); - - // Now send message to incorrect destination on session 1. - Destination destination = new AMQQueue(_connection, "incorrect"); - send(_session1, destination, "third"); // no point waiting as message will never be received. - - // Ensure both sessions are still ok. - // Send a bunch of messages as this give time for the sessions to be erroneously closed. - final int num = 300; - for (int i = 0; i < num; ++i) - { - send(_session1, _destination1, "" + i); - send(_session2, _destination2, "" + i); - } - - waitFor(_received1, num + 1); - waitFor(_received2, num + 1); - - // Note that the third message is never received as it is sent to an incorrect destination. - assertEquals(num + 1, _received1.size()); - assertEquals(num + 1, _received2.size()); - } - - private void sendAndWait(Session session, Destination destination, String message, List<Message> received, int count) - throws JMSException, InterruptedException - { - send(session, destination, message); - waitFor(received, count); - } - - private void send(Session session, Destination destination, String message) throws JMSException - { - _log.debug("sending message " + message); - MessageProducer producer1 = session.createProducer(destination); - producer1.send(session.createTextMessage(message)); - } - - private void waitFor(List<Message> received, int count) throws InterruptedException - { - long timeout = 20000; - - synchronized (received) - { - long start = System.currentTimeMillis(); - while (received.size() < count) - { - if (System.currentTimeMillis() - start > timeout) - { - fail("timeout expired waiting for messages"); - } - try - { - received.wait(timeout); - } - catch (InterruptedException e) - { - _log.info("Interrupted: " + e); - throw e; - } - - } - } - } - - private static String randomize(String in) - { - return in + System.currentTimeMillis(); - } - - public static void main(String[] args) - { - TestRunner.run(ChannelCloseOkTest.class); - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(ChannelCloseOkTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java deleted file mode 100644 index c20eefd987..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java +++ /dev/null @@ -1,399 +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.client.channelclose; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.failover.FailoverException; -import org.apache.qpid.client.protocol.AMQProtocolHandler; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.framing.ChannelOpenBody; -import org.apache.qpid.framing.ChannelOpenOkBody; -import org.apache.qpid.framing.ExchangeDeclareBody; -import org.apache.qpid.framing.ExchangeDeclareOkBody; -import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; - -public class ChannelCloseTest extends QpidBrokerTestCase implements ExceptionListener, ConnectionListener -{ - private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseTest.class); - - private Connection _connection; - private Session _session; - private static final long SYNC_TIMEOUT = 500; - private int TEST = 0; - - /** - * Close channel, use chanel with same id ensure error. - * - * This test is only valid for non 0-10 connection . - */ - public void testReusingChannelAfterFullClosure() throws Exception - { - _connection=newConnection(); - - // Create Producer - try - { - _connection.start(); - - createChannelAndTest(1); - - // Cause it to close - try - { - _logger.info("Testing invalid exchange"); - declareExchange(1, "", "name_that_will_lookup_to_null", false); - fail("Exchange name is empty so this should fail "); - } - catch (AMQException e) - { - assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode()); - } - - // Check that - try - { - _logger.info("Testing valid exchange should fail"); - declareExchange(1, "topic", "amq.topic", false); - fail("This should not succeed as the channel should be closed "); - } - catch (AMQException e) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Exception occured was:" + e.getErrorCode()); - } - - assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode()); - - _connection=newConnection(); - } - - checkSendingMessage(); - - _session.close(); - _connection.close(); - - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - } - - /* - close channel and send guff then send ok no errors - REMOVE TEST - The behaviour after server has sent close is undefined. - the server should be free to fail as it may wish to reclaim its resources - immediately after close. - */ - /*public void testSendingMethodsAfterClose() throws Exception - { - // this is testing an 0.8 connection - if(isBroker08()) - { - try - { - _connection=new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" + _brokerlist + "'"); - - ((AMQConnection) _connection).setConnectionListener(this); - - _connection.setExceptionListener(this); - - // Change the StateManager for one that doesn't respond with Close-OKs - AMQStateManager oldStateManager=((AMQConnection) _connection).getProtocolHandler().getStateManager(); - - _session=_connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - _connection.start(); - - // Test connection - checkSendingMessage(); - - // Set StateManager to manager that ignores Close-oks - AMQProtocolSession protocolSession= - ((AMQConnection) _connection).getProtocolHandler().getProtocolSession(); - - MethodDispatcher d = protocolSession.getMethodDispatcher(); - - MethodDispatcher wrappedDispatcher = (MethodDispatcher) - Proxy.newProxyInstance(d.getClass().getClassLoader(), - d.getClass().getInterfaces(), - new MethodDispatcherProxyHandler( - (ClientMethodDispatcherImpl) d)); - - protocolSession.setMethodDispatcher(wrappedDispatcher); - - - AMQStateManager newStateManager=new NoCloseOKStateManager(protocolSession); - newStateManager.changeState(oldStateManager.getCurrentState()); - - ((AMQConnection) _connection).getProtocolHandler().setStateManager(newStateManager); - - final int TEST_CHANNEL=1; - _logger.info("Testing Channel(" + TEST_CHANNEL + ") Creation"); - - createChannelAndTest(TEST_CHANNEL); - - // Cause it to close - try - { - _logger.info("Closing Channel - invalid exchange"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", false); - fail("Exchange name is empty so this should fail "); - } - catch (AMQException e) - { - assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode()); - } - - try - { - // Send other methods that should be ignored - // send them no wait as server will ignore them - _logger.info("Tested known exchange - should ignore"); - declareExchange(TEST_CHANNEL, "topic", "amq.topic", true); - - _logger.info("Tested known invalid exchange - should ignore"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", true); - - _logger.info("Tested known invalid exchange - should ignore"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", true); - - // Send sync .. server will igore and timy oue - _logger.info("Tested known invalid exchange - should ignore"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", false); - } - catch (AMQTimeoutException te) - { - assertEquals("Request should timeout", AMQConstant.REQUEST_TIMEOUT, te.getErrorCode()); - } - catch (AMQException e) - { - fail("This should not fail as all requests should be ignored"); - } - - _logger.info("Sending Close"); - // Send Close-ok - sendClose(TEST_CHANNEL); - - _logger.info("Re-opening channel"); - - createChannelAndTest(TEST_CHANNEL); - - // Test connection is still ok - - checkSendingMessage(); - - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - catch (AMQException e) - { - fail(e.getMessage()); - - } - catch (URLSyntaxException e) - { - fail(e.getMessage()); - } - finally - { - try - { - _session.close(); - _connection.close(); - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - } - } - } -*/ - private void createChannelAndTest(int channel) throws FailoverException - { - // Create A channel - try - { - createChannel(channel); - } - catch (AMQException e) - { - fail(e.getMessage()); - } - - // Test it is ok - try - { - declareExchange(channel, "topic", "amq.topic", false); - _logger.info("Tested known exchange"); - } - catch (AMQException e) - { - fail("This should not fail as this is the default exchange details"); - } - } - - private void sendClose(int channel) - { - ChannelCloseOkBody body = - ((AMQConnection) _connection).getProtocolHandler().getMethodRegistry().createChannelCloseOkBody(); - AMQFrame frame = body.generateFrame(channel); - - ((AMQConnection) _connection).getProtocolHandler().writeFrame(frame); - } - - private void checkSendingMessage() throws JMSException - { - TEST++; - _logger.info("Test creating producer which will use channel id 1"); - - Queue queue = _session.createQueue("CCT_test_validation_queue" + TEST); - - MessageConsumer consumer = _session.createConsumer(queue); - - MessageProducer producer = _session.createProducer(queue); - - final String MESSAGE = "CCT_Test_Message"; - producer.send(_session.createTextMessage(MESSAGE)); - - Message msg = consumer.receive(2000); - - assertNotNull("Received messages should not be null.", msg); - assertEquals("Message received not what we sent", MESSAGE, ((TextMessage) msg).getText()); - } - - private Connection newConnection() - { - Connection connection = null; - try - { - connection = getConnection(); - - ((AMQConnection) connection).setConnectionListener(this); - - _session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - connection.start(); - - } - catch (Exception e) - { - fail("Creating new connection when:" + e.getMessage()); - } - - return connection; - } - - private void declareExchange(int channelId, String _type, String _name, boolean nowait) - throws AMQException, FailoverException - { - ExchangeDeclareBody body = - ((AMQConnection) _connection).getProtocolHandler() - .getMethodRegistry() - .createExchangeDeclareBody(0, - new AMQShortString(_name), - new AMQShortString(_type), - true, - false, - false, - false, - nowait, - null); - AMQFrame exchangeDeclare = body.generateFrame(channelId); - AMQProtocolHandler protocolHandler = ((AMQConnection) _connection).getProtocolHandler(); - - - if (nowait) - { - protocolHandler.writeFrame(exchangeDeclare); - } - else - { - protocolHandler.syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class, SYNC_TIMEOUT); - } - -// return null; -// } -// }, (AMQConnection)_connection).execute(); - - } - - private void createChannel(int channelId) throws AMQException, FailoverException - { - ChannelOpenBody body = - ((AMQConnection) _connection).getProtocolHandler().getMethodRegistry().createChannelOpenBody(null); - - ((AMQConnection) _connection).getProtocolHandler().syncWrite(body.generateFrame(channelId), // outOfBand - ChannelOpenOkBody.class); - - } - - public void onException(JMSException jmsException) - { - // _logger.info("CCT" + jmsException); - fail(jmsException.getMessage()); - } - - public void bytesSent(long count) - { } - - public void bytesReceived(long count) - { } - - public boolean preFailover(boolean redirect) - { - return false; - } - - public boolean preResubscribe() - { - return false; - } - - public void failoverComplete() - { } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java index f2387fa99b..b43fe35a09 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java @@ -21,7 +21,7 @@ package org.apache.qpid.test.unit.close; import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.AMQSession_0_8; import org.apache.qpid.framing.AMQFrame; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ExchangeDeclareBody; @@ -81,7 +81,7 @@ public class JavaServerCloseRaceConditionTest extends QpidBrokerTestCase AMQConnection connection = (AMQConnection) getConnection(); - AMQSession session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + AMQSession_0_8 session = (AMQSession_0_8) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Set no wait true so that we block the connection // Also set a different exchange class string so the attempt to declare 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 a07e531b98..a9ac028af6 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 @@ -73,7 +73,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase public void setUp() throws Exception { - setConfigurationProperty("management.enabled", "true"); + getBrokerConfiguration().addJmxManagementConfiguration(); _jmxConnected=false; super.setUp(); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java index fd8beffbe6..d93c7a2e71 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java @@ -29,7 +29,7 @@ public class TransactionTimeoutDisabledTest extends TransactionTimeoutTestCase protected void configure() throws Exception { // Setup housekeeping every second - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); // No transaction timeout configuration. } 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 b11df5a2a0..4dc26847da 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 @@ -39,29 +39,29 @@ public class TransactionTimeoutTest extends TransactionTimeoutTestCase protected void configure() throws Exception { - // Setup housekeeping every second - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + // Setup housekeeping every 100ms + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); if (getName().contains("ProducerIdle")) { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500"); } else if (getName().contains("ProducerOpen")) { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0"); } else { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000"); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java index e2b0f00ee4..721dc027c6 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java @@ -23,17 +23,13 @@ package org.apache.qpid.test.unit.transacted; import junit.framework.TestCase; import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.jms.Session; +import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.util.LogMonitor; +import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.ExceptionListener; import javax.jms.JMSException; @@ -41,6 +37,7 @@ import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; +import javax.jms.Session; import javax.jms.TextMessage; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -61,7 +58,7 @@ public abstract class TransactionTimeoutTestCase extends QpidBrokerTestCase impl public static final String OPEN = "Open"; protected LogMonitor _monitor; - protected AMQConnection _con; + protected Connection _con; protected Session _psession, _csession; protected Queue _queue; protected MessageConsumer _consumer; @@ -89,16 +86,14 @@ public abstract class TransactionTimeoutTestCase extends QpidBrokerTestCase impl super.setUp(); // Connect to broker - String broker = ("tcp://localhost:" + DEFAULT_PORT); - ConnectionURL url = new AMQConnectionURL("amqp://guest:guest@clientid/test?brokerlist='" + broker + "'&maxprefetch='1'"); - _con = (AMQConnection) getConnection(url); + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, String.valueOf(1)); + _con = getConnection(); _con.setExceptionListener(this); _con.start(); // Create queue Session qsession = _con.createSession(true, Session.SESSION_TRANSACTED); - AMQShortString queueName = new AMQShortString("test"); - _queue = new AMQQueue(qsession.getDefaultQueueExchangeName(), queueName, queueName, false, true); + _queue = qsession.createQueue(getTestQueueName()); qsession.close(); // Create producer and consumer diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.java b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.java new file mode 100644 index 0000000000..12d286f822 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.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.test.utils; + +import java.io.File; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * Generates the command to start a broker by substituting the tokens + * in the provided broker command. + * + * The command is returned as a list so that it can be easily used by a + * {@link java.lang.ProcessBuilder}. + */ +public class BrokerCommandHelper +{ + private final List<String> _brokerCommandTemplateAsList; + + public BrokerCommandHelper(String brokerCommandTemplate) + { + _brokerCommandTemplateAsList = new LinkedList<String>(Arrays.asList(brokerCommandTemplate.split("\\s+"))); + } + + public String[] getBrokerCommand( int port, String storePath, String storeType, File logConfigFile) + { + String[] command = new String[_brokerCommandTemplateAsList.size()]; + int i=0; + for (String commandPart : _brokerCommandTemplateAsList) + { + command[i] = commandPart + .replace("@PORT", "" + port) + .replace("@STORE_PATH", storePath) + .replace("@STORE_TYPE", storeType) + .replace("@LOG_CONFIG_FILE", '"' + logConfigFile.getAbsolutePath() + '"'); + i++; + } + return command; + } + + private int getBrokerCommandLogOptionIndex(String logOption) + { + int logOptionIndex = _brokerCommandTemplateAsList.indexOf(logOption); + if(logOptionIndex == -1) + { + throw new RuntimeException("Could not find option " + logOption + " in " + _brokerCommandTemplateAsList); + } + return logOptionIndex; + } + + + public void removeBrokerCommandLog4JFile() + { + String logOption = "-l"; + int logOptionIndex = getBrokerCommandLogOptionIndex(logOption); + if (logOptionIndex + 1 >= _brokerCommandTemplateAsList.size()) + { + throw new RuntimeException("Could not find log config location"); + } + _brokerCommandTemplateAsList.remove(logOptionIndex); + _brokerCommandTemplateAsList.remove(logOptionIndex); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.java b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.java new file mode 100644 index 0000000000..f0bcea8e6e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.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.test.utils; + +import static org.mockito.Mockito.*; + +import java.io.File; + +public class BrokerCommandHelperTest extends QpidTestCase +{ + private BrokerCommandHelper _brokerCommandHelper = new BrokerCommandHelper("qpid -p @PORT -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE"); + + private File logConfigFile = mock(File.class); + + @Override + public void setUp() + { + when(logConfigFile.getAbsolutePath()).thenReturn("log Config File"); + } + + public void testGetBrokerCommand() + { + String[] brokerCommand = _brokerCommandHelper.getBrokerCommand(1, "configFile", "json", logConfigFile); + + String[] expected = { "qpid", "-p", "1", "-sp", "configFile", "-st", "json", "-l", "\"log Config File\"" }; + assertEquals("Unexpected broker command", 9, brokerCommand.length); + for (int i = 0; i < expected.length; i++) + { + assertEquals("Unexpected command part value at " + i,expected[i], brokerCommand[i] ); + } + } + + public void testRemoveBrokerCommandLog4JFile() + { + _brokerCommandHelper.removeBrokerCommandLog4JFile(); + String[] brokerCommand = _brokerCommandHelper.getBrokerCommand(1, "configFile", "json", logConfigFile); + + String[] expected = { "qpid", "-p", "1", "-sp", "configFile", "-st", "json" }; + assertEquals("Unexpected broker command", 7, brokerCommand.length); + for (int i = 0; i < expected.length; i++) + { + assertEquals("Unexpected command part value at " + i,expected[i], brokerCommand[i] ); + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java index a71a4ef517..8bad73d0ea 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java @@ -20,9 +20,6 @@ */ package org.apache.qpid.test.utils; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; import java.util.Set; import org.apache.log4j.Logger; @@ -82,28 +79,7 @@ public class InternalBrokerHolder implements BrokerHolder @Override public String dumpThreads() { - ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); - ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); - StringBuilder dump = new StringBuilder(); - dump.append(String.format("%n")); - for (ThreadInfo threadInfo : threadInfos) - { - dump.append(threadInfo); - } - - long[] deadLocks = threadMXBean.findDeadlockedThreads(); - if (deadLocks != null && deadLocks.length > 0) - { - ThreadInfo[] deadlockedThreads = threadMXBean.getThreadInfo(deadLocks); - dump.append(String.format("%n")); - dump.append("Deadlock is detected!"); - dump.append(String.format("%n")); - for (ThreadInfo threadInfo : deadlockedThreads) - { - dump.append(threadInfo); - } - } - return dump.toString(); + return TestUtils.dumpThreads(); } @Override 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 43b80b45fb..6e6e3271f0 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 @@ -24,7 +24,6 @@ import junit.framework.TestCase; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.management.common.JMXConnnectionFactory; -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; import org.apache.qpid.management.common.mbeans.LoggingManagement; import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.management.common.mbeans.ManagedConnection; @@ -32,6 +31,8 @@ import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.management.common.mbeans.ServerInformation; import org.apache.qpid.management.common.mbeans.UserManagement; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.plugin.PluginFactory; import javax.management.InstanceNotFoundException; import javax.management.JMException; @@ -46,7 +47,9 @@ import javax.management.ObjectName; import javax.management.remote.JMXConnector; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -78,7 +81,7 @@ public class JMXTestUtils public void setUp() throws IOException, ConfigurationException, Exception { - _test.setConfigurationProperty("management.enabled", "true"); + _test.getBrokerConfiguration().addJmxManagementConfiguration(); } public void open() throws Exception @@ -287,9 +290,7 @@ public class JMXTestUtils public ObjectName getQueueObjectName(String virtualHostName, String queue) { // Get the name of the test manager - String query = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" - + ObjectName.quote(virtualHostName) + ",name=" - + ObjectName.quote(queue) + ",*"; + String query = getQueueObjectNameString(virtualHostName, queue); Set<ObjectName> objectNames = queryObjects(query); @@ -302,32 +303,20 @@ public class JMXTestUtils return objectName; } + public String getQueueObjectNameString(String virtualHostName, String queue) { + return "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + + ObjectName.quote(virtualHostName) + ",name=" + + ObjectName.quote(queue) + ",*"; + } + /** - * Retrive the ObjectName for the given Exchange on a VirtualHost. - * - * This is then used to create a proxy to the ManagedExchange MBean. - * - * @param virtualHostName the VirtualHost the Exchange is on - * @param exchange the Exchange to retireve e.g. 'direct' - * @return the ObjectName for the given Exchange on the VirtualHost + * Generate the ObjectName for the given Exchange on a VirtualHost. */ - @SuppressWarnings("static-access") - public ObjectName getExchangeObjectName(String virtualHostName, String exchange) + public String getExchangeObjectName(String virtualHostName, String exchange) { - // Get the name of the test manager - String query = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + return "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + ObjectName.quote(virtualHostName) + ",name=" + ObjectName.quote(exchange) + ",*"; - - Set<ObjectName> objectNames = queryObjects(query); - - _test.assertNotNull("Null ObjectName Set returned", objectNames); - _test.assertEquals("Incorrect number of exchange with name '" + exchange + "' returned", 1, objectNames.size()); - - // We have verified we have only one value in objectNames so return it - ObjectName objectName = objectNames.iterator().next(); - _test.getLogger().info("Loading: " + objectName); - return objectName; } @SuppressWarnings("static-access") @@ -343,7 +332,7 @@ public class JMXTestUtils return getManagedObject(managedClass, objectName); } - public boolean isManagedObjectExist(String query) + public boolean doesManagedObjectExist(String query) { return !queryObjects(query).isEmpty(); } @@ -373,9 +362,20 @@ public class JMXTestUtils return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost)); } + @SuppressWarnings("static-access") public ManagedExchange getManagedExchange(String exchangeName) { - ObjectName objectName = getExchangeObjectName("test", exchangeName); + String query = getExchangeObjectName("test", exchangeName); + + Set<ObjectName> objectNames = queryObjects(query); + + _test.assertNotNull("Null ObjectName Set returned", objectNames); + _test.assertEquals("Incorrect number of exchange with name '" + exchangeName + "' returned", 1, objectNames.size()); + + // We have verified we have only one value in objectNames so return an mbean proxy for it + ObjectName objectName = objectNames.iterator().next(); + _test.getLogger().info("Loading: " + objectName); + return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, ManagedExchange.class, false); } @@ -391,12 +391,6 @@ public class JMXTestUtils return getManagedObject(LoggingManagement.class, objectName); } - public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException - { - ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement"); - return getManagedObject(ConfigurationManagement.class, objectName); - } - public UserManagement getUserManagement() throws MalformedObjectNameException { ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement"); 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 aa909a6674..d36f57171f 100644..100755 --- 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 @@ -19,18 +19,17 @@ package org.apache.qpid.test.utils; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; import java.io.PrintStream; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; 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; - import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.Destination; @@ -45,32 +44,34 @@ import javax.jms.Session; import javax.jms.StreamMessage; import javax.jms.TextMessage; import javax.jms.Topic; +import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; - import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; import org.apache.qpid.server.Broker; import org.apache.qpid.server.BrokerOptions; -import org.apache.qpid.server.ProtocolExclusion; -import org.apache.qpid.server.ProtocolInclusion; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStoreConstants; +import org.apache.qpid.server.store.MessageStoreCreator; +import org.apache.qpid.server.store.MessageStoreFactory; import org.apache.qpid.server.store.derby.DerbyMessageStore; import org.apache.qpid.url.URLSyntaxException; import org.apache.qpid.util.FileUtils; -import org.apache.qpid.util.LogMonitor; /** * Qpid base class for system testing test cases. @@ -80,7 +81,7 @@ public class QpidBrokerTestCase extends QpidTestCase public enum BrokerType { EXTERNAL /** Test case relies on a Broker started independently of the test-suite */, - INTERNAL /** Test case starts an embedded broker within this JVM */, + INTERNAL /** Test case starts an embedded broker within this JVM */, SPAWNED /** Test case spawns a new broker as a separate process */ } @@ -88,9 +89,9 @@ public class QpidBrokerTestCase extends QpidTestCase public static final String GUEST_PASSWORD = "guest"; protected final static String QpidHome = System.getProperty("QPID_HOME"); - protected File _configFile = new File(System.getProperty("broker.config")); - protected File _logConfigFile = new File(System.getProperty("log4j.configuration")); - + private final File _configFile = new File(System.getProperty("broker.config")); + private File _logConfigFile; + protected final String _brokerStoreType = System.getProperty("broker.config-store-type", "json"); protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class); protected static final int LOGMONITOR_TIMEOUT = 5000; @@ -98,7 +99,7 @@ public class QpidBrokerTestCase extends QpidTestCase private Map<String, String> _propertiesSetForBroker = new HashMap<String, String>(); - private XMLConfiguration _testConfiguration = new XMLConfiguration(); + private Map<Integer, TestBrokerConfiguration> _brokerConfigurations; private XMLConfiguration _testVirtualhosts = new XMLConfiguration(); protected static final String INDEX = "index"; @@ -106,24 +107,31 @@ public class QpidBrokerTestCase extends QpidTestCase private static final String DEFAULT_INITIAL_CONTEXT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"; + private static Map<String, String> supportedStoresClassToTypeMapping = new HashMap<String, String>(); + static { - String initialContext = System.getProperty(InitialContext.INITIAL_CONTEXT_FACTORY); + String initialContext = System.getProperty(Context.INITIAL_CONTEXT_FACTORY); if (initialContext == null || initialContext.length() == 0) { - System.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT); + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT); + } + + MessageStoreCreator messageStoreCreator = new MessageStoreCreator(); + Collection<MessageStoreFactory> factories = messageStoreCreator.getFactories(); + for (MessageStoreFactory messageStoreFactory : factories) + { + supportedStoresClassToTypeMapping.put(messageStoreFactory.createMessageStore().getClass().getName(), messageStoreFactory.getType()); } } // system properties private static final String TEST_VIRTUALHOSTS = "test.virtualhosts"; - private static final String TEST_CONFIG = "test.config"; private static final String BROKER_LANGUAGE = "broker.language"; protected static final String BROKER_TYPE = "broker.type"; private static final String BROKER_COMMAND = "broker.command"; private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests"; - private static final String BROKER_EXISTING_QPID_WORK = "broker.existing.qpid.work"; private static final String BROKER_VERSION = "broker.version"; protected static final String BROKER_READY = "broker.ready"; private static final String BROKER_STOPPED = "broker.stopped"; @@ -131,8 +139,14 @@ public class QpidBrokerTestCase extends QpidTestCase private static final String BROKER_LOG_INTERLEAVE = "broker.log.interleave"; private static final String BROKER_LOG_PREFIX = "broker.log.prefix"; private static final String BROKER_PERSITENT = "broker.persistent"; - public static final String BROKER_PROTOCOL_EXCLUDES = "broker.protocol.excludes"; - public static final String BROKER_PROTOCOL_INCLUDES = "broker.protocol.includes"; + public static final String PROFILE_USE_SSL = "profile.use_ssl"; + + public static final int DEFAULT_PORT_VALUE = 5672; + public static final int DEFAULT_SSL_PORT_VALUE = 5671; + public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999; + public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100; + public static final int DEFAULT_HTTP_MANAGEMENT_PORT = 8080; + public static final int DEFAULT_HTTPS_MANAGEMENT_PORT = 8443; // values protected static final String JAVA = "java"; @@ -140,15 +154,15 @@ public class QpidBrokerTestCase extends QpidTestCase protected static final String QPID_HOME = "QPID_HOME"; - public static final int DEFAULT_VM_PORT = 1; - public static final int DEFAULT_PORT = Integer.getInteger("test.port", ServerConfiguration.DEFAULT_PORT); + public static final int DEFAULT_PORT = Integer.getInteger("test.port", DEFAULT_PORT_VALUE); public static final int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt")); - public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", ServerConfiguration.DEFAULT_JMXPORT_REGISTRYSERVER); - public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", ServerConfiguration.DEFAULT_SSL_PORT); + public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", DEFAULT_JMXPORT_REGISTRYSERVER); + public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", DEFAULT_SSL_PORT_VALUE); protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA); protected BrokerType _brokerType = BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase()); - protected String _brokerCommand = System.getProperty(BROKER_COMMAND); + + protected BrokerCommandHelper _brokerCommandHelper = new BrokerCommandHelper(System.getProperty(BROKER_COMMAND)); private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS); private final AmqpProtocolVersion _brokerVersion = AmqpProtocolVersion.valueOf(System.getProperty(BROKER_VERSION, "")); protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir")); @@ -190,14 +204,67 @@ public class QpidBrokerTestCase extends QpidTestCase } private MessageType _messageType = MessageType.TEXT; - public QpidBrokerTestCase(String name) - { - super(name); - } - public QpidBrokerTestCase() { super(); + _brokerConfigurations = new HashMap<Integer, TestBrokerConfiguration>(); + initialiseLogConfigFile(); + } + + public TestBrokerConfiguration getBrokerConfiguration(int port) + { + int actualPort = getPort(port); + + synchronized (_brokerConfigurations) + { + TestBrokerConfiguration configuration = _brokerConfigurations.get(actualPort); + if (configuration == null) + { + configuration = createBrokerConfiguration(actualPort); + } + return configuration; + } + } + + public TestBrokerConfiguration getBrokerConfiguration() + { + return getBrokerConfiguration(DEFAULT_PORT); + } + + public TestBrokerConfiguration createBrokerConfiguration(int port) + { + int actualPort = getPort(port); + TestBrokerConfiguration configuration = new TestBrokerConfiguration(System.getProperty(_brokerStoreType), _configFile.getAbsolutePath()); + synchronized (_brokerConfigurations) + { + _brokerConfigurations.put(actualPort, configuration); + } + if (actualPort != DEFAULT_PORT) + { + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, Port.PORT, actualPort); + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_RMI_PORT, Port.PORT, getManagementPort(actualPort)); + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.PORT, getManagementPort(actualPort) + JMXPORT_CONNECTORSERVER_OFFSET); + } + return configuration; + } + + private void initialiseLogConfigFile() + { + try + { + _logger.info("About to initialise log config file from system property: " + LOG4J_CONFIG_FILE_PATH); + + URI uri = new URI("file", LOG4J_CONFIG_FILE_PATH, null); + _logConfigFile = new File(uri); + if(!_logConfigFile.exists()) + { + throw new RuntimeException("Log config file " + _logConfigFile.getAbsolutePath() + " does not exist"); + } + } + catch (URISyntaxException e) + { + throw new RuntimeException("Couldn't create URI from log4.configuration: " + LOG4J_CONFIG_FILE_PATH, e); + } } public Logger getLogger() @@ -289,16 +356,6 @@ public class QpidBrokerTestCase extends QpidTestCase fail("Unable to test without config file:" + _configFile); } - String existingQpidWorkPath = System.getProperty(BROKER_EXISTING_QPID_WORK); - if(existingQpidWorkPath != null && !existingQpidWorkPath.equals("")) - { - - String qpidWork = getQpidWork(_brokerType, getPort()); - File existing = new File(existingQpidWorkPath); - cleanBrokerWork(qpidWork); - FileUtils.copyRecursive(existing, new File(qpidWork)); - } - startBroker(); } @@ -322,7 +379,7 @@ public class QpidBrokerTestCase extends QpidTestCase { Set<Integer> ports = new HashSet<Integer>(); int managementPort = getManagementPort(mainPort); - int connectorServerPort = managementPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET; + int connectorServerPort = managementPort + JMXPORT_CONNECTORSERVER_OFFSET; ports.add(mainPort); ports.add(managementPort); @@ -354,37 +411,33 @@ public class QpidBrokerTestCase extends QpidTestCase } } - protected String getBrokerCommand(int port) throws MalformedURLException + public void startBroker() throws Exception { - final int sslPort = port-1; - final String protocolExcludesList = getProtocolExcludesList(port, sslPort); - final String protocolIncludesList = getProtocolIncludesList(port, sslPort); + startBroker(0); + } - return _brokerCommand - .replace("@PORT", "" + port) - .replace("@SSL_PORT", "" + sslPort) - .replace("@MPORT", "" + getManagementPort(port)) - .replace("@CONFIG_FILE", _configFile.toString()) - .replace("@LOG_CONFIG_FILE", _logConfigFile.toString()) - .replace("@EXCLUDES", protocolExcludesList) - .replace("@INCLUDES", protocolIncludesList); + public void startBroker(int port) throws Exception + { + int actualPort = getPort(port); + TestBrokerConfiguration configuration = getBrokerConfiguration(actualPort); + startBroker(actualPort, configuration, _testVirtualhosts); } - public void startBroker() throws Exception + + protected File getBrokerCommandLog4JFile() { - startBroker(0); + return _logConfigFile; } - public void startBroker(int port) throws Exception + protected void setBrokerCommandLog4JFile(File file) { - startBroker(port, _testConfiguration, _testVirtualhosts); + _logConfigFile = file; + _logger.info("Modified log config file to: " + file); } - public void startBroker(int port, XMLConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception + public void startBroker(int port, TestBrokerConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception { port = getPort(port); - - // Save any configuration changes that have been made String testConfig = saveTestConfiguration(port, testConfiguration); String virtualHostsConfig = saveTestVirtualhosts(port, virtualHosts); @@ -397,28 +450,20 @@ public class QpidBrokerTestCase extends QpidTestCase if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker()) { - setConfigurationProperty(ServerConfiguration.MGMT_CUSTOM_REGISTRY_SOCKET, String.valueOf(false)); - testConfig = saveTestConfiguration(port, testConfiguration); - _logger.info("Set test.config property to: " + testConfig); _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig); - setSystemProperty(TEST_CONFIG, testConfig); setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig); - + setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false"); BrokerOptions options = new BrokerOptions(); - options.setConfigFile(_configFile.getAbsolutePath()); - options.addPort(port); - - addExcludedPorts(port, DEFAULT_SSL_PORT, options); - addIncludedPorts(port, DEFAULT_SSL_PORT, options); - options.setJmxPortRegistryServer(getManagementPort(port)); + options.setConfigurationStoreType(_brokerStoreType); + options.setConfigurationStoreLocation(testConfig); //Set the log config file, relying on the log4j.configuration system property //set on the JVM by the JUnit runner task in module.xml. options.setLogConfigFile(_logConfigFile.getAbsolutePath()); Broker broker = new Broker(); - _logger.info("starting internal broker (same JVM)"); + _logger.info("Starting internal broker (same JVM)"); broker.startup(options); _brokers.put(port, new InternalBrokerHolder(broker, System.getProperty("QPID_WORK"), portsUsedByBroker)); @@ -427,9 +472,10 @@ public class QpidBrokerTestCase extends QpidTestCase { // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests final String qpidWork = getQpidWork(_brokerType, port); - String cmd = getBrokerCommand(port); - _logger.info("starting external broker: " + cmd); - ProcessBuilder pb = new ProcessBuilder(cmd.split("\\s+")); + + String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile); + _logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' ')); + ProcessBuilder pb = new ProcessBuilder(cmd); pb.redirectErrorStream(true); Map<String, String> processEnv = pb.environment(); String qpidHome = System.getProperty(QPID_HOME); @@ -459,28 +505,28 @@ public class QpidBrokerTestCase extends QpidTestCase } } + String qpidOpts = ""; - // Add default test logging levels that are used by the log4j-test - // Use the convenience methods to push the current logging setting - // in to the external broker's QPID_OPTS string. - if (System.getProperty("amqj.protocol.logging.level") != null) + // a synchronized hack to avoid adding into QPID_OPTS the values + // of JVM properties "test.virtualhosts" and "test.config" set by a concurrent startup process + synchronized (_propertiesSetForBroker) { + // Add default test logging levels that are used by the log4j-test + // Use the convenience methods to push the current logging setting + // in to the external broker's QPID_OPTS string. setSystemProperty("amqj.protocol.logging.level"); - } - if (System.getProperty("root.logging.level") != null) - { setSystemProperty("root.logging.level"); - } - - // set test.config and test.virtualhosts - String qpidOpts = " -D" + TEST_CONFIG + "=" + testConfig + " -D" + TEST_VIRTUALHOSTS + "=" + virtualHostsConfig; + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES); + setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig); - // Add all the specified system properties to QPID_OPTS - if (!_propertiesSetForBroker.isEmpty()) - { - for (String key : _propertiesSetForBroker.keySet()) + // Add all the specified system properties to QPID_OPTS + if (!_propertiesSetForBroker.isEmpty()) { - qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key); + for (String key : _propertiesSetForBroker.keySet()) + { + qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key); + } } } if (processEnv.containsKey("QPID_OPTS")) @@ -489,9 +535,6 @@ public class QpidBrokerTestCase extends QpidTestCase } processEnv.put("QPID_OPTS", qpidOpts); - _logger.info("Set test.config property to: " + testConfig); - _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig); - // cpp broker requires that the work directory is created createBrokerWork(qpidWork); @@ -505,9 +548,15 @@ public class QpidBrokerTestCase extends QpidTestCase p.start(); + SpawnedBrokerHolder holder = new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker); if (!p.await(30, TimeUnit.SECONDS)) { _logger.info("broker failed to become ready (" + p.getReady() + "):" + p.getStopLine()); + String threadDump = holder.dumpThreads(); + if (!threadDump.isEmpty()) + { + _logger.info("the result of a try to capture thread dump:" + threadDump); + } //Ensure broker has stopped process.destroy(); cleanBrokerWork(qpidWork); @@ -528,65 +577,7 @@ public class QpidBrokerTestCase extends QpidTestCase // this is expect if the broker started successfully } - _brokers.put(port, new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker)); - } - } - - private void addExcludedPorts(int port, int sslPort, BrokerOptions options) - { - final String protocolExcludesList = getProtocolExcludesList(port, sslPort); - - if (protocolExcludesList.equals("")) - { - return; - } - final String[] toks = protocolExcludesList.split("\\s"); - - if(toks.length % 2 != 0) - { - throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolExcludesList + "'"); - } - for (int i = 0; i < toks.length; i=i+2) - { - String excludeArg = toks[i]; - final int excludedPort = Integer.parseInt(toks[i+1]); - options.addExcludedPort(ProtocolExclusion.lookup(excludeArg), excludedPort); - - _logger.info("Adding protocol exclusion " + excludeArg + " " + excludedPort); - } - } - - protected String getProtocolExcludesList(int port, int sslPort) - { - return System.getProperty(BROKER_PROTOCOL_EXCLUDES,"").replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort); - } - - private String getProtocolIncludesList(int port, int sslPort) - { - return System.getProperty(BROKER_PROTOCOL_INCLUDES, "").replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort); - } - - private void addIncludedPorts(int port, int sslPort, BrokerOptions options) - { - final String protocolIncludesList = getProtocolIncludesList(port, sslPort); - - if (protocolIncludesList.equals("")) - { - return; - } - final String[] toks = protocolIncludesList.split("\\s"); - - if(toks.length % 2 != 0) - { - throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolIncludesList + "'"); - } - for (int i = 0; i < toks.length; i=i+2) - { - String includeArg = toks[i]; - final int includedPort = Integer.parseInt(toks[i+1]); - options.addIncludedPort(ProtocolInclusion.lookup(includeArg), includedPort); - - _logger.info("Adding protocol inclusion " + includeArg + " " + includedPort); + _brokers.put(port, holder); } } @@ -620,7 +611,7 @@ public class QpidBrokerTestCase extends QpidTestCase public String getTestConfigFile(int port) { - return _output + "/" + getTestQueueName() + "-" + port + "-config.xml"; + return _output + "/" + getTestQueueName() + "-" + port + "-config"; } public String getTestVirtualhostsFile(int port) @@ -633,44 +624,33 @@ public class QpidBrokerTestCase extends QpidTestCase return file.replace(System.getProperty(QPID_HOME,"QPID_HOME") + "/",""); } - protected void saveTestConfiguration() throws ConfigurationException + protected String getPathRelativeToWorkingDirectory(String file) { - String relative = saveTestConfiguration(getPort(), _testConfiguration); - _logger.info("Set test.config property to: " + relative); - setSystemProperty(TEST_CONFIG, relative); + File configLocation = new File(file); + File workingDirectory = new File(System.getProperty("user.dir")); + return configLocation.getAbsolutePath().replace(workingDirectory.getAbsolutePath(), "").substring(1); } - protected String saveTestConfiguration(int port, XMLConfiguration testConfiguration) throws ConfigurationException + protected String saveTestConfiguration(int port, TestBrokerConfiguration testConfiguration) { - // Specify the test config file String testConfig = getTestConfigFile(port); - String relative = relativeToQpidHome(testConfig); - - _logger.info("Saving test virtualhosts file at: " + testConfig); - - // Create the file if configuration does not exist - if (testConfiguration.isEmpty()) + String relative = getPathRelativeToWorkingDirectory(testConfig); + if (!testConfiguration.isSaved()) { - testConfiguration.addProperty("__ignore", "true"); + _logger.info("Saving test broker configuration at: " + testConfig); + testConfiguration.save(new File(testConfig)); + testConfiguration.setSaved(true); } - testConfiguration.save(testConfig); return relative; } - protected void saveTestVirtualhosts() throws ConfigurationException - { - String relative = saveTestVirtualhosts(getPort(), _testVirtualhosts); - _logger.info("Set test.virtualhosts property to: " + relative); - setSystemProperty(TEST_VIRTUALHOSTS, relative); - } - protected String saveTestVirtualhosts(int port, XMLConfiguration virtualHostConfiguration) throws ConfigurationException { // Specify the test virtualhosts file String testVirtualhosts = getTestVirtualhostsFile(port); String relative = relativeToQpidHome(testVirtualhosts); - _logger.info("Set test.virtualhosts property to: " + testVirtualhosts); + _logger.info("Path to virtualhosts configuration: " + testVirtualhosts); // Create the file if configuration does not exist if (virtualHostConfiguration.isEmpty()) @@ -818,57 +798,41 @@ public class QpidBrokerTestCase extends QpidTestCase } /** - * Attempt to set the Java Broker to use the BDBMessageStore for persistence - * Falling back to the DerbyMessageStore if - * - * @param virtualhost - The virtualhost to modify + * Creates a new virtual host within the test virtualhost file. + * @param brokerPort broker port + * @param virtualHostName virtual host name * - * @throws ConfigurationException - when reading/writing existing configuration - * @throws IOException - When creating a temporary file. + * @throws ConfigurationException */ - protected void makeVirtualHostPersistent(String virtualhost) - throws ConfigurationException, IOException + protected void createTestVirtualHost(int brokerPort, String virtualHostName) throws ConfigurationException { - Class<?> storeClass = null; - try + String storeClassName = getTestProfileMessageStoreClassName(); + + _testVirtualhosts.setProperty("virtualhost.name(-1)", virtualHostName); + _testVirtualhosts.setProperty("virtualhost." + virtualHostName + ".store.class", storeClassName); + + String storeDir = null; + + if (System.getProperty("profile", "").startsWith("java-dby-mem")) { - // Try and lookup the BDB class - storeClass = Class.forName("org.apache.qpid.server.store.berkeleydb.BDBMessageStore"); + storeDir = DerbyMessageStore.MEMORY_STORE_LOCATION; } - catch (ClassNotFoundException e) + else if (!MEMORY_STORE_CLASS_NAME.equals(storeClassName)) { - // No BDB store, we'll use Derby instead. - storeClass = DerbyMessageStore.class; + storeDir = "${QPID_WORK}" + File.separator + virtualHostName + "-store"; } + if (storeDir != null) + { + _testVirtualhosts.setProperty("virtualhost." + virtualHostName + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, storeDir); + } - setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store.class", - storeClass.getName()); - setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, - "${QPID_WORK}/" + virtualhost); - } - - /** - * Get a property value from the current configuration file. - * - * @param property the property to lookup - * - * @return the requested String Value - * - * @throws org.apache.commons.configuration.ConfigurationException - * - */ - protected String getConfigurationStringProperty(String property) throws ConfigurationException - { - // Call save Configuration to be sure we have saved the test specific - // file. As the optional status - saveTestConfiguration(); - saveTestVirtualhosts(); - - ServerConfiguration configuration = new ServerConfiguration(_configFile); - // Don't need to configuration.configure() here as we are just pulling - // values directly by String. - return configuration.getConfig().getString(property); + // add new virtual host configuration to the broker store + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(VirtualHost.NAME, virtualHostName); + attributes.put(VirtualHost.CONFIG_PATH, System.getProperty("broker.virtualhosts-config")); + int port = getPort(brokerPort); + getBrokerConfiguration(port).addHostConfiguration(attributes); } /** @@ -884,10 +848,8 @@ public class QpidBrokerTestCase extends QpidTestCase * @param value the new value * * @throws ConfigurationException when loading the current config file - * @throws IOException when writing the new config file */ - public void setConfigurationProperty(String property, String value) - throws ConfigurationException, IOException + public void setVirtualHostConfigurationProperty(String property, String value) throws ConfigurationException { // Choose which file to write the property to based on prefix. if (property.startsWith("virtualhosts")) @@ -896,7 +858,7 @@ public class QpidBrokerTestCase extends QpidTestCase } else { - _testConfiguration.setProperty(property, value); + throw new ConfigurationException("Cannot set broker configuration as property"); } } @@ -914,11 +876,13 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void setBrokerOnlySystemProperty(String property, String value) { - if (!_propertiesSetForBroker.containsKey(property)) + synchronized (_propertiesSetForBroker) { - _propertiesSetForBroker.put(property, value); + if (!_propertiesSetForBroker.containsKey(property)) + { + _propertiesSetForBroker.put(property, value); + } } - } /** @@ -931,7 +895,11 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void setSystemProperty(String property) { - setSystemProperty(property, System.getProperty(property)); + String value = System.getProperty(property); + if (value != null) + { + setSystemProperty(property, value); + } } /** @@ -939,7 +907,7 @@ public class QpidBrokerTestCase extends QpidTestCase * * When the test run is complete the value will be reverted. * - * The values set using this method will also be propogated to the external + * The values set using this method will also be propagated to the external * Java Broker via a -D value defined in QPID_OPTS. * * If the value should not be set on the broker then use @@ -950,9 +918,18 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void setSystemProperty(String property, String value) { - // Record the value for the external broker - _propertiesSetForBroker.put(property, value); - + synchronized(_propertiesSetForBroker) + { + // Record the value for the external broker + if (value == null) + { + _propertiesSetForBroker.remove(property); + } + else + { + _propertiesSetForBroker.put(property, value); + } + } //Set the value for the test client vm aswell. setTestClientSystemProperty(property, value); } @@ -1073,7 +1050,7 @@ public class QpidBrokerTestCase extends QpidTestCase _logger.info("get ConnectionFactory"); if (_connectionFactory == null) { - if (Boolean.getBoolean("profile.use_ssl")) + if (Boolean.getBoolean(PROFILE_USE_SSL)) { _connectionFactory = getConnectionFactory("default.ssl"); } @@ -1092,7 +1069,7 @@ public class QpidBrokerTestCase extends QpidTestCase * * @return A connection factory * - * @throws Exception if there is an error getting the tactory + * @throws Exception if there is an error getting the factory */ public AMQConnectionFactory getConnectionFactory(String factoryName) throws NamingException { @@ -1104,6 +1081,22 @@ public class QpidBrokerTestCase extends QpidTestCase return getConnection(GUEST_USERNAME, GUEST_PASSWORD); } + public Connection getConnectionWithOptions(Map<String, String> options) + throws URLSyntaxException, NamingException, JMSException + { + ConnectionURL curl = new AMQConnectionURL(getConnectionFactory().getConnectionURLString()); + for(Map.Entry<String,String> entry : options.entrySet()) + { + curl.setOption(entry.getKey(), entry.getValue()); + } + curl = new AMQConnectionURL(curl.toString()); + + curl.setUsername(GUEST_USERNAME); + curl.setPassword(GUEST_PASSWORD); + return getConnection(curl); + } + + public Connection getConnection(ConnectionURL url) throws JMSException { _logger.info(url.getURL()); @@ -1363,11 +1356,6 @@ public class QpidBrokerTestCase extends QpidTestCase _messageSize = byteSize; } - public ConnectionURL getConnectionURL() throws NamingException - { - return getConnectionFactory().getConnectionURL(); - } - public BrokerDetails getBroker() { try @@ -1390,31 +1378,6 @@ public class QpidBrokerTestCase extends QpidTestCase return null; } - /** - * Reloads the broker security configuration using the ApplicationRegistry (InVM brokers) or the - * ConfigurationManagementMBean via the JMX interface (Standalone brokers, management must be - * enabled before calling the method). - */ - public void reloadBrokerSecurityConfig() throws Exception - { - JMXTestUtils jmxu = new JMXTestUtils(this); - jmxu.open(); - - try - { - ConfigurationManagement configMBean = jmxu.getConfigurationManagement(); - configMBean.reloadSecurityConfiguration(); - } - finally - { - jmxu.close(); - } - - LogMonitor _monitor = new LogMonitor(_outputFile); - assertTrue("The expected server security configuration reload did not occur", - _monitor.waitForMessage(ServerConfiguration.SECURITY_CONFIG_RELOADED, LOGMONITOR_TIMEOUT)); - } - protected int getFailingPort() { return FAILING_PORT; @@ -1430,13 +1393,14 @@ public class QpidBrokerTestCase extends QpidTestCase _testVirtualhosts = testVirtualhosts; } - public XMLConfiguration getTestConfiguration() + public String getTestProfileMessageStoreType() { - return _testConfiguration; + final String storeClass = getTestProfileMessageStoreClassName(); + if (storeClass == null) + { + return MemoryMessageStore.TYPE; + } + return supportedStoresClassToTypeMapping.get(storeClass); } - public void setTestConfiguration(XMLConfiguration testConfiguration) - { - _testConfiguration = testConfiguration; - } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java deleted file mode 100644 index 72003ed7d7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java +++ /dev/null @@ -1,295 +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.utils; - -import org.apache.log4j.Logger; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQConnectionFactory; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.JMSAMQException; -import org.apache.qpid.url.URLSyntaxException; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; - -/** - * @todo This was originally cut and paste from the client module leading to a duplicate class, then altered very - * slightly. To avoid the duplicate class the name was altered slightly to have 'Helper' on the end in order - * to distinguish it from the original. Delete this class and use the original instead, just upgrade it to - * provide the new features needed. - */ -public class QpidClientConnectionHelper implements ExceptionListener -{ - - private static final Logger _logger = Logger.getLogger(QpidClientConnectionHelper.class); - - private boolean transacted = true; - private int ackMode = Session.CLIENT_ACKNOWLEDGE; - private Connection connection; - - private String virtualHost; - private String brokerlist; - private int prefetch; - protected Session session; - protected boolean connected; - - public QpidClientConnectionHelper(String broker) - { - super(); - setVirtualHost("/test"); - setBrokerList(broker); - setPrefetch(5000); - } - - public void connect() throws JMSException - { - if (!connected) - { - /* - * amqp://[user:pass@][clientid]/virtualhost? - * brokerlist='[transport://]host[:port][?option='value'[&option='value']];' - * [&failover='method[?option='value'[&option='value']]'] - * [&option='value']" - */ - String brokerUrl = "amqp://guest:guest@" + virtualHost + "?brokerlist='" + brokerlist + "'"; - try - { - AMQConnectionFactory factory = new AMQConnectionFactory(new AMQConnectionURL(brokerUrl)); - _logger.info("connecting to Qpid :" + brokerUrl); - connection = factory.createConnection(); - - // register exception listener - connection.setExceptionListener(this); - - session = ((AMQConnection) connection).createSession(transacted, ackMode, prefetch); - - _logger.info("starting connection"); - connection.start(); - - connected = true; - } - catch (URLSyntaxException e) - { - throw new JMSAMQException("URL syntax error in [" + brokerUrl + "]: " + e.getMessage(), e); - } - } - } - - public void disconnect() throws JMSException - { - if (connected) - { - session.commit(); - session.close(); - connection.close(); - connected = false; - _logger.info("disconnected"); - } - } - - public void disconnectWithoutCommit() throws JMSException - { - if (connected) - { - session.close(); - connection.close(); - connected = false; - _logger.info("disconnected without commit"); - } - } - - public String getBrokerList() - { - return brokerlist; - } - - public void setBrokerList(String brokerlist) - { - this.brokerlist = brokerlist; - } - - public String getVirtualHost() - { - return virtualHost; - } - - public void setVirtualHost(String virtualHost) - { - this.virtualHost = virtualHost; - } - - public void setPrefetch(int prefetch) - { - this.prefetch = prefetch; - } - - /** override as necessary */ - public void onException(JMSException exception) - { - _logger.info("ExceptionListener event: error " + exception.getErrorCode() + ", message: " + exception.getMessage()); - } - - public boolean isConnected() - { - return connected; - } - - public Session getSession() - { - return session; - } - - /** - * Put a String as a text messages, repeat n times. A null payload will result in a null message. - * - * @param queueName The queue name to put to - * @param payload the content of the payload - * @param copies the number of messages to put - * - * @throws javax.jms.JMSException any exception that occurs - */ - public void put(String queueName, String payload, int copies, int deliveryMode) throws JMSException - { - if (!connected) - { - connect(); - } - - _logger.info("putting to queue " + queueName); - Queue queue = session.createQueue(queueName); - - final MessageProducer sender = session.createProducer(queue); - - sender.setDeliveryMode(deliveryMode); - - for (int i = 0; i < copies; i++) - { - Message m = session.createTextMessage(payload + i); - m.setIntProperty("index", i + 1); - sender.send(m); - } - - session.commit(); - sender.close(); - _logger.info("put " + copies + " copies"); - } - - /** - * GET the top message on a queue. Consumes the message. Accepts timeout value. - * - * @param queueName The quename to get from - * @param readTimeout The timeout to use - * - * @return the content of the text message if any - * - * @throws javax.jms.JMSException any exception that occured - */ - public Message getNextMessage(String queueName, long readTimeout) throws JMSException - { - if (!connected) - { - connect(); - } - - Queue queue = session.createQueue(queueName); - - final MessageConsumer consumer = session.createConsumer(queue); - - Message message = consumer.receive(readTimeout); - session.commit(); - consumer.close(); - - Message result; - - // all messages we consume should be TextMessages - if (message instanceof TextMessage) - { - result = ((TextMessage) message); - } - else if (null == message) - { - result = null; - } - else - { - _logger.info("warning: received non-text message"); - result = message; - } - - return result; - } - - /** - * GET the top message on a queue. Consumes the message. - * - * @param queueName The Queuename to get from - * - * @return The string content of the text message, if any received - * - * @throws javax.jms.JMSException any exception that occurs - */ - public Message getNextMessage(String queueName) throws JMSException - { - return getNextMessage(queueName, 0); - } - - /** - * Completely clears a queue. For readTimeout behaviour see Javadocs for javax.jms.MessageConsumer. - * - * @param queueName The Queue name to consume from - * @param readTimeout The timeout for each consume - * - * @throws javax.jms.JMSException Any exception that occurs during the consume - * @throws InterruptedException If the consume thread was interrupted during a consume. - */ - public void consume(String queueName, int readTimeout) throws JMSException, InterruptedException - { - if (!connected) - { - connect(); - } - - _logger.info("consuming queue " + queueName); - Queue queue = session.createQueue(queueName); - - final MessageConsumer consumer = session.createConsumer(queue); - int messagesReceived = 0; - - _logger.info("consuming..."); - while ((consumer.receive(readTimeout)) != null) - { - messagesReceived++; - } - - session.commit(); - consumer.close(); - _logger.info("consumed: " + messagesReceived); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java new file mode 100644 index 0000000000..80f8010678 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.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.test.utils; + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.PluginFactory; + +public class TestBrokerConfiguration +{ + public static final String ENTRY_NAME_HTTP_PORT = "http"; + public static final String ENTRY_NAME_AMQP_PORT = "amqp"; + public static final String ENTRY_NAME_RMI_PORT = "rmi"; + public static final String ENTRY_NAME_JMX_PORT = "jmx"; + public static final String ENTRY_NAME_VIRTUAL_HOST = "test"; + public static final String ENTRY_NAME_AUTHENTICATION_PROVIDER = "plain"; + public static final String ENTRY_NAME_EXTERNAL_PROVIDER = "external"; + public static final String ENTRY_NAME_SSL_PORT = "sslPort"; + public static final String ENTRY_NAME_HTTP_MANAGEMENT = "MANAGEMENT-HTTP"; + public static final String MANAGEMENT_HTTP_PLUGIN_TYPE = "MANAGEMENT-HTTP"; + public static final String ENTRY_NAME_JMX_MANAGEMENT = "MANAGEMENT-JMX"; + public static final String MANAGEMENT_JMX_PLUGIN_TYPE = "MANAGEMENT-JMX"; + public static final String ENTRY_NAME_ANONYMOUS_PROVIDER = "anonymous"; + + private JsonConfigurationEntryStore _store; + private boolean _saved; + + public TestBrokerConfiguration(String storeType, String intialStoreLocation) + { + // TODO: add support for DERBY store + _store = new JsonConfigurationEntryStore(); + _store.open(JsonConfigurationEntryStore.IN_MEMORY, intialStoreLocation); + } + + public boolean setBrokerAttribute(String name, Object value) + { + return setObjectAttribute(_store.getRootEntry(), name, value); + } + + public boolean setObjectAttribute(String objectName, String attributeName, Object value) + { + ConfigurationEntry entry = findObjectByName(objectName); + if (entry == null) + { + return false; + } + return setObjectAttribute(entry, attributeName, value); + } + + public boolean setObjectAttributes(String objectName, Map<String, Object> attributes) + { + ConfigurationEntry entry = findObjectByName(objectName); + if (entry == null) + { + return false; + } + return setObjectAttributes(entry, attributes); + } + + public boolean save(File configFile) + { + _store.copyTo(configFile.getAbsolutePath()); + return true; + } + + public UUID[] removeObjectConfiguration(String name) + { + ConfigurationEntry entry = findObjectByName(name); + if (entry != null) + { + return _store.remove(entry.getId()); + } + return null; + } + + public UUID addObjectConfiguration(String name, String type, Map<String, Object> attributes) + { + UUID id = UUIDGenerator.generateBrokerChildUUID(type, name); + addObjectConfiguration(id, type, attributes); + return id; + } + + public UUID addJmxManagementConfiguration() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PluginFactory.PLUGIN_TYPE, MANAGEMENT_JMX_PLUGIN_TYPE); + attributes.put(Plugin.NAME, ENTRY_NAME_JMX_MANAGEMENT); + return addObjectConfiguration(ENTRY_NAME_JMX_MANAGEMENT, Plugin.class.getSimpleName(), attributes); + } + + public UUID addHttpManagementConfiguration() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PluginFactory.PLUGIN_TYPE, MANAGEMENT_HTTP_PLUGIN_TYPE); + attributes.put(Plugin.NAME, ENTRY_NAME_HTTP_MANAGEMENT); + return addObjectConfiguration(ENTRY_NAME_HTTP_MANAGEMENT, Plugin.class.getSimpleName(), attributes); + } + + public UUID addPortConfiguration(Map<String, Object> attributes) + { + String name = (String) attributes.get(Port.NAME); + return addObjectConfiguration(name, Port.class.getSimpleName(), attributes); + } + + public UUID addHostConfiguration(Map<String, Object> attributes) + { + String name = (String) attributes.get(VirtualHost.NAME); + return addObjectConfiguration(name, VirtualHost.class.getSimpleName(), attributes); + } + + public UUID addAuthenticationProviderConfiguration(Map<String, Object> attributes) + { + String name = (String) attributes.get(AuthenticationProvider.NAME); + return addObjectConfiguration(name, AuthenticationProvider.class.getSimpleName(), attributes); + } + + private boolean setObjectAttributes(ConfigurationEntry entry, Map<String, Object> attributes) + { + Map<String, Object> newAttributes = new HashMap<String, Object>(entry.getAttributes()); + newAttributes.putAll(attributes); + ConfigurationEntry newEntry = new ConfigurationEntry(entry.getId(), entry.getType(), newAttributes, + entry.getChildrenIds(), _store); + _store.save(newEntry); + return true; + } + + private ConfigurationEntry findObjectByName(String objectName) + { + ConfigurationEntry root = _store.getRootEntry(); + return findObjectByName(root, objectName); + } + + private ConfigurationEntry findObjectByName(ConfigurationEntry entry, String objectName) + { + Map<String, Object> attributes = entry.getAttributes(); + if (attributes != null) + { + String name = (String) attributes.get("name"); + if (objectName.equals(name)) + { + return entry; + } + } + Set<UUID> childrenIds = entry.getChildrenIds(); + for (UUID uuid : childrenIds) + { + ConfigurationEntry child = _store.getEntry(uuid); + ConfigurationEntry result = findObjectByName(child, objectName); + if (result != null) + { + return result; + } + } + return null; + } + + private void addObjectConfiguration(UUID id, String type, Map<String, Object> attributes) + { + ConfigurationEntry entry = new ConfigurationEntry(id, type, attributes, Collections.<UUID> emptySet(), _store); + ConfigurationEntry root = _store.getRootEntry(); + Set<UUID> childrenIds = new HashSet<UUID>(root.getChildrenIds()); + childrenIds.add(id); + ConfigurationEntry newRoot = new ConfigurationEntry(root.getId(), root.getType(), root.getAttributes(), childrenIds, + _store); + _store.save(newRoot, entry); + } + + private boolean setObjectAttribute(ConfigurationEntry entry, String attributeName, Object value) + { + Map<String, Object> attributes = new HashMap<String, Object>(entry.getAttributes()); + attributes.put(attributeName, value); + ConfigurationEntry newEntry = new ConfigurationEntry(entry.getId(), entry.getType(), attributes, entry.getChildrenIds(), + _store); + _store.save(newEntry); + return true; + } + + public boolean isSaved() + { + return _saved; + } + + public void setSaved(boolean saved) + { + _saved = saved; + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/systest/GlobalTopicsTest.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java index 6297478883..9d5be775dc 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/GlobalTopicsTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java @@ -1,5 +1,4 @@ /* - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -16,16 +15,16 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ -package org.apache.qpid.systest; +package org.apache.qpid.test.utils; -public class GlobalTopicsTest extends GlobalQueuesTest +public interface TestSSLConstants { - @Override - public void setUp() throws Exception - { - CONFIG_SECTION = ".topics"; - super.setUp(); - } + String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; + String KEYSTORE_PASSWORD = "password"; + String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; + String TRUSTSTORE_PASSWORD = "password"; + + String BROKER_KEYSTORE = "test-profiles/test_resources/ssl/java_broker_keystore.jks"; + String BROKER_KEYSTORE_PASSWORD = "password"; } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java new file mode 100644 index 0000000000..c651d3ec7f --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.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.test.utils; + +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; + +public class TestUtils +{ + public static String dumpThreads() + { + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); + StringBuilder dump = new StringBuilder(); + dump.append(String.format("%n")); + for (ThreadInfo threadInfo : threadInfos) + { + dump.append(threadInfo); + } + + long[] deadLocks = threadMXBean.findDeadlockedThreads(); + if (deadLocks != null && deadLocks.length > 0) + { + ThreadInfo[] deadlockedThreads = threadMXBean.getThreadInfo(deadLocks); + dump.append(String.format("%n")); + dump.append("Deadlock is detected!"); + dump.append(String.format("%n")); + for (ThreadInfo threadInfo : deadlockedThreads) + { + dump.append(threadInfo); + } + } + return dump.toString(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java index 2b99289cd1..d77731d09f 100644 --- a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java +++ b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java @@ -30,8 +30,10 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * Utility to simplify the monitoring of Log4j file output @@ -42,6 +44,8 @@ import java.util.List; */ public class LogMonitor { + private static final Logger _logger = Logger.getLogger(LogMonitor.class); + // The file that the log statements will be written to. private final File _logfile; @@ -90,6 +94,8 @@ public class LogMonitor _appender.setImmediateFlush(true); Logger.getRootLogger().addAppender(_appender); } + + _logger.info("Created LogMonitor. Monitoring file: " + _logfile.getAbsolutePath()); } /** @@ -156,6 +162,39 @@ public class LogMonitor return results; } + public Map<String, List<String>> findMatches(String... pattern) throws IOException + { + + Map<String, List<String>> results= new HashMap<String, List<String>>(); + for (String p : pattern) + { + results.put(p, new LinkedList<String>()); + } + LineNumberReader reader = new LineNumberReader(new FileReader(_logfile)); + try + { + while (reader.ready()) + { + String line = reader.readLine(); + if (reader.getLineNumber() > _linesToSkip) + { + for (String p : pattern) + { + if (line.contains(p)) + { + results.get(p).add(line); + } + } + } + } + } + finally + { + reader.close(); + } + + return results; + } /** * Checks the log file for a given message to appear. If the caller * has previously called {@link #markDiscardPoint()}, lines up until the discard |