ARTEMIS-3969 Removing Extra tests from the codebase

This commit is contained in:
Clebert Suconic 2022-09-02 12:29:25 -04:00 committed by clebertsuconic
parent 90966ccdf1
commit f953408185
68 changed files with 6 additions and 15570 deletions

View File

@ -71,7 +71,7 @@ jobs:
- name: Build Main
run: |
mvn -s .github/maven-settings.xml -DskipTests -Derrorprone -Pdev -Pextra-tests -Pjmh install
mvn -s .github/maven-settings.xml -DskipTests -Derrorprone -Pdev -Pjmh install
- name: Build Examples (JDK11 / -Prelease)
if: matrix.java == '11'

View File

@ -16,11 +16,10 @@ before_install:
- rm -rf $HOME/.m2/repository/org/apache/activemq/artemis-*
# use 'install' so smoke-tests will work
# use '-Pextra-tests' to ensure extra-tests compiles even though they won't actually run
# By setting anything to org.apache.activemq.artemis.core.io.aio.AIOSequentialFileFactory.DISABLED we are disabling libaio loading on the testsuite
script:
- set -e
- mvn -s .github/maven-settings.xml -ntp -Dorg.apache.activemq.artemis.core.io.aio.AIOSequentialFileFactory.DISABLED=AnythingNotNull -Dmaven.test.redirectTestOutputToFile=true -Derrorprone -Pdev -Pfast-tests -Pextra-tests -Ptests-CI -Pjmh -B install
- mvn -s .github/maven-settings.xml -ntp -Dorg.apache.activemq.artemis.core.io.aio.AIOSequentialFileFactory.DISABLED=AnythingNotNull -Dmaven.test.redirectTestOutputToFile=true -Derrorprone -Pdev -Pfast-tests -Ptests-CI -Pjmh -B install
- cd examples
- mvn -s ../.github/maven-settings.xml verify -P${EXAMPLES_PROFILE} -B -q

View File

@ -9,7 +9,7 @@ agent and stored in JaCoCo exec files. All you need to do
is run the tests with `jacoco` maven profile.
```
mvn test -Ptests,extra-tests,jacoco
mvn test -Ptests,jacoco
```
## Generate JaCoCo reports

View File

@ -11,7 +11,7 @@ What does it mean to be reasonably confident? If the developer has run the same
builds are running they can be reasonably confident. Currently the [PR build](https://builds.apache.org/job/ActiveMQ-Artemis-PR-Build/)
runs this command:
mvn -Pfast-tests -Pextra-tests install
mvn -Pfast-tests install
However, if the changes are significant, touches a wide area of code, or even if the developer just wants a second
opinion they are encouraged to engage other members of the community to obtain an additional review prior to pushing.

View File

@ -16,6 +16,6 @@
# specific language governing permissions and limitations
# under the License.
mvn -Ptests,jacoco -DfailIfNoTests=false -Pextra-tests -DskipStyleCheck=true -DskipPerformanceTests=false -Dtest=$1 test
mvn -Ptests,jacoco -DfailIfNoTests=false -DskipStyleCheck=true -DskipPerformanceTests=false -Dtest=$1 test
mvn jacoco:merge -N -Pjacoco
mvn verify -Pjacoco-generate-report -DskipTests

View File

@ -16,4 +16,4 @@
# specific language governing permissions and limitations
# under the License.
mvn -Ptests -DfailIfNoTests=false -Ptests-retry -Pextra-tests -DskipStyleCheck=true -DskipPerformanceTests=false -DskipSoakTests=false -Dtest=$1 test
mvn -Ptests -DfailIfNoTests=false -Ptests-retry -DskipStyleCheck=true -DskipPerformanceTests=false -DskipSoakTests=false -Dtest=$1 test

View File

@ -1,291 +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.
-->
<!-- This test folder contains tests that are not part of the regular testsuite
because they use optional libraries such as LGPL or private ones.
They are optional and will validate extra functionality available through Service Integration
Example: Transaction Manager -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.activemq.tests</groupId>
<artifactId>artemis-tests-pom</artifactId>
<version>2.26.0-SNAPSHOT</version>
</parent>
<artifactId>extra-tests</artifactId>
<packaging>jar</packaging>
<name>ActiveMQ Artemis Extra Tests</name>
<properties>
<activemq.basedir>${project.basedir}/../..</activemq.basedir>
<jboss-jts.version>4.17.13.Final</jboss-jts.version>
<hornetq.version>2.4.7.Final</hornetq.version>
<openhft.core.version>1.4.9</openhft.core.version>
<openhft.affinity.version>3.0.6</openhft.affinity.version>
<openjdk.jmh.version>1.12</openjdk.jmh.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jboss.byteman</groupId>
<artifactId>byteman</artifactId>
<version>${byteman.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.byteman</groupId>
<artifactId>byteman-submit</artifactId>
<scope>test</scope>
<version>${byteman.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.byteman</groupId>
<artifactId>byteman-install</artifactId>
<scope>test</scope>
<version>${byteman.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-junit</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.byteman</groupId>
<artifactId>byteman-bmunit</artifactId>
<scope>test</scope>
<version>${byteman.version}</version>
<exclusions>
<exclusion>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-core-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq.tests</groupId>
<artifactId>integration-tests</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>org.apache.activemq.tests</groupId>
<artifactId>unit-tests</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-ra</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-hqclient-protocol</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-service-extensions</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>jakarta.resource</groupId>
<artifactId>jakarta.resource-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.transaction</groupId>
<artifactId>jakarta.transaction-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.jms</groupId>
<artifactId>jakarta.jms-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-processor</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.common</groupId>
<artifactId>wildfly-common</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-unit-test-support</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq.tests</groupId>
<artifactId>artemis-test-support</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!-- this is for the log assertion -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-commons</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-hornetq-protocol</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!-- Needed for JMS Bridge Tests -->
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-transaction-spi</artifactId>
<version>7.1.0.Final</version>
<exclusions>
<exclusion>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-commons</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-core-client</artifactId>
<version>${hornetq.version}</version>
</dependency>
<!-- Needed for XA tests -->
<dependency>
<groupId>org.jboss.jbossts.jts</groupId>
<artifactId>jbossjts-jacorb</artifactId>
<version>4.17.13.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${skipExtraTests}</skipTests>
<!-- ensure we don't inherit a byteman jar form any env settings -->
<environmentVariables>
<BYTEMAN_HOME />
</environmentVariables>
<systemProperties>
<property>
<name>com.arjuna.ats.arjuna.objectstore.objectStoreDir</name>
<value>target/ObjectStore</value>
</property>
<property>
<name>ObjectStoreEnvironmentBean.objectStoreDir</name>
<value>target/ObjectStore</value>
</property>
<!--
<property>
<name>org.jboss.byteman.home</name>
<value></value>
</property>
<property>
<name>org.jboss.byteman.verbose</name>
<value>true</value>
</property>
<property>
<name>org.jboss.byteman.contrib.bmunit.verbose</name>
<value>true</value>
</property>
<property>
<name>org.jboss.byteman.dump.generated.classes</name>
<value></value>
</property>
-->
</systemProperties>
<!-- make sure maven puts the byteman jar in the classpath rather than in a manifest jar -->
<useManifestOnlyJar>false</useManifestOnlyJar>
<!-- when upgrading this plugin from 2.4 to 2.18.1 <forkMode>once</forkMode> was replaced with these: -->
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<!--
<debugForkedProcess>true</debugForkedProcess>
-->
<!-- the option <parallel>false</parallel> is not supported after the plugin upgrade from 2.4 to 2.18.1 -->
<!--<argLine>${activemq-surefire-argline} -Dorg.jboss.byteman.verbose -Dorg.jboss.byteman.contrib.bmunit.verbose</argLine>-->
<!-- '-noverify' is needed here to fix VerifyErrors on ScaleDownFailoverTest and ScaleDownFailureTest (and their subclasses). I got the tip from https://issues.jboss.org/browse/BYTEMAN-248. -->
<argLine>${activemq-surefire-argline} -noverify</argLine>
</configuration>
</plugin>
<!-- Don't deploy artifacts for this module. It has non-permissive
dependencies and is only optionally used for local testing. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,30 +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.activemq.artemis.tests.extras;
import org.jboss.logging.BasicLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.MessageLogger;
@MessageLogger(projectCode = "AMQTEST")
public interface ExtrasTestLogger extends BasicLogger {
/**
* The integration test logger.
*/
ExtrasTestLogger LOGGER = Logger.getMessageLogger(ExtrasTestLogger.class, ExtrasTestLogger.class.getPackage().getName());
}

View File

@ -1,375 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.Message;
import javax.resource.ResourceException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.ra.ActiveMQResourceAdapter;
import org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec;
import org.apache.activemq.artemis.tests.integration.ra.ActiveMQRATestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ActiveMQMessageHandlerTest extends ActiveMQRATestBase {
@Override
protected boolean usePersistence() {
return true;
}
@Override
public boolean useSecurity() {
return false;
}
@Test
@BMRules(
rules = {
@BMRule(
name = "interrupt",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQSessionContext",
targetMethod = "xaEnd",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ActiveMQMessageHandlerTest.interrupt();")})
public void testSimpleMessageReceivedOnQueue() throws Exception {
ActiveMQResourceAdapter qResourceAdapter = newResourceAdapter();
resourceAdapter = qResourceAdapter;
MyBootstrapContext ctx = new MyBootstrapContext();
qResourceAdapter.setConnectorClassName(NETTY_CONNECTOR_FACTORY);
qResourceAdapter.start(ctx);
ActiveMQActivationSpec spec = new ActiveMQActivationSpec();
spec.setMaxSession(1);
spec.setCallTimeout(1000L);
spec.setResourceAdapter(qResourceAdapter);
spec.setUseJNDI(false);
spec.setDestinationType("javax.jms.Queue");
spec.setDestination(MDBQUEUE);
CountDownLatch latch = new CountDownLatch(1);
XADummyEndpoint endpoint = new XADummyEndpoint(latch, false);
DummyMessageEndpointFactory endpointFactory = new DummyMessageEndpointFactory(endpoint, true);
qResourceAdapter.endpointActivation(endpointFactory, spec);
ClientSession session = locator.createSessionFactory().createSession();
ClientProducer clientProducer = session.createProducer(MDBQUEUEPREFIXED);
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("teststring");
clientProducer.send(message);
session.close();
latch.await(5, TimeUnit.SECONDS);
assertNotNull(endpoint.lastMessage);
assertEquals(endpoint.lastMessage.getCoreMessage().getBodyBuffer().readString(), "teststring");
qResourceAdapter.endpointDeactivation(endpointFactory, spec);
qResourceAdapter.stop();
Binding binding = server.getPostOffice().getBinding(SimpleString.toSimpleString(MDBQUEUEPREFIXED));
assertEquals(1, getMessageCount(((Queue) binding.getBindable())));
server.stop();
server.start();
ClientSessionFactory factory = locator.createSessionFactory();
session = factory.createSession(true, true);
session.start();
ClientConsumer consumer = session.createConsumer(MDBQUEUEPREFIXED);
assertNotNull(consumer.receive(5000));
session.close();
}
@Test
@BMRules(
rules = {
@BMRule(
name = "interrupt",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQSessionContext",
targetMethod = "xaEnd",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ActiveMQMessageHandlerTest.interrupt();")})
public void testSimpleMessageReceivedOnQueueTwoPhase() throws Exception {
ActiveMQResourceAdapter qResourceAdapter = newResourceAdapter();
resourceAdapter = qResourceAdapter;
MyBootstrapContext ctx = new MyBootstrapContext();
qResourceAdapter.setConnectorClassName(NETTY_CONNECTOR_FACTORY);
qResourceAdapter.start(ctx);
ActiveMQActivationSpec spec = new ActiveMQActivationSpec();
spec.setMaxSession(1);
spec.setCallTimeout(1000L);
spec.setResourceAdapter(qResourceAdapter);
spec.setUseJNDI(false);
spec.setDestinationType("javax.jms.Queue");
spec.setDestination(MDBQUEUE);
CountDownLatch latch = new CountDownLatch(1);
XADummyEndpoint endpoint = new XADummyEndpoint(latch, true);
DummyMessageEndpointFactory endpointFactory = new DummyMessageEndpointFactory(endpoint, true);
qResourceAdapter.endpointActivation(endpointFactory, spec);
ClientSession session = locator.createSessionFactory().createSession();
ClientProducer clientProducer = session.createProducer(MDBQUEUEPREFIXED);
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("teststring");
clientProducer.send(message);
session.close();
latch.await(5, TimeUnit.SECONDS);
assertNotNull(endpoint.lastMessage);
assertEquals(endpoint.lastMessage.getCoreMessage().getBodyBuffer().readString(), "teststring");
qResourceAdapter.endpointDeactivation(endpointFactory, spec);
qResourceAdapter.stop();
Binding binding = server.getPostOffice().getBinding(SimpleString.toSimpleString(MDBQUEUEPREFIXED));
assertEquals(1, getMessageCount(((Queue) binding.getBindable())));
server.stop();
server.start();
ClientSessionFactory factory = locator.createSessionFactory();
session = factory.createSession(true, true);
session.start();
ClientConsumer consumer = session.createConsumer(MDBQUEUEPREFIXED);
assertNotNull(consumer.receive(5000));
session.close();
}
static volatile ActiveMQResourceAdapter resourceAdapter;
static boolean resourceAdapterStopped = false;
public static void interrupt() throws InterruptedException {
//Thread.currentThread().interrupt();
if (!resourceAdapterStopped) {
resourceAdapter.stop();
resourceAdapterStopped = true;
throw new InterruptedException("foo");
}
//Thread.currentThread().interrupt();
}
Transaction currentTX;
public class XADummyEndpoint extends DummyMessageEndpoint {
final boolean twoPhase;
ClientSession session;
int afterDeliveryCounts = 0;
public XADummyEndpoint(CountDownLatch latch, boolean twoPhase) throws SystemException {
super(latch);
this.twoPhase = twoPhase;
try {
session = locator.createSessionFactory().createSession(true, false, false);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
super.beforeDelivery(method);
try {
DummyTMLocator.tm.begin();
currentTX = DummyTMLocator.tm.getTransaction();
currentTX.enlistResource(xaResource);
if (twoPhase) {
currentTX.enlistResource(new DummyXAResource());
}
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public void onMessage(Message message) {
super.onMessage(message);
// try
// {
// lastMessage = (ActiveMQMessage) message;
// currentTX.enlistResource(session);
// ClientProducer prod = session.createProducer()
// }
// catch (Exception e)
// {
// e.printStackTrace();
// }
}
@Override
public void afterDelivery() throws ResourceException {
afterDeliveryCounts++;
try {
currentTX.commit();
} catch (Throwable e) {
//its unsure as to whether the EJB/JCA layer will handle this or throw it to us,
// either way we don't do anything else so its fine just to throw.
// NB this will only happen with 2 phase commit
throw new RuntimeException(e);
}
super.afterDelivery();
}
}
@Override
@Before
public void setUp() throws Exception {
resourceAdapter = null;
resourceAdapterStopped = false;
super.setUp();
DummyTMLocator.startTM();
}
@Override
@After
public void tearDown() throws Exception {
DummyTMLocator.stopTM();
super.tearDown();
}
public static class DummyTMLocator {
public static TransactionManagerImple tm;
public static void stopTM() {
try {
TransactionReaper.terminate(true);
TxControl.disable(true);
} catch (Exception e) {
e.printStackTrace();
}
tm = null;
}
public static void startTM() {
tm = new TransactionManagerImple();
TxControl.enable();
}
public TransactionManager getTM() {
return tm;
}
}
static class DummyXAResource implements XAResource {
@Override
public void commit(Xid xid, boolean b) throws XAException {
}
@Override
public void end(Xid xid, int i) throws XAException {
}
@Override
public void forget(Xid xid) throws XAException {
}
@Override
public int getTransactionTimeout() throws XAException {
return 0;
}
@Override
public boolean isSameRM(XAResource xaResource) throws XAException {
return false;
}
@Override
public int prepare(Xid xid) throws XAException {
return 0;
}
@Override
public Xid[] recover(int i) throws XAException {
return new Xid[0];
}
@Override
public void rollback(Xid xid) throws XAException {
}
@Override
public boolean setTransactionTimeout(int i) throws XAException {
return false;
}
@Override
public void start(Xid xid, int i) throws XAException {
}
}
}

View File

@ -1,248 +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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.json.JsonArray;
import org.apache.activemq.artemis.json.JsonObject;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.JsonUtil;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.integration.management.ManagementControlHelper;
import org.apache.activemq.artemis.tests.integration.management.ManagementTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ActiveMQServerControlMultiThreadTest extends ManagementTestBase {
private ActiveMQServer server;
private static volatile CountDownLatch delayCalled;
/**
* Aim: verify that no exceptions will occur if deleteAddress() is invoked when listAddress() is happening
*
* test delays the listAddress() operations; delay after the list of addresses are retrieved but before
* Json string (representing the addresses) is created.
*
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "Delay listAddress() by 2 secs ",
targetClass = "org.apache.activemq.artemis.core.postoffice.impl.PostOfficeImpl",
targetMethod = "getAddressInfo(org.apache.activemq.artemis.api.core.SimpleString)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ActiveMQServerControlMultiThreadTest.delay(2)")})
public void listAddressDuringDeleteAddress() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(1);
String addressName1 = "MyAddress_one";
String addressName2 = "MyAddress_two";
try {
//used to block thread, until the delay() has been called.
delayCalled = new CountDownLatch(1);
ActiveMQServerControl serverControl = createManagementControl();
serverControl.createAddress(addressName1, RoutingType.ANYCAST.toString());
serverControl.createAddress(addressName2, RoutingType.ANYCAST.toString());
executorService.submit(new Runnable() {
@Override
public void run() {
try {
// wait until the listAddress has retrieved list of addresses BUT has not
// created JSon string.
delayCalled.await();
serverControl.deleteAddress(addressName1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
String filter = createJsonFilter("", "", "");
String addressesAsJsonString = serverControl.listAddresses(filter, 1, 10);
JsonObject addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
JsonArray addressesArray = (JsonArray) addressesAsJsonObject.get("data");
// the deleteAddress() should have happened before the Json String was created
Assert.assertEquals("number of Addresses returned from query", 1, addressesArray.size());
Assert.assertEquals("check addresses username", addressName2.toString(), addressesArray.getJsonObject(0).getString("name"));
} finally {
executorService.shutdown();
}
}
/**
* Aim: verify that no exceptions will occur when a session is closed during listConsumers() operation
*
* test delays the listConsumer() BEFORE the Session information associated with the consumer is retrieved.
* During this delay the client session is closed.
*
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "Delay listConsumers() by 2 secs ",
targetClass = "org.apache.activemq.artemis.core.management.impl.view.ConsumerView",
targetMethod = "toJson(org.apache.activemq.artemis.core.server.ServerConsumer)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ActiveMQServerControlMultiThreadTest.delay(2)")})
public void listConsumersDuringSessionClose() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(1);
SimpleString addressName1 = new SimpleString("MyAddress_one");
SimpleString queueName1 = new SimpleString("my_queue_one");
ActiveMQServerControl serverControl = createManagementControl();
server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
// create a consumer
try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);
ClientSession session = csf.createSession()) {
ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
// add another consumer (on separate session)
ClientSession session_two = csf.createSession();
ClientConsumer consumer2_q1 = session_two.createConsumer(queueName1);
//first(normal) invocation - ensure 2 consumers returned
//used to block thread, until the delay() has been called.
delayCalled = new CountDownLatch(1);
String consumersAsJsonString = serverControl.listConsumers(createJsonFilter("", "", ""), 1, 10);
JsonObject consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
JsonArray consumersArray = (JsonArray) consumersAsJsonObject.get("data");
Assert.assertEquals("number of consumers returned from query", 2, consumersArray.size());
Assert.assertEquals("check consumer's queue", queueName1.toString(), consumersArray.getJsonObject(0).getString("queueName"));
Assert.assertNotEquals("check session", "", consumersArray.getJsonObject(0).getString("sessionName"));
//second invocation - close session during listConsumers()
//used to block thread, until the delay() has been called.
delayCalled = new CountDownLatch(1);
executorService.submit(new Runnable() {
@Override
public void run() {
try {
//wait until the delay occurs and close the session.
delayCalled.await();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
consumersAsJsonString = serverControl.listConsumers(createJsonFilter("", "", ""), 1, 10);
consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
consumersArray = (JsonArray) consumersAsJsonObject.get("data");
// session is closed before Json string is created - should only be one consumer returned
Assert.assertEquals("number of consumers returned from query", 1, consumersArray.size());
Assert.assertEquals("check consumer's queue", queueName1.toString(), consumersArray.getJsonObject(0).getString("queueName"));
Assert.assertNotEquals("check session", "", consumersArray.getJsonObject(0).getString("sessionName"));
} finally {
executorService.shutdown();
}
}
//notify delay has been called and wait for X seconds
public static void delay(int seconds) {
delayCalled.countDown();
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
Configuration config = createDefaultInVMConfig().setJMXManagementEnabled(true);
server = createServer(false, config);
server.setMBeanServer(mbeanServer);
server.start();
}
@Override
@After
public void tearDown() throws Exception {
super.tearDown();
server.stop();
}
protected ActiveMQServerControl createManagementControl() throws Exception {
return ManagementControlHelper.createActiveMQServerControl(mbeanServer);
}
private String createJsonFilter(String fieldName, String operationName, String value) {
HashMap<String, Object> filterMap = new HashMap<>();
filterMap.put("field", fieldName);
filterMap.put("operation", operationName);
filterMap.put("value", value);
JsonObject jsonFilterObject = JsonUtil.toJsonObject(filterMap);
return jsonFilterObject.toString();
}
}

View File

@ -1,45 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.util.UUID;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class AddressDeploymentFailedTest extends ActiveMQTestBase {
@Test
@BMRule(name = "blow up address deployment",
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "addOrUpdateAddressInfo(AddressInfo)",
targetLocation = "EXIT",
action = "throw new IllegalStateException(\"test exception\")")
public void testAddressDeploymentFailure() throws Exception {
ActiveMQServer server = createServer(false, createDefaultNettyConfig());
server.getConfiguration().addAddressConfiguration(new CoreAddressConfiguration().setName(UUID.randomUUID().toString()).addRoutingType(RoutingType.ANYCAST));
server.start();
assertTrue(server.getRemotingService().isStarted());
}
}

View File

@ -1,368 +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.activemq.artemis.tests.extras.byteman;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.activemq.artemis.api.core.ActiveMQTransactionOutcomeUnknownException;
import org.apache.activemq.artemis.api.core.ActiveMQTransactionRolledBackException;
import org.apache.activemq.artemis.api.core.ActiveMQUnBlockedException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
import org.apache.activemq.artemis.core.client.impl.ClientMessageImpl;
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal;
import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.transaction.impl.XidImpl;
import org.apache.activemq.artemis.tests.integration.cluster.failover.FailoverTestBase;
import org.apache.activemq.artemis.tests.integration.cluster.util.TestableServer;
import org.apache.activemq.artemis.tests.util.RandomUtil;
import org.apache.activemq.artemis.utils.UUIDGenerator;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class BMFailoverTest extends FailoverTestBase {
private static final Logger log = Logger.getLogger(BMFailoverTest.class);
private ServerLocator locator;
private ClientSessionFactoryInternal sf;
private ClientSessionFactoryInternal sf2;
public static TestableServer serverToStop;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
stopped = false;
locator = getServerLocator();
}
private static boolean stopped = false;
public static void stopAndThrow() throws ActiveMQUnBlockedException {
if (!stopped) {
try {
serverToStop.getServer().fail(true);
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stopped = true;
throw ActiveMQClientMessageBundle.BUNDLE.unblockingACall(null);
}
}
@Test
@BMRules(
rules = {
@BMRule(
name = "trace ActiveMQSessionContext xaEnd",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQSessionContext",
targetMethod = "xaEnd",
targetLocation = "AT EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.BMFailoverTest.stopAndThrow()")})
//https://bugzilla.redhat.com/show_bug.cgi?id=1152410
public void testFailOnEndAndRetry() throws Exception {
serverToStop = liveServer;
createSessionFactory();
ClientSession session = createSession(sf, true, false, false);
session.createQueue(new QueueConfiguration(FailoverTestBase.ADDRESS));
ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);
for (int i = 0; i < 100; i++) {
producer.send(createMessage(session, i, true));
}
ClientConsumer consumer = session.createConsumer(FailoverTestBase.ADDRESS);
Xid xid = RandomUtil.randomXid();
session.start(xid, XAResource.TMNOFLAGS);
session.start();
// Receive MSGs but don't ack!
for (int i = 0; i < 100; i++) {
ClientMessage message = consumer.receive(1000);
Assert.assertNotNull(message);
assertMessageBody(i, message);
Assert.assertEquals(i, message.getIntProperty("counter").intValue());
}
try {
//top level prepare
session.end(xid, XAResource.TMSUCCESS);
} catch (XAException e) {
try {
//top level abort
session.end(xid, XAResource.TMFAIL);
} catch (XAException e1) {
try {
//rollback
session.rollback(xid);
} catch (XAException e2) {
}
}
}
xid = RandomUtil.randomXid();
session.start(xid, XAResource.TMNOFLAGS);
for (int i = 0; i < 50; i++) {
ClientMessage message = consumer.receive(1000);
Assert.assertNotNull(message);
assertMessageBody(i, message);
Assert.assertEquals(i, message.getIntProperty("counter").intValue());
}
session.end(xid, XAResource.TMSUCCESS);
session.commit(xid, true);
}
@Test
@BMRules(
rules = {
@BMRule(
name = "trace clientsessionimpl commit",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "start(javax.transaction.xa.Xid, int)",
targetLocation = "AT EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.BMFailoverTest.serverToStop.getServer().stop(true)")})
public void testFailoverOnCommit2() throws Exception {
serverToStop = liveServer;
locator = getServerLocator();
SimpleString inQueue = new SimpleString("inQueue");
SimpleString outQueue = new SimpleString("outQueue");
createSessionFactory();
createSessionFactory2();
// closeable will take care of closing it
try (ClientSession session = sf.createSession(false, true, true);
ClientProducer sendInitialProducer = session.createProducer();) {
session.createQueue(new QueueConfiguration(inQueue));
session.createQueue(new QueueConfiguration(outQueue));
sendInitialProducer.send(inQueue, createMessage(session, 0, true));
}
ClientSession xaSessionRec = addClientSession(sf.createSession(true, false, false));
ClientConsumer consumer = addClientConsumer(xaSessionRec.createConsumer(inQueue));
byte[] globalTransactionId = UUIDGenerator.getInstance().generateStringUUID().getBytes();
Xid xidRec = new XidImpl("xa2".getBytes(), 1, globalTransactionId);
xaSessionRec.start();
xaSessionRec.getXAResource().start(xidRec, XAResource.TMNOFLAGS);
//failover is now occurring, receive, ack and end will be called whilst this is happening.
ClientMessageImpl m = (ClientMessageImpl) consumer.receive(5000);
assertNotNull(m);
log.debug("********************" + m.getIntProperty("counter"));
//the mdb would ack the message before calling onMessage()
m.acknowledge();
try {
//this may fail but thats ok, it depends on the race and when failover actually happens
xaSessionRec.end(xidRec, XAResource.TMSUCCESS);
} catch (XAException ignore) {
}
//we always reset the client on the RA
((ClientSessionInternal) xaSessionRec).resetIfNeeded();
// closeable will take care of closing it
try (ClientSession session = sf.createSession(false, true, true);
ClientProducer sendInitialProducer = session.createProducer();) {
sendInitialProducer.send(inQueue, createMessage(session, 0, true));
}
//now receive and send a message successfully
globalTransactionId = UUIDGenerator.getInstance().generateStringUUID().getBytes();
xidRec = new XidImpl("xa4".getBytes(), 1, globalTransactionId);
xaSessionRec.getXAResource().start(xidRec, XAResource.TMNOFLAGS);
Binding binding = backupServer.getServer().getPostOffice().getBinding(inQueue);
Queue inQ = (Queue) binding.getBindable();
m = (ClientMessageImpl) consumer.receive(5000);
assertNotNull(m);
//the mdb would ack the message before calling onMessage()
m.acknowledge();
log.debug("********************" + m.getIntProperty("counter"));
xaSessionRec.getXAResource().end(xidRec, XAResource.TMSUCCESS);
xaSessionRec.getXAResource().prepare(xidRec);
xaSessionRec.getXAResource().commit(xidRec, false);
//let's close the consumer so anything pending is handled
consumer.close();
assertEquals(1, getMessageCount(inQ));
}
@Test
@BMRules(
rules = {
@BMRule(
name = "trace clientsessionimpl commit",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "commit",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.BMFailoverTest.serverToStop.getServer().stop(true)")})
public void testFailoverOnCommit() throws Exception {
serverToStop = liveServer;
locator = getServerLocator();
createSessionFactory();
ClientSession session = createSessionAndQueue();
ClientProducer producer = addClientProducer(session.createProducer(FailoverTestBase.ADDRESS));
sendMessages(session, producer, 10);
try {
session.commit();
fail("should have thrown an exception");
} catch (ActiveMQTransactionOutcomeUnknownException e) {
//pass
}
sendMessages(session, producer, 10);
session.commit();
Queue bindable = (Queue) backupServer.getServer().getPostOffice().getBinding(FailoverTestBase.ADDRESS).getBindable();
assertEquals(10, getMessageCount(bindable));
}
@Test
@BMRules(
rules = {
@BMRule(
name = "trace clientsessionimpl commit",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "commit",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.BMFailoverTest.serverToStop.getServer().stop(true)")})
public void testFailoverOnReceiveCommit() throws Exception {
serverToStop = liveServer;
locator = getServerLocator();
createSessionFactory();
ClientSession session = createSessionAndQueue();
ClientSession sendSession = createSession(sf, true, true);
ClientProducer producer = addClientProducer(sendSession.createProducer(FailoverTestBase.ADDRESS));
sendMessages(sendSession, producer, 10);
ClientConsumer consumer = session.createConsumer(FailoverTestBase.ADDRESS);
session.start();
for (int i = 0; i < 10; i++) {
ClientMessage m = consumer.receive(500);
assertNotNull(m);
m.acknowledge();
}
try {
session.commit();
fail("should have thrown an exception");
} catch (ActiveMQTransactionOutcomeUnknownException e) {
//pass
} catch (ActiveMQTransactionRolledBackException e1) {
//pass
}
Queue bindable = (Queue) backupServer.getServer().getPostOffice().getBinding(FailoverTestBase.ADDRESS).getBindable();
assertEquals(10, getMessageCount(bindable));
}
@Override
protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live) {
return getNettyAcceptorTransportConfiguration(live);
}
@Override
protected TransportConfiguration getConnectorTransportConfiguration(final boolean live) {
return getNettyConnectorTransportConfiguration(live);
}
private ClientSession createSessionAndQueue() throws Exception {
ClientSession session = createSession(sf, false, false);
session.createQueue(new QueueConfiguration(FailoverTestBase.ADDRESS));
return session;
}
private ClientSession createXASessionAndQueue() throws Exception {
ClientSession session = addClientSession(sf.createSession(true, true, true));
session.createQueue(new QueueConfiguration(FailoverTestBase.ADDRESS));
return session;
}
protected ClientSession createSession(ClientSessionFactory sf1,
boolean autoCommitSends,
boolean autoCommitAcks) throws Exception {
return addClientSession(sf1.createSession(autoCommitSends, autoCommitAcks));
}
protected ClientSession createSession(ClientSessionFactory sf1,
boolean xa,
boolean autoCommitSends,
boolean autoCommitAcks) throws Exception {
return addClientSession(sf1.createSession(xa, autoCommitSends, autoCommitAcks));
}
private void createSessionFactory() throws Exception {
locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setReconnectAttempts(15);
sf = createSessionFactoryAndWaitForTopology(locator, 2);
}
private void createSessionFactory2() throws Exception {
sf2 = createSessionFactoryAndWaitForTopology(locator, 2);
}
}

View File

@ -1,142 +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.activemq.artemis.tests.extras.byteman;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.BridgeConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.cluster.impl.BridgeImpl;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class BridgeServerLocatorConfigurationTest extends ActiveMQTestBase {
private static final long BRIDGE_TTL = 1234L;
private static final String BRIDGE_NAME = "bridge1";
protected boolean isNetty() {
return false;
}
private String getConnector() {
if (isNetty()) {
return NETTY_CONNECTOR_FACTORY;
}
return INVM_CONNECTOR_FACTORY;
}
@Test
@BMRule(name = "check connection ttl",
targetClass = "org.apache.activemq.artemis.tests.extras.byteman.BridgeServerLocatorConfigurationTest",
targetMethod = "getBridgeTTL(ActiveMQServer, String)", targetLocation = "EXIT",
action = "$! = $0.getConfiguredBridge($1).serverLocator.getConnectionTTL();")
/**
* Checks the connection ttl by using byteman to override the methods on this class to return the value of private variables in the Bridge.
* @throws Exception
*
* The byteman rule on this test overwrites the {@link #getBridgeTTL} method to retrieve the bridge called {@link @BRIDGE_NAME}.
* It the overrides the return value to be the value of the connection ttl. Note that the unused String parameter is required to
* ensure that byteman populates the $1 variable, otherwise it will not bind correctly.
*/ public void testConnectionTTLOnBridge() throws Exception {
Map<String, Object> server0Params = new HashMap<>();
ActiveMQServer serverWithBridge = createClusteredServerWithParams(isNetty(), 0, true, server0Params);
Map<String, Object> server1Params = new HashMap<>();
if (isNetty()) {
server1Params.put("port", org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.DEFAULT_PORT + 1);
} else {
server1Params.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
}
ActiveMQServer server1 = createClusteredServerWithParams(isNetty(), 1, true, server1Params);
try {
final String testAddress = "testAddress";
final String queueName0 = "queue0";
final String forwardAddress = "forwardAddress";
final String queueName1 = "queue1";
Map<String, TransportConfiguration> connectors = new HashMap<>();
TransportConfiguration server1tc = new TransportConfiguration(getConnector(), server1Params);
connectors.put(server1tc.getName(), server1tc);
serverWithBridge.getConfiguration().setConnectorConfigurations(connectors);
ArrayList<String> staticConnectors = new ArrayList<>();
staticConnectors.add(server1tc.getName());
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration().setName(BRIDGE_NAME).setQueueName(queueName0).setForwardingAddress(forwardAddress).setConnectionTTL(BRIDGE_TTL).setRetryInterval(1000).setReconnectAttempts(0).setReconnectAttemptsOnSameNode(0).setConfirmationWindowSize(1024).setStaticConnectors(staticConnectors);
List<BridgeConfiguration> bridgeConfigs = new ArrayList<>();
bridgeConfigs.add(bridgeConfiguration);
serverWithBridge.getConfiguration().setBridgeConfigurations(bridgeConfigs);
serverWithBridge.getConfiguration().addQueueConfiguration(new QueueConfiguration(queueName0).setAddress(testAddress));
server1.getConfiguration().addQueueConfiguration(new QueueConfiguration(queueName1).setAddress(forwardAddress));
server1.start();
waitForServerToStart(server1);
serverWithBridge.start();
waitForServerToStart(serverWithBridge);
long bridgeTTL = getBridgeTTL(serverWithBridge, BRIDGE_NAME);
assertEquals(BRIDGE_TTL, bridgeTTL);
} finally {
serverWithBridge.stop();
server1.stop();
}
}
/**
* Method for byteman to wrap around and do its magic with to return the ttl from private members
* rather than -1
*
* @param bridgeServer
* @param bridgeName
* @return
*/
private long getBridgeTTL(ActiveMQServer bridgeServer, String bridgeName) {
return -1L;
}
/**
* Byteman seems to need this method so that it gets back the concrete type not the interface
*
* @param bridgeServer
* @return
*/
private BridgeImpl getConfiguredBridge(ActiveMQServer bridgeServer) {
return getConfiguredBridge(bridgeServer, BRIDGE_NAME);
}
private BridgeImpl getConfiguredBridge(ActiveMQServer bridgeServer, String bridgeName) {
return (BridgeImpl) bridgeServer.getClusterManager().getBridges().get(bridgeName);
}
}

View File

@ -1,231 +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.activemq.artemis.tests.extras.byteman;
import java.util.concurrent.CountDownLatch;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.management.CoreNotificationType;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.core.server.cluster.MessageFlowRecord;
import org.apache.activemq.artemis.core.server.cluster.impl.ClusterConnectionBridge;
import org.apache.activemq.artemis.core.server.cluster.impl.ClusterConnectionImpl;
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.tests.integration.cluster.distribution.ClusterTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* This will simulate a failure of a failure.
* The bridge could eventually during a race or multiple failures not be able to reconnect because it failed again.
* this should make the bridge to always reconnect itself.
*/
@RunWith(BMUnitRunner.class)
public class ClusteredBridgeReconnectTest extends ClusterTestBase {
static ThreadLocal<Boolean> inConnect = new ThreadLocal<>();
public static void enterConnect() {
inConnect.set(Boolean.TRUE);
}
public static void exitConnect() {
inConnect.set(null);
}
public static volatile boolean shouldFail = false;
public static void send() {
if (inConnect.get() != null) {
if (shouldFail) {
shouldFail = false;
throw new NullPointerException("just because it's a test...");
}
}
}
@Test
@BMRules(
rules = {
@BMRule(
name = "enter",
targetClass = "org.apache.activemq.artemis.core.server.cluster.impl.BridgeImpl",
targetMethod = "connect",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredBridgeReconnectTest.enterConnect();"),
@BMRule(
name = "exit",
targetClass = "org.apache.activemq.artemis.core.server.cluster.impl.BridgeImpl",
targetMethod = "connect",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredBridgeReconnectTest.exitConnect();"),
@BMRule(
name = "send",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ChannelImpl",
targetMethod = "send(org.apache.activemq.artemis.core.protocol.core.Packet)",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredBridgeReconnectTest.send();")})
public void testReconnectBridge() throws Exception {
setupServer(0, isFileStorage(), isNetty());
setupServer(1, isFileStorage(), isNetty());
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 0, 1);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 1, 0);
startServers(0, 1);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
createQueue(0, "queues.testaddress", "queue0", null, true);
createQueue(1, "queues.testaddress", "queue0", null, true);
addConsumer(0, 0, "queue0", null);
addConsumer(1, 1, "queue0", null);
waitForBindings(0, "queues.testaddress", 1, 1, true);
waitForBindings(1, "queues.testaddress", 1, 1, true);
waitForBindings(0, "queues.testaddress", 1, 1, false);
waitForBindings(1, "queues.testaddress", 1, 1, false);
ClientSession session0 = sfs[0].createSession();
ClientSession session1 = sfs[0].createSession();
session0.start();
session1.start();
ClientProducer producer = session0.createProducer("queues.testaddress");
int NUMBER_OF_MESSAGES = 100;
Assert.assertEquals(1, servers[0].getClusterManager().getClusterConnections().size());
ClusterConnectionImpl connection = servers[0].getClusterManager().getClusterConnections().toArray(new ClusterConnectionImpl[0])[0];
Assert.assertEquals(1, connection.getRecords().size());
MessageFlowRecord record = connection.getRecords().values().toArray(new MessageFlowRecord[1])[0];
ClusterConnectionBridge bridge = (ClusterConnectionBridge) record.getBridge();
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
ClientMessage msg = session0.createMessage(true);
producer.send(msg);
session0.commit();
if (i == 17) {
shouldFail = true;
bridge.getSessionFactory().getConnection().fail(new ActiveMQException("failed once!"));
}
}
int cons0Count = 0, cons1Count = 0;
while (true) {
ClientMessage msg = consumers[0].getConsumer().receive(1000);
if (msg == null) {
break;
}
cons0Count++;
msg.acknowledge();
session0.commit();
}
while (true) {
ClientMessage msg = consumers[1].getConsumer().receive(1000);
if (msg == null) {
break;
}
cons1Count++;
msg.acknowledge();
session1.commit();
}
Assert.assertEquals("cons0 = " + cons0Count + ", cons1 = " + cons1Count, NUMBER_OF_MESSAGES, cons0Count + cons1Count);
session0.commit();
session1.commit();
stopServers(0, 1);
}
static CountDownLatch latch;
static CountDownLatch latch2;
static Thread main;
public static void pause(SimpleString clusterName) {
if (clusterName.toString().startsWith("queue0")) {
try {
latch2.countDown();
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void pause2(Notification notification) {
if (notification.getType() == CoreNotificationType.BINDING_REMOVED) {
SimpleString clusterName = notification.getProperties().getSimpleStringProperty(ManagementHelper.HDR_CLUSTER_NAME);
boolean inMain = main == Thread.currentThread();
if (clusterName.toString().startsWith("queue0") && !inMain) {
try {
latch2.countDown();
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void restart2() {
latch.countDown();
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
shouldFail = false;
}
@Override
@After
public void tearDown() throws Exception {
closeAllConsumers();
closeAllSessionFactories();
closeAllServerLocatorsFactories();
super.tearDown();
}
public boolean isNetty() {
return true;
}
}

View File

@ -1,380 +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.activemq.artemis.tests.extras.byteman;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.ActiveMQNonExistentQueueException;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.management.CoreNotificationType;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
import org.apache.activemq.artemis.core.server.group.impl.GroupingHandlerConfiguration;
import org.apache.activemq.artemis.core.server.group.impl.Response;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.tests.integration.cluster.distribution.ClusterTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ClusteredGroupingTest extends ClusterTestBase {
@Test
@BMRules(
rules = {
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.LocalGroupingHandler",
targetMethod = "removeGrouping",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.pause($1);"),
@BMRule(
name = "blow-up2",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.GroupHandlingAbstract",
targetMethod = "forceRemove",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.restart2();")})
public void test2serversLocalGoesDown() throws Exception {
setupServer(0, isFileStorage(), isNetty());
setupServer(1, isFileStorage(), isNetty());
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 0, 1);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 1, 0);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.LOCAL, 0);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 1);
startServers(0, 1);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
createQueue(0, "queues.testaddress", "queue0", null, true);
createQueue(1, "queues.testaddress", "queue0", null, true);
addConsumer(0, 1, "queue0", null);
waitForBindings(0, "queues.testaddress", 1, 0, true);
waitForBindings(1, "queues.testaddress", 1, 1, true);
waitForBindings(0, "queues.testaddress", 1, 1, false);
waitForBindings(1, "queues.testaddress", 1, 0, false);
sendWithProperty(0, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
latch = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
crashAndWaitForFailure(getServer(1));
assertTrue(latch2.await(20000, TimeUnit.MILLISECONDS));
try {
try {
sendWithProperty(0, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
} catch (ActiveMQNonExistentQueueException e) {
fail("did not handle removal of queue");
}
} finally {
latch.countDown();
}
}
@Test
@BMRules(
rules = {
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.RemoteGroupingHandler",
targetMethod = "onNotification",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.pause2($1);"),
@BMRule(name = "blow-up2",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.RemoteGroupingHandler",
targetMethod = "remove",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.restart2();")})
public void test3serversLocalGoesDown() throws Exception {
setupServer(0, isFileStorage(), isNetty());
setupServer(1, isFileStorage(), isNetty());
setupServer(2, isFileStorage(), isNetty());
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 0, 1, 2);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 1, 0, 2);
setupClusterConnection("cluster2", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 2, 0, 1);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.LOCAL, 0);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 1);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 2);
startServers(0, 1, 2);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
setupSessionFactory(2, isNetty());
createQueue(0, "queues.testaddress", "queue0", null, true);
createQueue(1, "queues.testaddress", "queue0", null, true);
createQueue(2, "queues.testaddress", "queue0", null, true);
addConsumer(0, 2, "queue0", null);
waitForBindings(0, "queues.testaddress", 1, 0, true);
waitForBindings(1, "queues.testaddress", 1, 0, true);
waitForBindings(2, "queues.testaddress", 1, 1, true);
waitForBindings(0, "queues.testaddress", 2, 1, false);
waitForBindings(1, "queues.testaddress", 2, 1, false);
waitForBindings(2, "queues.testaddress", 2, 0, false);
sendWithProperty(1, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
latch = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
main = Thread.currentThread();
crashAndWaitForFailure(getServer(2));
assertTrue(latch2.await(20000, TimeUnit.MILLISECONDS));
try {
try {
sendWithProperty(1, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
} catch (ActiveMQNonExistentQueueException e) {
fail("did not handle removal of queue");
}
} finally {
latch.countDown();
}
assertHandlersAreSame(getServer(0), getServer(1));
}
@Test
@BMRules(
rules = {
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.LocalGroupingHandler",
targetMethod = "onNotification",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.pause2($1);"),
@BMRule(name = "blow-up2",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.LocalGroupingHandler",
targetMethod = "remove",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.restart2();")})
public void testLocal3serversLocalGoesDown() throws Exception {
setupServer(0, isFileStorage(), isNetty());
setupServer(1, isFileStorage(), isNetty());
setupServer(2, isFileStorage(), isNetty());
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 0, 1, 2);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 1, 0, 2);
setupClusterConnection("cluster2", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 2, 0, 1);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.LOCAL, 0);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 1);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 2);
startServers(0, 1, 2);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
setupSessionFactory(2, isNetty());
createQueue(0, "queues.testaddress", "queue0", null, true);
createQueue(1, "queues.testaddress", "queue0", null, true);
createQueue(2, "queues.testaddress", "queue0", null, true);
addConsumer(0, 2, "queue0", null);
waitForBindings(0, "queues.testaddress", 1, 0, true);
waitForBindings(1, "queues.testaddress", 1, 0, true);
waitForBindings(2, "queues.testaddress", 1, 1, true);
waitForBindings(0, "queues.testaddress", 2, 1, false);
waitForBindings(1, "queues.testaddress", 2, 1, false);
waitForBindings(2, "queues.testaddress", 2, 0, false);
sendWithProperty(0, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
latch = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
main = Thread.currentThread();
crashAndWaitForFailure(getServer(2));
assertTrue(latch2.await(20000, TimeUnit.MILLISECONDS));
try {
try {
sendWithProperty(0, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
} catch (ActiveMQNonExistentQueueException e) {
fail("did not handle removal of queue");
}
} finally {
latch.countDown();
}
assertHandlersAreSame(getServer(0), getServer(1));
}
@Test
@BMRules(
rules = {
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.LocalGroupingHandler",
targetMethod = "onNotification",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.pause2($1);"),
@BMRule(name = "blow-up2",
targetClass = "org.apache.activemq.artemis.core.server.group.impl.LocalGroupingHandler",
targetMethod = "remove",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ClusteredGroupingTest.restart2();")})
public void testLocal4serversLocalGoesDown() throws Exception {
setupServer(0, isFileStorage(), isNetty());
setupServer(1, isFileStorage(), isNetty());
setupServer(2, isFileStorage(), isNetty());
setupServer(3, isFileStorage(), isNetty());
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 0, 1, 2, 3);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 1, 0, 2, 3);
setupClusterConnection("cluster2", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 2, 0, 1, 3);
setupClusterConnection("cluster3", "queues", MessageLoadBalancingType.ON_DEMAND, 1, -1, 500, isNetty(), 3, 1, 2, 3);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.LOCAL, 0);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 1);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 2);
setUpGroupHandler(GroupingHandlerConfiguration.TYPE.REMOTE, 3);
startServers(0, 1, 2, 3);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
setupSessionFactory(2, isNetty());
setupSessionFactory(3, isNetty());
createQueue(0, "queues.testaddress", "queue0", null, true);
createQueue(1, "queues.testaddress", "queue0", null, true);
createQueue(2, "queues.testaddress", "queue0", null, true);
createQueue(3, "queues.testaddress", "queue0", null, true);
addConsumer(0, 2, "queue0", null);
waitForBindings(0, "queues.testaddress", 1, 0, true);
waitForBindings(1, "queues.testaddress", 1, 0, true);
waitForBindings(2, "queues.testaddress", 1, 1, true);
waitForBindings(3, "queues.testaddress", 1, 0, true);
waitForBindings(0, "queues.testaddress", 3, 1, false);
waitForBindings(1, "queues.testaddress", 3, 1, false);
waitForBindings(2, "queues.testaddress", 3, 0, false);
waitForBindings(3, "queues.testaddress", 3, 1, false);
sendWithProperty(0, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
latch = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
main = Thread.currentThread();
crashAndWaitForFailure(getServer(2));
assertTrue(latch2.await(20000, TimeUnit.MILLISECONDS));
try {
try {
sendWithProperty(0, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
} catch (ActiveMQNonExistentQueueException e) {
fail("did not handle removal of queue");
}
} finally {
latch.countDown();
}
//now restart server
getServer(2).start();
waitForBindings(2, "queues.testaddress", 1, 0, true);
waitForBindings(2, "queues.testaddress", 3, 0, false);
sendWithProperty(3, "queues.testaddress", 1, true, Message.HDR_GROUP_ID, new SimpleString("id1"));
Thread.sleep(2000);
assertHandlersAreSame(getServer(0), getServer(1), getServer(2), getServer(3));
}
private void assertHandlersAreSame(ActiveMQServer server, ActiveMQServer... qServers) {
SimpleString id = server.getGroupingHandler().getProposal(new SimpleString("id1.queue0"), false).getClusterName();
for (ActiveMQServer qServer : qServers) {
Response proposal = qServer.getGroupingHandler().getProposal(new SimpleString("id1.queue0"), false);
if (proposal != null) {
assertEquals(qServer.getIdentity() + " is incorrect", id, proposal.getChosenClusterName());
}
}
}
static CountDownLatch latch;
static CountDownLatch latch2;
static Thread main;
public static void pause(SimpleString clusterName) {
if (clusterName.toString().startsWith("queue0")) {
try {
latch2.countDown();
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void pause2(Notification notification) {
if (notification.getType() == CoreNotificationType.BINDING_REMOVED) {
SimpleString clusterName = notification.getProperties().getSimpleStringProperty(ManagementHelper.HDR_CLUSTER_NAME);
boolean inMain = main == Thread.currentThread();
if (clusterName.toString().startsWith("queue0") && !inMain) {
try {
latch2.countDown();
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void restart2() {
latch.countDown();
}
public boolean isNetty() {
return true;
}
}

View File

@ -1,259 +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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.XAConnection;
import javax.jms.XAConnectionFactory;
import javax.jms.XASession;
import javax.transaction.xa.XAResource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.core.transaction.impl.XidImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQSession;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* This test will force two consumers to be waiting on close and introduce a race I saw in a production system
*/
@RunWith(BMUnitRunner.class)
public class ConcurrentDeliveryCancelTest extends JMSTestBase {
private static final Logger log = Logger.getLogger(ConcurrentDeliveryCancelTest.class);
// used to wait the thread to align at the same place and create the race
private static final ReusableLatch latchEnter = new ReusableLatch(2);
// used to start
private static final ReusableLatch latchFlag = new ReusableLatch(1);
public static void enterCancel() {
try {
latchEnter.countDown();
latchFlag.await(1, TimeUnit.SECONDS);
} catch (Throwable ignored) {
ignored.printStackTrace();
}
}
public static void resetLatches(int numberOfThreads) {
latchEnter.setCount(numberOfThreads);
latchFlag.setCount(1);
}
@Override
protected boolean usePersistence() {
return true;
}
@Test
@BMRules(
rules = {
@BMRule(
name = "enterCancel-holdThere",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl",
targetMethod = "close",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ConcurrentDeliveryCancelTest.enterCancel();")})
public void testConcurrentCancels() throws Exception {
log.debug(server.getConfiguration().getJournalLocation().toString());
server.getAddressSettingsRepository().clear();
AddressSettings settings = new AddressSettings();
settings.setMaxDeliveryAttempts(-1);
server.getAddressSettingsRepository().addMatch("#", settings);
ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactory("tcp://localhost:61616", "test");
cf.setReconnectAttempts(0);
cf.setRetryInterval(10);
log.debug(".....");
for (ServerSession srvSess : server.getSessions()) {
log.debug(srvSess);
}
String queueName = RandomUtil.randomString();
Queue queue = createQueue(queueName);
int numberOfMessages = 100;
{
Connection connection = cf.createConnection();
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
MessageProducer producer = session.createProducer(queue);
for (int i = 0; i < numberOfMessages; i++) {
TextMessage msg = session.createTextMessage("message " + i);
msg.setIntProperty("i", i);
producer.send(msg);
}
session.commit();
connection.close();
}
for (int i = 0; i < 10; i++) {
XAConnectionFactory xacf = ActiveMQJMSClient.createConnectionFactory("tcp://localhost:61616", "test");
final XAConnection connection = xacf.createXAConnection();
final XASession theSession = connection.createXASession();
((ActiveMQSession) theSession).getCoreSession().addMetaData("theSession", "true");
connection.start();
final MessageConsumer consumer = theSession.createConsumer(queue);
XidImpl xid = newXID();
theSession.getXAResource().start(xid, XAResource.TMNOFLAGS);
theSession.getXAResource().setTransactionTimeout(1); // I'm setting a small timeout just because I'm lazy to call end myself
for (int msg = 0; msg < 11; msg++) {
Assert.assertNotNull(consumer.receiveNoWait());
}
log.debug(".....");
final List<ServerSession> serverSessions = new LinkedList<>();
// We will force now the failure simultaneously from several places
for (ServerSession srvSess : server.getSessions()) {
if (srvSess.getMetaData("theSession") != null) {
log.debug(srvSess);
serverSessions.add(srvSess);
}
}
latchFlag.countDown();
latchFlag.countUp();
latchEnter.countUp();
latchEnter.countUp();
List<Thread> threads = new LinkedList<>();
threads.add(new Thread("ConsumerCloser") {
@Override
public void run() {
try {
log.debug(Thread.currentThread().getName() + " closing consumer");
consumer.close();
log.debug(Thread.currentThread().getName() + " closed consumer");
} catch (Exception e) {
e.printStackTrace();
}
}
});
threads.add(new Thread("SessionCloser") {
@Override
public void run() {
for (ServerSession sess : serverSessions) {
log.debug("Thread " + Thread.currentThread().getName() + " starting");
try {
// A session.close could sneak in through failover or some other scenarios.
// a call to RemotingConnection.fail wasn't replicating the issue.
// I needed to call Session.close() directly to replicate what was happening in production
sess.close(true);
} catch (Exception e) {
e.printStackTrace();
}
log.debug("Thread " + Thread.currentThread().getName() + " done");
}
}
});
for (Thread t : threads) {
t.start();
}
latchEnter.await(1, TimeUnit.SECONDS);
latchFlag.countDown();
for (Thread t : threads) {
t.join(5000);
Assert.assertFalse(t.isAlive());
}
connection.close();
}
Connection connection = cf.createConnection();
try {
connection.setClientID("myID");
Thread.sleep(5000); // I am too lazy to call end on all the transactions
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = session.createConsumer(queue);
HashMap<Integer, AtomicInteger> mapCount = new HashMap<>();
while (true) {
TextMessage message = (TextMessage) consumer.receiveNoWait();
if (message == null) {
break;
}
Integer value = message.getIntProperty("i");
AtomicInteger count = mapCount.get(value);
if (count == null) {
count = new AtomicInteger(0);
mapCount.put(message.getIntProperty("i"), count);
}
count.incrementAndGet();
}
boolean failed = false;
for (int i = 0; i < numberOfMessages; i++) {
AtomicInteger count = mapCount.get(i);
if (count == null) {
log.debug("Message " + i + " not received");
failed = true;
} else if (count.get() > 1) {
log.debug("Message " + i + " received " + count.get() + " times");
failed = true;
}
}
Assert.assertFalse("test failed, look at the system.out of the test for more information", failed);
} finally {
connection.close();
}
}
}

View File

@ -1,112 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class CriticalAnalyzerFaultInjectionTest extends JMSTestBase {
// Critical Analyzer Settings
private static long CHECK_PERIOD = 100;
private static long TIMEOUT = 1000;
public static long TEST_TIMEOUT = 5000;
private SimpleString address = SimpleString.toSimpleString("faultInjectionTestAddress");
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server.addAddressInfo(new AddressInfo(address, RoutingType.ANYCAST));
server.createQueue(new QueueConfiguration(address).setRoutingType(RoutingType.ANYCAST));
conn = nettyCf.createConnection();
}
/*
Checks every 100ms timesout after 3000ms. Test should wait no longer than 3100s + Shutdown time.
*/
@Override
protected Configuration createDefaultConfig(boolean netty) throws Exception {
return super.createDefaultConfig(netty)
.setCriticalAnalyzerPolicy(CriticalAnalyzerPolicy.SHUTDOWN)
.setCriticalAnalyzer(true)
.setCriticalAnalyzerCheckPeriod(CHECK_PERIOD)
.setCriticalAnalyzerTimeout(TIMEOUT)
.setJournalType(JournalType.NIO);
}
@Override
public boolean usePersistence() {
return true;
}
@BMRules(
rules = {
@BMRule(
name = "Sync file data hangs",
targetClass = "org.apache.activemq.artemis.core.io.nio.NIOSequentialFile",
targetMethod = "sync",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.CriticalAnalyzerFaultInjectionTest.methodHang();")})
@Test(timeout = 60000)
public void testSlowDiskSync() throws Exception {
sendConsumeDurableMessage();
Wait.waitFor(() -> !server.isStarted(), WAIT_TIMEOUT * 5);
assertFalse(server.isStarted());
}
private void sendConsumeDurableMessage() throws Exception {
try {
Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue jmsQueue = s.createQueue(address.toString());
MessageProducer p = s.createProducer(jmsQueue);
p.setDeliveryMode(DeliveryMode.PERSISTENT);
conn.start();
p.send(s.createTextMessage("payload"));
} catch (JMSException expected) {
} finally {
if (conn != null) {
conn.close();
}
}
}
public static void methodHang() throws InterruptedException {
Thread.sleep(TEST_TIMEOUT);
}
}

View File

@ -1,208 +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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
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;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@RunWith(BMUnitRunner.class)
public class DisconnectOnCriticalFailureTest extends JMSTestBase {
private static AtomicBoolean corruptPacket = new AtomicBoolean(false);
@After
@Override
public void tearDown() throws Exception {
corruptPacket.set(false);
super.tearDown();
}
@Test
@BMRules(
rules = {
@BMRule(
name = "Corrupt Decoding",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.PacketDecoder",
targetMethod = "decode(byte)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.DisconnectOnCriticalFailureTest.doThrow();")})
public void testSendDisconnect() throws Exception {
createQueue("queue1");
final Connection producerConnection = nettyCf.createConnection();
final CountDownLatch latch = new CountDownLatch(1);
try {
producerConnection.setExceptionListener(new ExceptionListener() {
@Override
public void onException(JMSException e) {
latch.countDown();
}
});
corruptPacket.set(true);
producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
assertTrue(latch.await(5, TimeUnit.SECONDS));
} finally {
corruptPacket.set(false);
if (producerConnection != null) {
producerConnection.close();
}
}
}
@Test
@BMRules(
rules = {
@BMRule(
name = "Corrupt Decoding",
targetClass = "org.apache.activemq.artemis.core.protocol.ClientPacketDecoder",
targetMethod = "decode(org.apache.activemq.artemis.api.core.ActiveMQBuffer)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.DisconnectOnCriticalFailureTest.doThrow($1);")})
public void testClientDisconnect() throws Exception {
Queue q1 = createQueue("queue1");
final Connection connection = nettyCf.createConnection();
final CountDownLatch latch = new CountDownLatch(1);
try {
connection.setExceptionListener(new ExceptionListener() {
@Override
public void onException(JMSException e) {
latch.countDown();
}
});
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(q1);
TextMessage m = session.createTextMessage("hello");
producer.send(m);
connection.start();
corruptPacket.set(true);
MessageConsumer consumer = session.createConsumer(q1);
consumer.receive(2000);
assertTrue(latch.await(5, TimeUnit.SECONDS));
} finally {
corruptPacket.set(false);
if (connection != null) {
connection.close();
}
}
}
@Test(timeout = 60000)
@BMRules(
rules = {
@BMRule(
name = "Corrupt Decoding",
targetClass = "org.apache.activemq.artemis.core.protocol.ClientPacketDecoder",
targetMethod = "decode(org.apache.activemq.artemis.api.core.ActiveMQBuffer)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.DisconnectOnCriticalFailureTest.doThrow($1);")})
public void testClientDisconnectLarge() throws Exception {
Queue q1 = createQueue("queue1");
final Connection connection = nettyCf.createConnection();
final CountDownLatch latch = new CountDownLatch(1);
ServerLocator locator = ((ActiveMQConnectionFactory)nettyCf).getServerLocator();
int minSize = locator.getMinLargeMessageSize();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < minSize; i++) {
builder.append("a");
}
try {
connection.setExceptionListener(new ExceptionListener() {
@Override
public void onException(JMSException e) {
latch.countDown();
}
});
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(q1);
TextMessage m = session.createTextMessage(builder.toString());
producer.send(m);
connection.start();
corruptPacket.set(true);
MessageConsumer consumer = session.createConsumer(q1);
Message lm = consumer.receive(2000);
//first receive won't crash because the packet
//is SESS_RECEIVE_LARGE_MSG
assertNotNull(lm);
//second receive will force server to send a
//"forced delivery" message, and will cause
//the exception to be thrown.
lm = consumer.receive(5000);
assertNull(lm);
assertTrue(latch.await(5, TimeUnit.SECONDS));
} finally {
corruptPacket.set(false);
if (connection != null) {
connection.close();
}
}
}
public static void doThrow(ActiveMQBuffer buff) {
byte type = buff.getByte(buff.readerIndex());
if (corruptPacket.get() && type == PacketImpl.SESS_RECEIVE_MSG) {
corruptPacket.set(false);
throw new IllegalArgumentException("Invalid type: -84");
}
}
public static void doThrow() {
if (corruptPacket.get()) {
corruptPacket.set(false);
throw new IllegalArgumentException("Invalid type: -84");
}
}
}

View File

@ -1,131 +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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.XAConnection;
import javax.jms.XASession;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class FailureXATest extends ActiveMQTestBase {
protected ActiveMQServer server = null;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server = createServer(createDefaultNettyConfig());
server.start();
}
@Override
@After
public void tearDown() throws Exception {
if (server != null) {
server.stop();
}
super.tearDown();
}
@Test
@BMRules(
rules = {
@BMRule(
name = "Crash after onephase committed",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerSessionImpl",
targetMethod = "xaCommit(javax.transaction.xa.Xid, boolean)",
targetLocation = "EXIT",
action = "throw new RuntimeException()")})
public void testCrashServerAfterOnePhaseCommit() throws Exception {
doTestCrashServerAfterXACommit(true);
}
@Test
@BMRules(
rules = {
@BMRule(
name = "Crash after onephase committed",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerSessionImpl",
targetMethod = "xaCommit(javax.transaction.xa.Xid, boolean)",
targetLocation = "EXIT",
//helper = "org.apache.activemq.artemis.tests.extras.byteman.FailureXATest",
action = "throw new RuntimeException()")})
public void testCrashServerAfterTwoPhaseCommit() throws Exception {
doTestCrashServerAfterXACommit(false);
}
private void doTestCrashServerAfterXACommit(boolean onePhase) throws Exception {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
XAConnection connection = connectionFactory.createXAConnection();
try {
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Queue queue = session.createQueue("Queue1");
final XASession xaSession = connection.createXASession();
MessageConsumer consumer = xaSession.createConsumer(queue);
MessageProducer producer = session.createProducer(queue);
producer.send(session.createTextMessage("hello " + 1));
session.commit();
XAResource xaResource = xaSession.getXAResource();
final Xid xid = newXID();
xaResource.start(xid, XAResource.TMNOFLAGS);
connection.start();
Assert.assertNotNull(consumer.receive(5000));
xaResource.end(xid, XAResource.TMSUCCESS);
try {
xaResource.commit(xid, onePhase);
Assert.fail("didn't get expected exception!");
} catch (XAException xae) {
if (onePhase) {
//expected error code is XAER_RMFAIL
Assert.assertEquals(XAException.XAER_RMFAIL, xae.errorCode);
} else {
//expected error code is XA_RETRY
Assert.assertEquals(XAException.XA_RETRY, xae.errorCode);
}
}
} finally {
connection.close();
}
}
}

View File

@ -1,124 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.io.File;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.apache.activemq.artemis.core.server.ActivateCallback;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.NodeManager.LockListener;
import org.apache.activemq.artemis.core.server.impl.FileLockNodeManager;
import org.apache.activemq.artemis.utils.Wait;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class FileLockMonitorTest {
private File sharedDir;
private volatile boolean lostLock = false;
private volatile FileLockNodeManager nodeManager;
private ScheduledThreadPoolExecutor executor;
@Before
public void handleLockFile() throws Exception {
sharedDir = File.createTempFile("shared-dir", "");
sharedDir.delete();
Assert.assertTrue(sharedDir.mkdir());
}
@Test
@BMRules(rules = {
@BMRule(name = "lock is invalid", targetClass = "org.apache.activemq.artemis.core.server.impl.FileLockNodeManager", targetMethod = "isLiveLockLost", action = "return true;") })
public void testLockMonitorInvalid() throws Exception {
lostLock = false;
startServer();
Wait.assertTrue("The FileLockNodeManager should have lost the lock", () -> lostLock, 20_000, 100);
nodeManager.isStarted();
nodeManager.crashLiveServer();
executor.shutdown();
}
public static void throwNodeManagerException(String msg) {
throw new NodeManager.NodeManagerException(msg);
}
@Test
@BMRules(rules = {
@BMRule(name = "lock is invalid", targetClass = "org.apache.activemq.artemis.core.server.impl.FileLockNodeManager",
targetMethod = "getState",
action = "org.apache.activemq.artemis.tests.extras.byteman.FileLockMonitorTest.throwNodeManagerException(\"EFS is disconnected\");") })
public void testLockMonitorIOException() throws Exception {
lostLock = false;
startServer();
Wait.assertTrue("The FileLockNodeManager should have lost the lock", () -> lostLock, 5000, 100);
nodeManager.crashLiveServer();
executor.shutdown();
}
@Test
public void testLockMonitorHasCorrectLockAndState() throws Exception {
lostLock = false;
startServer();
Assert.assertFalse("The FileLockNodeManager should not have lost the lock", Wait.waitFor(() -> lostLock, 5000, 100));
nodeManager.crashLiveServer();
executor.shutdown();
}
@Test
@BMRules(rules = {
@BMRule(name = "lock is invalid", targetClass = "org.apache.activemq.artemis.core.server.impl.FileLockNodeManager", targetMethod = "getState", action = "return 70;") })
public void testLockMonitorHasLockWrongState() throws Exception {
lostLock = false;
startServer();
Assert.assertFalse("The FileLockNodeManager should not have lost the lock", Wait.waitFor(() -> lostLock, 5000, 100));
nodeManager.crashLiveServer();
executor.shutdown();
}
public LockListener startServer() throws Exception {
executor = new ScheduledThreadPoolExecutor(2);
nodeManager = new FileLockNodeManager(sharedDir, false, executor);
LockListener listener = () -> {
lostLock = true;
try {
nodeManager.crashLiveServer();
} catch (Throwable t) {
t.printStackTrace();
}
};
nodeManager.registerLockListener(listener);
try {
nodeManager.start();
ActivateCallback startLiveNode = nodeManager.startLiveNode();
startLiveNode.activationComplete();
} catch (Exception exception) {
exception.printStackTrace();
}
return listener;
}
}

View File

@ -1,90 +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.activemq.artemis.tests.extras.byteman;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.apache.activemq.artemis.core.server.impl.FileLockNodeManager;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class FileLockNodeManagerTest {
private static final Logger log = Logger.getLogger(FileLockNodeManagerTest.class);
private static final int TIMEOUT_TOLERANCE = 50;
private File sharedDir;
public FileLockNodeManagerTest() throws IOException {
sharedDir = File.createTempFile("shared-dir", "");
sharedDir.delete();
Assert.assertTrue(sharedDir.mkdir());
}
@Test
@BMRules(
rules = {
@BMRule(
name = "throw IOException during activation",
targetClass = "org.apache.activemq.artemis.core.server.impl.FileLockNodeManager",
targetMethod = "tryLock",
targetLocation = "AT ENTRY",
action = "THROW new IOException(\"IO Error\");")
})
public void test() throws Exception {
measureLockAcquisisionTimeout(100); // warm-up
assertMeasuredTimeoutFor(100);
assertMeasuredTimeoutFor(200);
}
protected void assertMeasuredTimeoutFor(long lockAcquisitionTimeout) throws Exception {
long realTimeout = measureLockAcquisisionTimeout(lockAcquisitionTimeout);
log.debug(String.format("lockAcquisisionTimeout: %d ms, measured timeout: %d ms", lockAcquisitionTimeout, realTimeout));
Assert.assertTrue(String.format("Timeout %d ms was larger than expected %d ms", realTimeout, lockAcquisitionTimeout + TIMEOUT_TOLERANCE),
lockAcquisitionTimeout + TIMEOUT_TOLERANCE >= realTimeout);
Assert.assertTrue(String.format("Timeout %d ms was lower than expected %d ms", realTimeout, lockAcquisitionTimeout),
lockAcquisitionTimeout + TIMEOUT_TOLERANCE >= realTimeout);
}
private long measureLockAcquisisionTimeout(long lockAcquisitionTimeout) throws Exception {
FileLockNodeManager manager = new FileLockNodeManager(sharedDir, false, lockAcquisitionTimeout, new ScheduledThreadPoolExecutor(1));
manager.start();
// try to lock and measure real timeout
long start = System.currentTimeMillis();
try {
manager.awaitLiveNode();
} catch (Exception e) {
long stop = System.currentTimeMillis();
if (!"timed out waiting for lock".equals(e.getCause().getMessage())) {
throw e;
}
return stop - start;
}
Assert.fail("Exception expected");
return 0;
}
}

View File

@ -1,163 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* GroupingTest
*/
@RunWith(BMUnitRunner.class)
public class GroupingTest extends JMSTestBase {
private static final Logger log = Logger.getLogger(GroupingTest.class);
private Queue queue;
static boolean pause = false;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
queue = createQueue("TestQueue");
}
protected ConnectionFactory getCF() throws Exception {
return cf;
}
@Test
@BMRules(
rules = {
@BMRule(
name = "trace clientsessionimpl commit",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerSessionImpl",
targetMethod = "rollback",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.GroupingTest.pause();")})
public void testGroupingRollbackOnClose() throws Exception {
Connection sendConnection = null;
Connection connection = null;
Connection connection2 = null;
try {
ActiveMQConnectionFactory fact = (ActiveMQConnectionFactory) getCF();
fact.setReconnectAttempts(0);
//fact.setConsumerWindowSize(1000);
//fact.setTransactionBatchSize(0);
connection = fact.createConnection();
RemotingConnection rc = server.getRemotingService().getConnections().iterator().next();
connection2 = fact.createConnection();
sendConnection = fact.createConnection();
final Session sendSession = sendConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Session session2 = connection2.createSession(true, Session.SESSION_TRANSACTED);
final MessageProducer producer = sendSession.createProducer(queue);
MessageConsumer consumer1 = session.createConsumer(queue);
MessageConsumer consumer2 = session2.createConsumer(queue);
connection.start();
connection2.start();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int j = 0; j < 10000; j++) {
TextMessage message = sendSession.createTextMessage();
message.setText("Message" + j);
message.setStringProperty("JMSXGroupID", "foo");
producer.send(message);
}
} catch (JMSException e) {
e.printStackTrace();
}
}
});
t.start();
//consume 5 msgs from 1st first consumer
for (int j = 0; j < 5; j++) {
TextMessage tm = (TextMessage) consumer1.receive(10000);
assertNotNull(tm);
assertEquals("Message" + j, tm.getText());
assertEquals(tm.getStringProperty("JMSXGroupID"), "foo");
}
pause = true;
rc.fail(new ActiveMQNotConnectedException());
pause = false;
for (int j = 0; j < 10000; j++) {
TextMessage tm = (TextMessage) consumer2.receive(5000);
assertNotNull(tm);
assertEquals("Message" + j, tm.getText());
assertEquals(tm.getStringProperty("JMSXGroupID"), "foo");
}
} finally {
if (sendConnection != null) {
sendConnection.close();
}
if (connection2 != null) {
connection2.close();
}
}
}
public static void pause() {
if (pause) {
try {
log.debug("pausing after rollback");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
log.debug("finished pausing after rollback");
}
}
}

View File

@ -1,139 +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.activemq.artemis.tests.extras.byteman;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.core.settings.impl.HierarchicalObjectRepository;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
@BMRules(rules = {
@BMRule(name = "modify map during iteration",
targetClass = "org.apache.activemq.artemis.core.settings.impl.HierarchicalObjectRepository",
targetMethod = "getPossibleMatches(String)",
targetLocation = "AT INVOKE java.util.HashMap.put",
action = "org.apache.activemq.artemis.tests.extras.byteman.HierarchicalObjectRepositoryTest.bum()"),})
public class HierarchicalObjectRepositoryTest {
private static final String A = "a.";
private static final int TOTAL = 100;
private static CountDownLatch latch;
private static CountDownLatch latch2;
private ExecutorService executor;
private HierarchicalObjectRepository<String> repo;
@Before
public void setUp() {
latch = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
executor = Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory(getClass().getName()));
repo = new HierarchicalObjectRepository<>();
addToRepo(repo, A);
}
static void addToRepo(HierarchicalObjectRepository<String> repo0, String pattern) {
for (int i = 0; i < TOTAL; i++) {
repo0.addMatch(pattern + i + ".*", String.valueOf(i));
}
}
@After
public void tearDown() throws InterruptedException {
latch.countDown();
latch2.countDown();
executor.shutdown();
executor.awaitTermination(1, TimeUnit.SECONDS);
}
private class Clearer implements Runnable {
private final int code;
private Clearer(int code) {
this.code = code;
}
@Override
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
switch (code) {
case 0:
repo.clear();
break;
case 1:
addToRepo(repo, "bb.");
break;
case 2:
for (int i = TOTAL / 2; i < TOTAL; i++) {
repo.removeMatch(A + i + ".*");
}
break;
default:
throw new RuntimeException();
}
latch2.countDown();
}
}
@Test
public void testConcurrentModificationsClear() {
executor.execute(new Clearer(0));
repo.getMatch(A + (TOTAL - 10) + ".foobar");
Assert.assertEquals("Byteman rule failed?", 0, latch.getCount());
}
@Test
public void testConcurrentModificationsAdd() {
executor.execute(new Clearer(1));
repo.getMatch(A + (TOTAL - 10) + ".foobar");
Assert.assertEquals("Byteman rule failed?", 0, latch.getCount());
}
@Test
public void testConcurrentModificationsRemove() {
executor.execute(new Clearer(2));
repo.getMatch(A + (TOTAL - 10) + ".foobar");
Assert.assertEquals("Byteman rule failed?", 0, latch.getCount());
}
public static void bum() {
latch.countDown();
try {
latch2.await(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// no op
}
}
}

View File

@ -1,335 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.Message;
import javax.resource.ResourceException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.ra.ActiveMQResourceAdapter;
import org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec;
import org.apache.activemq.artemis.tests.integration.ra.ActiveMQRATestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class InterruptedMessageHandlerTest extends ActiveMQRATestBase {
@Override
protected boolean usePersistence() {
return true;
}
@Override
public boolean useSecurity() {
return false;
}
@Test
@BMRules(
rules = {
@BMRule(
name = "throw ActiveMQException(CONNETION_TIMEOUT) during rollback",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "flushAcks",
targetLocation = "AFTER INVOKE flushAcks",
action = "org.apache.activemq.artemis.tests.extras.byteman.InterruptedMessageHandlerTest.throwActiveMQQExceptionConnectionTimeout();"),
@BMRule(
name = "check that outcome of XA transaction is TwoPhaseOutcome.FINISH_ERROR=8",
targetClass = "com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord",
targetMethod = "topLevelAbort",
targetLocation = "AT EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.InterruptedMessageHandlerTest.assertTxOutComeIsOfStatusFinishedError($!);")})
public void testSimpleMessageReceivedOnQueueTwoPhaseFailPrepareByConnectionTimout() throws Exception {
ActiveMQResourceAdapter qResourceAdapter = newResourceAdapter();
resourceAdapter = qResourceAdapter;
MyBootstrapContext ctx = new MyBootstrapContext();
qResourceAdapter.setConnectorClassName(NETTY_CONNECTOR_FACTORY);
qResourceAdapter.start(ctx);
ActiveMQActivationSpec spec = new ActiveMQActivationSpec();
spec.setMaxSession(1);
spec.setCallTimeout(1000L);
spec.setResourceAdapter(qResourceAdapter);
spec.setUseJNDI(false);
spec.setDestinationType("javax.jms.Queue");
spec.setDestination(MDBQUEUE);
CountDownLatch latch = new CountDownLatch(1);
XADummyEndpointWithDummyXAResourceFailEnd endpoint = new XADummyEndpointWithDummyXAResourceFailEnd(latch, true);
DummyMessageEndpointFactory endpointFactory = new DummyMessageEndpointFactory(endpoint, true);
qResourceAdapter.endpointActivation(endpointFactory, spec);
ClientSession session = locator.createSessionFactory().createSession();
ClientProducer clientProducer = session.createProducer(MDBQUEUEPREFIXED);
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("teststring");
clientProducer.send(message);
session.close();
latch.await(5, TimeUnit.SECONDS);
assertNotNull(endpoint.lastMessage);
assertEquals(endpoint.lastMessage.getCoreMessage().getBodyBuffer().readString(), "teststring");
qResourceAdapter.endpointDeactivation(endpointFactory, spec);
qResourceAdapter.stop();
server.stop();
assertEquals("Two phase outcome must be of TwoPhaseOutcome.FINISH_ERROR.", TwoPhaseOutcome.FINISH_ERROR, txTwoPhaseOutCome.intValue());
}
static volatile ActiveMQResourceAdapter resourceAdapter;
static boolean resourceAdapterStopped = false;
public static void interrupt() throws InterruptedException {
if (!resourceAdapterStopped) {
resourceAdapter.stop();
resourceAdapterStopped = true;
throw new InterruptedException("foo");
}
}
public static void throwActiveMQQExceptionConnectionTimeout() throws ActiveMQException, XAException {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : stackTraceElements) {
if (element.getClassName().contains("ClientSessionImpl") && element.getMethodName().contains("rollback")) {
throw new ActiveMQException(ActiveMQExceptionType.CONNECTION_TIMEDOUT);
}
}
}
static Integer txTwoPhaseOutCome = null;
public static void assertTxOutComeIsOfStatusFinishedError(int txOutCome) {
// check only first trigger of byteman rule
if (txTwoPhaseOutCome == null) {
txTwoPhaseOutCome = Integer.valueOf(txOutCome);
}
}
Transaction currentTX;
public class XADummyEndpoint extends DummyMessageEndpoint {
final boolean twoPhase;
ClientSession session;
int afterDeliveryCounts = 0;
public XADummyEndpoint(CountDownLatch latch, boolean twoPhase) throws SystemException {
super(latch);
this.twoPhase = twoPhase;
try {
session = locator.createSessionFactory().createSession(true, false, false);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
super.beforeDelivery(method);
try {
DummyTMLocator.tm.begin();
currentTX = DummyTMLocator.tm.getTransaction();
currentTX.enlistResource(xaResource);
if (twoPhase) {
currentTX.enlistResource(new DummyXAResource());
}
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public void onMessage(Message message) {
super.onMessage(message);
}
@Override
public void afterDelivery() throws ResourceException {
afterDeliveryCounts++;
try {
currentTX.commit();
} catch (Throwable e) {
// its unsure as to whether the EJB/JCA layer will handle this or throw it to us,
// either way we don't do anything else so its fine just to throw.
// NB this will only happen with 2 phase commit
throw new RuntimeException(e);
}
super.afterDelivery();
}
}
@Override
@Before
public void setUp() throws Exception {
resourceAdapter = null;
resourceAdapterStopped = false;
super.setUp();
DummyTMLocator.startTM();
}
@Override
@After
public void tearDown() throws Exception {
DummyTMLocator.stopTM();
super.tearDown();
}
public static class DummyTMLocator {
public static TransactionManagerImple tm;
public static void stopTM() {
try {
TransactionReaper.terminate(true);
TxControl.disable(true);
} catch (Exception e) {
e.printStackTrace();
}
tm = null;
}
public static void startTM() {
tm = new TransactionManagerImple();
TxControl.enable();
}
public TransactionManager getTM() {
return tm;
}
}
static class DummyXAResource implements XAResource {
@Override
public void commit(Xid xid, boolean b) throws XAException {
}
@Override
public void end(Xid xid, int i) throws XAException {
}
@Override
public void forget(Xid xid) throws XAException {
}
@Override
public int getTransactionTimeout() throws XAException {
return 0;
}
@Override
public boolean isSameRM(XAResource xaResource) throws XAException {
return false;
}
@Override
public int prepare(Xid xid) throws XAException {
return 0;
}
@Override
public Xid[] recover(int i) throws XAException {
return new Xid[0];
}
@Override
public void rollback(Xid xid) throws XAException {
}
@Override
public boolean setTransactionTimeout(int i) throws XAException {
return false;
}
@Override
public void start(Xid xid, int i) throws XAException {
}
}
public class XADummyEndpointWithDummyXAResourceFailEnd extends XADummyEndpoint {
public XADummyEndpointWithDummyXAResourceFailEnd(CountDownLatch latch, boolean twoPhase) throws SystemException {
super(latch, twoPhase);
}
@Override
public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
try {
DummyTMLocator.tm.begin();
currentTX = DummyTMLocator.tm.getTransaction();
currentTX.enlistResource(xaResource);
if (twoPhase) {
currentTX.enlistResource(new DummyXAResourceFailEnd());
}
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
static class DummyXAResourceFailEnd extends DummyXAResource {
@Override
public void end(Xid xid, int i) throws XAException {
throw new XAException(XAException.XAER_RMFAIL);
}
}
}

View File

@ -1,121 +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.activemq.artemis.tests.extras.byteman;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.core.client.impl.ClientProducerCredits;
import org.apache.activemq.artemis.core.protocol.core.Packet;
import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory;
import org.apache.activemq.artemis.jms.bridge.QualityOfServiceMode;
import org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl;
import org.apache.activemq.artemis.tests.extras.jms.bridge.BridgeTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class JMSBridgeReconnectionTest extends BridgeTestBase {
@Test
@BMRules(
rules = {
@BMRule(
name = "trace clientsessionimpl send",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ChannelImpl",
targetMethod = "send",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.JMSBridgeReconnectionTest.pause($1);"),
@BMRule(
name = "trace sendRegularMessage",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientProducerImpl",
targetMethod = "sendRegularMessage",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.JMSBridgeReconnectionTest.pause2($2,$3,$4);")})
public void performCrashDestinationStopBridge() throws Exception {
activeMQServer = server1;
ConnectionFactoryFactory factInUse0 = cff0;
ConnectionFactoryFactory factInUse1 = cff1;
final JMSBridgeImpl bridge = new JMSBridgeImpl(factInUse0, factInUse1, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, QualityOfServiceMode.DUPLICATES_OK, 10, -1, null, null, false).setBridgeName("test-bridge");
addActiveMQComponent(bridge);
bridge.setTransactionManager(newTransactionManager());
bridge.start();
final CountDownLatch latch = new CountDownLatch(20);
Thread clientThread = new Thread(new Runnable() {
@Override
public void run() {
while (bridge.isStarted()) {
try {
sendMessages(cf0, sourceQueue, 0, 1, false, false);
latch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
clientThread.start();
stopLatch.await(10000, TimeUnit.MILLISECONDS);
bridge.stop();
clientThread.join(5000);
assertTrue(!clientThread.isAlive());
}
public static void pause(Packet packet) {
if (packet.getType() == PacketImpl.SESS_SEND) {
SessionSendMessage sendMessage = (SessionSendMessage) packet;
if (sendMessage.getMessage().containsProperty("__AMQ_CID") && count < 0 && !stopped) {
try {
activeMQServer.stop();
} catch (Exception e) {
e.printStackTrace();
}
stopped = true;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stopLatch.countDown();
}
}
}
static ActiveMQServer activeMQServer;
static boolean stopped = false;
static int count = 20;
static CountDownLatch stopLatch = new CountDownLatch(1);
public static void pause2(Message msgI, boolean sendBlocking, final ClientProducerCredits theCredits) {
if (msgI.containsProperty("__AMQ_CID")) {
count--;
}
}
}

View File

@ -1,71 +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.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.core.io.SequentialFileFactory;
import org.apache.activemq.artemis.tests.unit.core.journal.impl.JournalImplTestBase;
import org.apache.activemq.artemis.tests.unit.core.journal.impl.fakes.FakeSequentialFileFactory;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.ExecutionException;
@RunWith(BMUnitRunner.class)
public class JournalImplConcurrencyTest extends JournalImplTestBase {
@Override
protected SequentialFileFactory getFileFactory() {
return new FakeSequentialFileFactory();
}
/**
* Tests that JournalImpl#checkKnownRecordID() doesn't hang when the executor thread fails with
* an exception before setting the future value.
*/
@Test(timeout = 2000)
@BMRules(rules = {
@BMRule(
name = "BlockOnFinalLargeMessagePacket",
targetClass = "java.util.concurrent.locks.ReentrantReadWriteLock",
targetMethod = "readLock()",
targetLocation = "EXIT",
condition = "Thread.currentThread().getName().contains(\"ArtemisIOThread\")",
action = "throw RuntimeException(\"Injected exception\");")})
public void testTryDelete() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3);
try {
tryDelete(1);
Assert.fail("Expected to throw exception injected by a byteman rule");
} catch (ExecutionException e) {
Assert.assertTrue(e.getCause() instanceof RuntimeException);
Assert.assertEquals("Injected exception", e.getCause().getMessage());
}
stopJournal();
}
}

View File

@ -1,136 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.io.ByteArrayInputStream;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class LargeMessageOnShutdownTest extends ActiveMQTestBase {
private static final SimpleString queueName = new SimpleString("largeMessageShutdownQueue");
private static ActiveMQServer server;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
server = createServer(true, createDefaultNettyConfig());
startServer();
server.createQueue(new QueueConfiguration(queueName));
}
@After
@Override
public void tearDown() throws Exception {
super.tearDown();
stopServer();
}
@Test
@BMRules(
rules = {
@BMRule(
name = "BlockOnFinalLargeMessagePacket",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerSessionImpl",
targetMethod = "doSend(Transaction,Message,SimpleString,boolean,boolean)",
targetLocation = "EXIT",
condition = "!flagged(\"testLargeMessageOnShutdown\")",
action =
"org.apache.activemq.artemis.tests.extras.byteman.LargeMessageOnShutdownTest.stopServer();" +
"waitFor(\"testLargeMessageOnShutdown\", 5000);" +
"flag(\"testLargeMessageOnShutdown\")"),
@BMRule(
name = "ReleaseBlockOnSessionCleanup",
targetClass = "org.apache.activemq.artemis.core.protocol.core.ServerSessionPacketHandler",
targetMethod = "clearLargeMessage()",
targetLocation = "EXIT",
action = "signalWake(\"testLargeMessageOnShutdown\")")
}
)
public void testLargeMessageOnShutdown() throws Exception {
byte[] payload = new byte[ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE * 2];
// Send Large Message
ClientSessionFactory csf1 = createSessionFactory(createNettyNonHALocator());
try {
ClientSession session1 = csf1.createSession();
ClientProducer producer1 = session1.createProducer(queueName);
ClientMessage message = session1.createMessage(true);
message.setBodyInputStream(new ByteArrayInputStream(payload));
producer1.send(message);
} catch (Exception e) {
// Expected due to shutdown.
} finally {
csf1.close();
}
waitForStoppedServer();
startServer();
// Consume Large Message
ClientSessionFactory csf2 = createSessionFactory(createNettyNonHALocator());
try {
ClientSession session2 = csf2.createSession();
session2.start();
ClientConsumer consumer2 = session2.createConsumer(queueName);
ClientMessage rmessage = consumer2.receive(10000);
assertEquals(payload.length, rmessage.getBodyBuffer().readableBytes());
assertEqualsBuffers(payload.length, ActiveMQBuffers.wrappedBuffer(payload), rmessage.getBodyBuffer());
} finally {
csf2.close();
}
}
public static void stopServer() throws Exception {
server.stop();
waitForStoppedServer();
}
public static void startServer() throws Exception {
server.start();
server.waitForActivation(30, TimeUnit.SECONDS);
}
public static void waitForStoppedServer() throws Exception {
Wait.waitFor(() -> server.getState() == ActiveMQServer.SERVER_STATE.STOPPED);
}
}

View File

@ -1,259 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.CoreQueueConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.ReplicatedBackupUtils;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class LargeMessageOverReplicationTest extends ActiveMQTestBase {
public static int messageChunkCount = 0;
private static final ReusableLatch ruleFired = new ReusableLatch(1);
private static ActiveMQServer backupServer;
private static ActiveMQServer liveServer;
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?minLargeMessageSize=10000&HA=true&retryInterval=100&reconnectAttempts=-1&producerWindowSize=10000");
ActiveMQConnection connection;
Session session;
Queue queue;
MessageProducer producer;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
ruleFired.setCount(1);
messageChunkCount = 0;
TransportConfiguration liveConnector = TransportConfigurationUtils.getNettyConnector(true, 0);
TransportConfiguration liveAcceptor = TransportConfigurationUtils.getNettyAcceptor(true, 0);
TransportConfiguration backupConnector = TransportConfigurationUtils.getNettyConnector(false, 0);
TransportConfiguration backupAcceptor = TransportConfigurationUtils.getNettyAcceptor(false, 0);
Configuration backupConfig = createDefaultInVMConfig().setBindingsDirectory(getBindingsDir(0, true)).setJournalDirectory(getJournalDir(0, true)).setPagingDirectory(getPageDir(0, true)).setLargeMessagesDirectory(getLargeMessagesDir(0, true));
Configuration liveConfig = createDefaultInVMConfig();
ReplicatedBackupUtils.configureReplicationPair(backupConfig, backupConnector, backupAcceptor, liveConfig, liveConnector, liveAcceptor);
liveServer = createServer(liveConfig);
liveServer.getConfiguration().addQueueConfiguration(new CoreQueueConfiguration().setName("Queue").setAddress("Queue"));
liveServer.start();
waitForServerToStart(liveServer);
backupServer = createServer(backupConfig);
backupServer.start();
waitForServerToStart(backupServer);
// Just to make sure the expression worked
Assert.assertEquals(10000, factory.getMinLargeMessageSize());
Assert.assertEquals(10000, factory.getProducerWindowSize());
Assert.assertEquals(100, factory.getRetryInterval());
Assert.assertEquals(-1, factory.getReconnectAttempts());
Assert.assertTrue(factory.isHA());
connection = (ActiveMQConnection) factory.createConnection();
waitForRemoteBackup(connection.getSessionFactory(), 30);
session = connection.createSession(true, Session.SESSION_TRANSACTED);
queue = session.createQueue("Queue");
producer = session.createProducer(queue);
}
@After
public void stopServers() throws Exception {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
}
}
if (backupServer != null) {
backupServer.stop();
backupServer = null;
}
if (liveServer != null) {
liveServer.stop();
liveServer = null;
}
backupServer = liveServer = null;
}
/*
* simple test to induce a potential race condition where the server's acceptors are active, but the server's
* state != STARTED
*/
@Test
@BMRules(
rules = {
@BMRule(
name = "InterruptSending",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQSessionContext",
targetMethod = "sendLargeMessageChunk",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LargeMessageOverReplicationTest.messageChunkSent();")})
public void testSendLargeMessage() throws Exception {
MapMessage message = createLargeMessage();
try {
producer.send(message);
Assert.fail("expected an exception");
// session.commit();
} catch (JMSException expected) {
}
session.rollback();
producer.send(message);
session.commit();
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
MapMessage messageRec = (MapMessage) consumer.receive(5000);
Assert.assertNotNull(messageRec);
for (int i = 0; i < 10; i++) {
Assert.assertEquals(1024 * 1024, message.getBytes("test" + i).length);
}
}
@Test
@BMRules(
rules = {
@BMRule(
name = "InterruptReceive",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.CoreSessionCallback",
targetMethod = "sendLargeMessageContinuation",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LargeMessageOverReplicationTest.messageChunkReceived();")})
public void testReceiveLargeMessage() throws Exception {
MapMessage message = createLargeMessage();
producer.send(message);
session.commit();
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
MapMessage messageRec = null;
try {
consumer.receive(5000);
Assert.fail("Expected a failure here");
} catch (JMSException expected) {
}
session.rollback();
messageRec = (MapMessage) consumer.receive(5000);
Assert.assertNotNull(messageRec);
session.commit();
for (int i = 0; i < 10; i++) {
Assert.assertEquals(1024 * 1024, message.getBytes("test" + i).length);
}
}
public static void messageChunkReceived() {
messageChunkCount++;
if (messageChunkCount == 100) {
final CountDownLatch latch = new CountDownLatch(1);
new Thread() {
@Override
public void run() {
try {
latch.countDown();
liveServer.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
try {
// just to make sure it's about to be stopped
// avoiding bootstrapping the thread as a delay
latch.await(1, TimeUnit.MINUTES);
} catch (Throwable ignored) {
}
}
}
public static void messageChunkSent() {
messageChunkCount++;
try {
if (messageChunkCount == 10) {
liveServer.fail(true);
System.err.println("activating");
if (!backupServer.waitForActivation(1, TimeUnit.MINUTES)) {
Logger.getLogger(LargeMessageOverReplicationTest.class).warn("Can't failover server");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private MapMessage createLargeMessage() throws JMSException {
MapMessage message = session.createMapMessage();
for (int i = 0; i < 10; i++) {
message.setBytes("test" + i, new byte[1024 * 1024]);
}
return message;
}
}

View File

@ -1,206 +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.activemq.artemis.tests.extras.byteman;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
import org.apache.activemq.artemis.core.config.DivertConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.tests.integration.cluster.failover.FailoverTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class LargeMessageReplicationTest extends FailoverTestBase {
private static final Logger log = Logger.getLogger(LargeMessageReplicationTest.class);
private static final String DIVERT_ADDRESS = "jms.queue.testQueue";
private static final String DIVERT_FORWARD_ADDRESS = "jms.queue.divertedQueue";
private ClientSessionFactoryInternal sf;
private static AtomicLong copyThread = new AtomicLong(-1);
private static List<byte[]> sourceBytes = new ArrayList<>();
private static byte[] originalBuffer;
private static boolean isOk;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
isOk = true;
}
@Override
protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live) {
return getNettyAcceptorTransportConfiguration(live);
}
@Override
protected TransportConfiguration getConnectorTransportConfiguration(final boolean live) {
return getNettyConnectorTransportConfiguration(live);
}
@Override
protected void createConfigs() throws Exception {
createReplicatedConfigs();
liveConfig.setJournalFileSize(10240000);
backupConfig.setJournalFileSize(10240000);
addQueue(liveConfig, DIVERT_ADDRESS, DIVERT_ADDRESS);
addQueue(liveConfig, DIVERT_FORWARD_ADDRESS, DIVERT_FORWARD_ADDRESS);
addDivert(liveConfig, DIVERT_ADDRESS, DIVERT_FORWARD_ADDRESS, false);
addDivert(backupConfig, DIVERT_ADDRESS, DIVERT_FORWARD_ADDRESS, false);
}
private void addQueue(Configuration serverConfig, String address, String name) {
List<CoreAddressConfiguration> addrConfigs = serverConfig.getAddressConfigurations();
CoreAddressConfiguration addrCfg = new CoreAddressConfiguration();
addrCfg.setName(address);
addrCfg.addRoutingType(RoutingType.ANYCAST);
addrCfg.addQueueConfiguration(new QueueConfiguration(name).setAddress(address));
addrConfigs.add(addrCfg);
}
private void addDivert(Configuration serverConfig, String source, String target, boolean exclusive) {
List<DivertConfiguration> divertConfigs = serverConfig.getDivertConfigurations();
DivertConfiguration newDivert = new DivertConfiguration();
newDivert.setName("myDivert");
newDivert.setAddress(source);
newDivert.setForwardingAddress(target);
newDivert.setExclusive(exclusive);
divertConfigs.add(newDivert);
}
@Test
@BMRules(
rules = {
@BMRule(
name = "record large message copy thread",
targetClass = "org.apache.activemq.artemis.core.persistence.impl.journal.LargeServerMessageImpl",
targetMethod = "copy(long)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LargeMessageReplicationTest.copyThread()"),
@BMRule(
name = "record byte array in addBytes",
targetClass = "org.apache.activemq.artemis.core.persistence.impl.journal.LargeServerMessageImpl",
targetMethod = "addBytes(byte[])",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LargeMessageReplicationTest.addBytesIn($1)"),
@BMRule(
name = "record byte array used for reading large message",
targetClass = "^org.apache.activemq.artemis.core.io.SequentialFile",
isInterface = true,
targetMethod = "read(java.nio.ByteBuffer)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LargeMessageReplicationTest.originBuff($1)")})
//https://issues.apache.org/jira/browse/ARTEMIS-1220
public void testDivertCopyMessageBuffer() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put(TransportConstants.HOST_PROP_NAME, "localhost");
TransportConfiguration tc = createTransportConfiguration(true, false, params);
ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithHA(tc)).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setReconnectAttempts(-1);
sf = createSessionFactoryAndWaitForTopology(locator, 2);
int minLarge = locator.getMinLargeMessageSize();
ClientSession session = sf.createSession(false, false);
addClientSession(session);
session.start();
ClientProducer producer = session.createProducer(DIVERT_ADDRESS);
ClientMessage message = createLargeMessage(session, 3 * minLarge);
producer.send(message);
session.commit();
ClientConsumer consumer = session.createConsumer(DIVERT_ADDRESS);
ClientMessage receivedFromSourceQueue = consumer.receive(5000);
assertNotNull(receivedFromSourceQueue);
receivedFromSourceQueue.acknowledge();
session.commit();
crash(session);
ClientConsumer consumer1 = session.createConsumer(DIVERT_FORWARD_ADDRESS);
ClientMessage receivedFromTargetQueue = consumer1.receive(5000);
assertNotNull(receivedFromTargetQueue);
receivedFromTargetQueue.acknowledge();
session.commit();
checkBufferNotReused();
}
private void checkBufferNotReused() throws Exception {
assertNotNull("Didn't catch the original buffer!", originalBuffer);
assertTrue("Didn't catch the read buffer!", sourceBytes.size() > 0);
for (byte[] array : sourceBytes) {
assertFalse("Buffer reused!", originalBuffer == array);
}
}
private ClientMessage createLargeMessage(ClientSession session, final int largeSize) {
ClientMessage message = session.createMessage(true);
ActiveMQBuffer bodyBuffer = message.getBodyBuffer();
final int propSize = 10240;
while (bodyBuffer.writerIndex() < largeSize) {
byte[] prop = new byte[propSize];
bodyBuffer.writeBytes(prop);
}
return message;
}
private static void copyThread() {
log.debug("_************************ " + Thread.currentThread().getId());
copyThread.set(Thread.currentThread().getId());
}
private static void addBytesIn(final byte[] bytes) {
if (copyThread.get() != -1 && copyThread.get() == Thread.currentThread().getId()) {
sourceBytes.add(bytes);
}
}
private static void originBuff(final ByteBuffer buff) {
if (copyThread.get() != -1 && copyThread.get() == Thread.currentThread().getId()) {
originalBuffer = buff.array();
}
}
}

View File

@ -1,66 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class LatencyTest extends ActiveMQTestBase {
private static final Logger log = Logger.getLogger(LatencyTest.class);
private static void debugLog(String message) {
log.debug(message);
}
/*
* simple test to make sure connect still works with some network latency built into netty
* */
@Test
@BMRules(
rules = {
@BMRule(
name = "trace ClientBootstrap.connect",
targetClass = "org.jboss.netty.bootstrap.ClientBootstrap",
targetMethod = "connect",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LatencyTest.debugLog(\"netty connecting\")"),
@BMRule(
name = "sleep OioWorker.run",
targetClass = "org.jboss.netty.channel.socket.oio.OioWorker",
targetMethod = "run",
targetLocation = "ENTRY",
action = "Thread.sleep(500)")})
public void testLatency() throws Exception {
ActiveMQServer server = createServer(createDefaultNettyConfig());
server.start();
ServerLocator locator = createNettyNonHALocator();
ClientSessionFactory factory = createSessionFactory(locator);
ClientSession session = factory.createSession();
session.close();
server.stop();
}
}

View File

@ -1,180 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
import javax.jms.JMSException;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* NOTE: this test should be run at log level INFO
*
* This test checks the LoggingActiveMQServerPlugin is logging expected data with specific property configurations
* when client using AMQP
*/
@RunWith(BMUnitRunner.class)
public class LoggingActiveMQServerPluginAMQPTest extends LoggingActiveMQServerPluginTest {
/**
* Aim: test all events are logged when plugin configured with
* LOG_ALL_EVENTS
*
* Overridden as behaviour slightly different for AMQP - consumer closed plugin point called twice
*
* @throws Exception
*/
@Override
@Test
@BMRules(rules = {
@BMRule(name = "test logAll EVENT",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogAll() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_ALL_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "log ALL Message_1", 0);
sendAndReceive(true, true, "log ALL Message_2", 0);
Thread.sleep(500);
assertEquals("created connections", 2, createdConnectionLogs.size());
assertEquals("destroyed connections", 2, destroyedConnectionLogs.size());
assertEquals("created consumer", 2, createdConsumerLogs.size());
assertEquals("closed consumer", 4, closedConsumerLogs.size());
assertEquals("delivered message", 2, deliveredLogs.size());
assertEquals("acked message", 2, ackedLogs.size());
assertEquals("sending message", 2, sentLogs.size());
assertEquals("routing message", 2, routedLogs.size());
assertEquals("queue created", 2, createdQueueLogs.size());
assertEquals("queue destroyed", 2, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test the consumer create/close events are logged when plugin configured with
* LOG_CONSUMER_EVENTS
*
* Overridden as behaviour slightly different for AMQP - consumer closed plugin point seems to be called twice
* @throws Exception
*/
@Override
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_CONSUMER_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogConsumerEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_CONSUMER_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "txtMessage", 0);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 1, createdConsumerLogs.size());
assertEquals("closed consumer", 2, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 0, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test the session create/close events are logged when plugin configured with
* LOG_SESSION_EVENTS
*
* Overriden as addedMetaData does not seem to be invoked for AMQP
*
* @throws Exception
*/
@Override
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_SESSION_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogSessionEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_SESSION_EVENTS);
activeMQServer.start();
try {
sendAndReceive(false,false,"test_message",0);
Thread.sleep(500);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 2, createdSessionLogs.size());
assertEquals("closed sessions", 2, closedSessionLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
@Override
protected Connection createActiveMQConnection() throws JMSException {
JmsConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:61616");
return factory.createConnection();
}
}

View File

@ -1,194 +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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
import javax.jms.JMSException;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
*
* NOTE: this test should be run at log level INFO
*
* This test checks the LoggingActiveMQServerPlugin is logging expected data with specific property configurations
* when client using OpenWire
*
*/
@RunWith(BMUnitRunner.class)
public class LoggingActiveMQServerPluginOpenWireTest extends LoggingActiveMQServerPluginTest {
private static final Logger log = Logger.getLogger(LoggingActiveMQServerPluginOpenWireTest.class);
/**
* Aim: test queue creation are logged when plugin configured with
* LOG_INTERNAL_EVENTS
*
* Overiden as Openwire does not seem to destroy the queue.
*
* @throws Exception
*/
@Override
@Test
@BMRules(rules = {
@BMRule(name = "test queue creation log",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testQueueCreationLog() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_INTERNAL_EVENTS);
activeMQServer.start();
try {
sendAndReceive(false, true, "NO_MESSAGE", 0);
Thread.sleep(500);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 0, createdConsumerLogs.size());
assertEquals("closed consumer", 0, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 1, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test the session create/close events are logged when plugin configured with
* LOG_SESSION_EVENTS
*
* Overriden as
* - ceated/closed sessions is invoke 3 times for openwire
* - no meta data added to the session .
* @throws Exception
*/
@Override
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_SESSION_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogSessionEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_SESSION_EVENTS);
activeMQServer.start();
try {
sendAndReceive(false,false,"test_message",0);
Thread.sleep(500);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 3, createdSessionLogs.size());
assertEquals("closed sessions", 3, closedSessionLogs.size());
assertEquals("added Metadata logs", 0, addedSessionMetaData.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test all events are logged when plugin configured with
* LOG_ALL_EVENTS
*
* Overridden as behaviour slightly different for queue create/destroy with Openwire
*
* @throws Exception
*/
@Override
@Test
@BMRules(rules = {
@BMRule(name = "test logAll EVENT",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogAll() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_ALL_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "log ALL Message_1", 0);
sendAndReceive(true, true, "log ALL Message_2", 0);
Thread.sleep(500);
for (String logline : unexpectedLogs) {
log.debug(" others events logged >>>>" + logline);
}
assertEquals("created connections", 2, createdConnectionLogs.size());
assertEquals("destroyed connections", 2, destroyedConnectionLogs.size());
//assertEquals("created sessions", 0, createdSessionLogs.size());
//assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 2, createdConsumerLogs.size());
assertEquals("closed consumer", 2, closedConsumerLogs.size());
assertEquals("delivered message", 2, deliveredLogs.size());
assertEquals("acked message", 2, ackedLogs.size());
assertEquals("sending message", 2, sentLogs.size());
assertEquals("routing message", 2, routedLogs.size());
assertEquals("queue created", 1, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
@Override
protected Connection createActiveMQConnection() throws JMSException {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?jms.watchTopicAdvisories=false");
return factory.createConnection();
}
}

View File

@ -1,546 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jboss.logging.Logger.Level;
/**
* NOTE: this test should be run at log level INFO
*
* This test checks the LoggingActiveMQServerPlugin is logging expected data with specific property configurations
* when using CORE protocol
*
* Byteman is used to intercept the logged message and uses a helper method to put the messages into seperate lists
* based on its content. The test subsequently checks to ensure correct number of logs in each list.
*/
@RunWith(BMUnitRunner.class)
public class LoggingActiveMQServerPluginTest extends ActiveMQTestBase {
//buckets for logging
protected static List<String> createdConnectionLogs = new ArrayList<>();
protected static List<String> destroyedConnectionLogs = new ArrayList<>();
protected static List<String> createdSessionLogs = new ArrayList<>();
protected static List<String> closedSessionLogs = new ArrayList<>();
protected static List<String> createdConsumerLogs = new ArrayList<>();
protected static List<String> closedConsumerLogs = new ArrayList<>();
protected static List<String> deliveredLogs = new ArrayList<>();
protected static List<String> ackedLogs = new ArrayList<>();
protected static List<String> sentLogs = new ArrayList<>();
protected static List<String> routedLogs = new ArrayList<>();
protected static List<String> createdQueueLogs = new ArrayList<>();
protected static List<String> destroyedQueueLogs = new ArrayList<>();
protected static List<String> messageExpiredLogs = new ArrayList<>();
protected static List<String> unexpectedLogs = new ArrayList<>();
protected static List<String> addedSessionMetaData = new ArrayList<>();
/**
* Aim: verify connection creation/destroy is logged when LOG_CONNECTION_EVENTS is set
*
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_CONNECTION_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogConnectEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_CONNECTION_EVENTS);
activeMQServer.start();
try {
Connection connection = createActiveMQConnection();
connection.start();
Thread.sleep(100);
connection.close();
//ensure logs are collected.
Thread.sleep(500);
assertEquals("created connections", 1, createdConnectionLogs.size());
assertEquals("destroyed connections", 1, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 0, createdConsumerLogs.size());
assertEquals("closed consumer", 0, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 0, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test the session create/close events are logged when plugin configured with
* LOG_SESSION_EVENTS
*
* NOTE: Session plugin points seem to be invoked twice - did not expect that.
*
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_SESSION_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogSessionEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_SESSION_EVENTS);
activeMQServer.start();
try {
sendAndReceive(false, false, "test_message", 0);
Thread.sleep(500);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 2, createdSessionLogs.size());
assertEquals("closed sessions", 2, closedSessionLogs.size());
assertEquals("added Metadata logs", 2, addedSessionMetaData.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test the consumer create/close events are logged when plugin configured with
* LOG_CONSUMER_EVENTS
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_CONSUMER_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogConsumerEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_CONSUMER_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "txtMessage", 0);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 1, createdConsumerLogs.size());
assertEquals("closed consumer", 1, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 0, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test delivering events are logged when plugin configured with
* LOG_DELIVERING_EVENTS
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_DELIVERING_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogDeliveringEvents() throws Exception {
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_DELIVERING_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "txtMessage 1", 0);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 0, createdConsumerLogs.size());
assertEquals("closed consumer", 0, closedConsumerLogs.size());
assertEquals("delivered message", 1, deliveredLogs.size());
assertEquals("acked message", 1, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 0, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test sending events are logged when plugin configured with
* LOG_SENDING_EVENTS
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test LOG_SENDING_EVENTS",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogSendingEvents() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_SENDING_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "txtMessage 1", 0);
sendAndReceive(true, true, "txtMessage 2", 0);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 0, createdConsumerLogs.size());
assertEquals("closed consumer", 0, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 2, sentLogs.size());
assertEquals("routing message", 2, routedLogs.size());
assertEquals("queue created", 0, createdQueueLogs.size());
assertEquals("queue destroyed", 0, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test queue creation/destroy are logged when plugin configured with
* LOG_INTERNAL_EVENTS
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test queue creation log",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testQueueCreationLog() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_INTERNAL_EVENTS);
activeMQServer.start();
try {
sendAndReceive(false, true, "NO_MESSAGE", 0);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 0, createdConsumerLogs.size());
assertEquals("closed consumer", 0, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 1, createdQueueLogs.size());
assertEquals("queue destroyed", 1, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test message expiry is logged when plugin configured with
* LOG_INTERNAL_EVENTS
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test queue creation log",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testExpireMessageLog() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_INTERNAL_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, false, "message to expiry", 100);
Thread.sleep(1000);
sendAndReceive(false, true, "NO_MESSAGE", 0);
assertEquals("created connections", 0, createdConnectionLogs.size());
assertEquals("destroyed connections", 0, destroyedConnectionLogs.size());
assertEquals("created sessions", 0, createdSessionLogs.size());
assertEquals("closed sessions", 0, createdSessionLogs.size());
assertEquals("created consumer", 0, createdConsumerLogs.size());
assertEquals("closed consumer", 0, closedConsumerLogs.size());
assertEquals("delivered message", 0, deliveredLogs.size());
assertEquals("acked message", 0, ackedLogs.size());
assertEquals("sending message", 0, sentLogs.size());
assertEquals("routing message", 0, routedLogs.size());
assertEquals("queue created", 1, createdQueueLogs.size());
assertEquals("queue destroyed", 1, destroyedQueueLogs.size());
assertEquals("expired message", 1, messageExpiredLogs.size());
assertEquals("unexpected logs", 0, unexpectedLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
/**
* Aim: test all events are logged when plugin configured with
* LOG_ALL_EVENTS
* @throws Exception
*/
@Test
@BMRules(rules = {
@BMRule(name = "test logAll EVENT",
targetClass = "org.jboss.logging.Logger",
targetMethod = "logv",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.LoggingActiveMQServerPluginTest.infoLog($2, $4, $0)")})
public void testLogAll() throws Exception {
//initial plugin
ActiveMQServer activeMQServer = createServerWithLoggingPlugin(LoggingActiveMQServerPlugin.LOG_ALL_EVENTS);
activeMQServer.start();
try {
sendAndReceive(true, true, "log ALL Message_1", 0);
sendAndReceive(true, true, "log ALL Message_2", 0);
Thread.sleep(500);
assertEquals("created connections", 2, createdConnectionLogs.size());
assertEquals("destroyed connections", 2, destroyedConnectionLogs.size());
assertEquals("created consumer", 2, createdConsumerLogs.size());
assertEquals("closed consumer", 2, closedConsumerLogs.size());
assertEquals("delivered message", 2, deliveredLogs.size());
assertEquals("acked message", 2, ackedLogs.size());
assertEquals("sending message", 2, sentLogs.size());
assertEquals("routing message", 2, routedLogs.size());
assertEquals("queue created", 2, createdQueueLogs.size());
assertEquals("queue destroyed", 2, destroyedQueueLogs.size());
assertEquals("expired message", 0, messageExpiredLogs.size());
} finally {
activeMQServer.stop();
//reset the logs lists
clearLogLists();
}
}
//collect the log invocation from LoggingActiveMQServerPlugin
public static void infoLog(Level level, Object message, org.jboss.logging.Logger logger) {
//only interested in log level INFO
if (!level.equals(Level.INFO)) {
return;
}
//only interested in one logger
if (!logger.getName().startsWith(LoggingActiveMQServerPlugin.class.getPackage().getName())) {
return;
}
String stringMessage = (String) message;
if (stringMessage.startsWith("AMQ841000")) {
createdConnectionLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841001")) {
destroyedConnectionLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841002")) {
createdSessionLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841003")) {
closedSessionLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841004")) {
addedSessionMetaData.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841005")) {
createdConsumerLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841006")) {
closedConsumerLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841012")) {
deliveredLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841014")) {
ackedLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841009")) {
sentLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841010")) {
routedLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841007")) {
createdQueueLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841008")) {
destroyedQueueLogs.add(stringMessage);
} else if (stringMessage.startsWith("AMQ841013")) {
messageExpiredLogs.add(stringMessage);
} else {
unexpectedLogs.add(stringMessage);
}
}
//----- helper methods ---
protected void clearLogLists() {
createdConnectionLogs.clear();
destroyedConnectionLogs.clear();
createdSessionLogs.clear();
closedSessionLogs.clear();
createdConsumerLogs.clear();
closedConsumerLogs.clear();
deliveredLogs.clear();
ackedLogs.clear();
sentLogs.clear();
routedLogs.clear();
createdQueueLogs.clear();
destroyedQueueLogs.clear();
messageExpiredLogs.clear();
unexpectedLogs.clear();
addedSessionMetaData.clear();
}
protected ActiveMQServer createServerWithLoggingPlugin(String loggingPluginEventType) throws Exception {
//initial plugin
LoggingActiveMQServerPlugin loggingActiveMQServerPlugin = new LoggingActiveMQServerPlugin();
Map<String, String> properties = new HashMap<>();
properties.put(loggingPluginEventType, "true");
loggingActiveMQServerPlugin.init(properties);
//register
Configuration config = createDefaultConfig(true);
config.registerBrokerPlugin(loggingActiveMQServerPlugin);
return createServer(false, config);
}
protected void sendAndReceive(boolean send,
boolean receive,
String txtMessage,
long expiry) throws JMSException, InterruptedException {
Connection connection = createActiveMQConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
Queue queue = session.createQueue("TEST.QUEUE");
MessageConsumer messageConsumer = null;
if (receive) {
messageConsumer = session.createConsumer(queue);
Thread.sleep(1000);
}
if (send) {
MessageProducer messageProducer = session.createProducer(queue);
if (expiry > 0) {
messageProducer.setTimeToLive(expiry);
}
messageProducer.send(session.createTextMessage(txtMessage));
}
if (receive) {
messageConsumer.receive(100);
messageConsumer.close();
}
session.close();
connection.close();
}
protected Connection createActiveMQConnection() throws JMSException {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
return (ActiveMQConnection) factory.createConnection();
}
}

View File

@ -1,107 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.RuntimeMBeanException;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ManagementExceptionHandlingTest extends ActiveMQTestBase {
private static final Logger log = Logger.getLogger(ManagementExceptionHandlingTest.class);
protected ActiveMQServer server = null;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server = createServer(createDefaultNettyConfig());
server.getConfiguration().setJMXManagementEnabled(true);
server.start();
}
@Override
@After
public void tearDown() throws Exception {
if (server != null) {
server.stop();
}
super.tearDown();
}
@Test
@BMRules(rules = {
@BMRule(
name = "checking ActiveMQServerControl methods",
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "createQueue(org.apache.activemq.artemis.api.core.SimpleString, org.apache.activemq.artemis.api.core.RoutingType, org.apache.activemq.artemis.api.core.SimpleString, org.apache.activemq.artemis.api.core.SimpleString, boolean, boolean, int, boolean, boolean)",
targetLocation = "EXIT",
action = "throw new org.apache.activemq.artemis.api.core.ActiveMQException(\"gotcha\")")})
public void testActiveMQServerControl() throws Exception {
try {
server.getActiveMQServerControl().createQueue(new QueueConfiguration("some.queue").setAddress("some.address").setRoutingType(RoutingType.ANYCAST).toJSON());
fail("test should have gotten an exception!");
} catch (ActiveMQException e) {
fail("Wrong exception got!");
} catch (IllegalStateException e) {
assertEquals("gotcha", e.getMessage());
}
}
@Test
@BMRules(rules = {
@BMRule(
name = "checking ActiveMQServerControl methods",
targetClass = "org.apache.activemq.artemis.core.postoffice.impl.PostOfficeImpl",
targetMethod = "route(org.apache.activemq.artemis.api.core.Message, boolean)",
targetLocation = "ENTRY",
action = "throw new org.apache.activemq.artemis.api.core.ActiveMQException(\"gotcha\")")})
public void testAddressControl() throws Exception {
server.getActiveMQServerControl().createAddress("test.address", "ANYCAST");
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
log.debug("server is " + mbs);
ObjectName objectName = new ObjectName("org.apache.activemq.artemis:broker=\"localhost\",component=addresses,address=\"test.address\"");
Object[] params = new Object[] {new HashMap(), 3, "aGVsbG8=", true, null, null};
String[] signature = new String[] {"java.util.Map", "int", "java.lang.String", "boolean", "java.lang.String", "java.lang.String"};
try {
mbs.invoke(objectName, "sendMessage", params, signature);
fail("test should have gotten an exception!");
} catch (RuntimeMBeanException ex) {
assertTrue(ex.getCause() instanceof IllegalStateException);
IllegalStateException e = (IllegalStateException) ex.getCause();
assertEquals("gotcha", e.getMessage());
}
}
}

View File

@ -1,241 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class OrphanedConsumerTest extends ActiveMQTestBase {
private static final Logger log = Logger.getLogger(OrphanedConsumerTest.class);
private static void debugLog(String message) {
log.debug(message);
}
private static boolean conditionActive = true;
public static final boolean isConditionActive() {
return conditionActive;
}
public static final void setConditionActive(boolean _conditionActive) {
conditionActive = _conditionActive;
}
public static void throwException() throws Exception {
throw new InterruptedException("nice.. I interrupted this!");
}
private ActiveMQServer server;
private ServerLocator locator;
static ActiveMQServer staticServer;
/**
* {@link #leavingCloseOnTestCountersWhileClosing()} will set this in case of any issues.
* the test must then validate for this being null
*/
static AssertionError verification;
/**
* This static method is an entry point for the byteman rules on {@link #testOrphanedConsumers()}
*/
public static void leavingCloseOnTestCountersWhileClosing() {
if (staticServer.getSessions().size() == 0) {
verification = new AssertionError("The session was closed before the consumers, this may cause issues on management leaving Orphaned Consumers!");
}
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
setConditionActive(true);
/** I'm using the internal method here because closing
* this locator on tear down would hang.
* as we are tweaking with the internal state and making it fail */
locator = internalCreateNonHALocator(true);
}
@Override
@After
public void tearDown() throws Exception {
super.tearDown();
setConditionActive(false);
staticServer = null;
}
/**
* This is like being two tests in one:
* I - validating that any exception during the close wouldn't stop connection from being closed
* II - validating that the connection is only removed at the end of the process and you wouldn't see
* inconsistencies on management
*
* @throws Exception
*/
@Test
@BMRules(
rules = {
@BMRule(
name = "closeExit",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl",
targetMethod = "close",
targetLocation = "AT EXIT",
condition = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.isConditionActive()",
action = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.debugLog(\"throwing stuff\");throw new InterruptedException()"),
@BMRule(
name = "closeEnter",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl",
targetMethod = "close",
targetLocation = "ENTRY",
condition = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.isConditionActive()",
action = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.leavingCloseOnTestCountersWhileClosing()")})
public void testOrphanedConsumers() throws Exception {
internalTestOrphanedConsumers(false);
}
/**
* This is like being two tests in one:
* I - validating that any exception during the close wouldn't stop connection from being closed
* II - validating that the connection is only removed at the end of the process and you wouldn't see
* inconsistencies on management
*
* @throws Exception
*/
@Test
@BMRules(
rules = {
@BMRule(
name = "closeExit",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl",
targetMethod = "close",
targetLocation = "AT EXIT",
condition = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.isConditionActive()",
action = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.debugLog(\"throwing stuff\");throw new InterruptedException()"),
@BMRule(
name = "closeEnter",
targetClass = "org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl",
targetMethod = "close",
targetLocation = "ENTRY",
condition = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.isConditionActive()",
action = "org.apache.activemq.artemis.tests.extras.byteman.OrphanedConsumerTest.leavingCloseOnTestCountersWhileClosing()")})
public void testOrphanedConsumersByManagement() throws Exception {
internalTestOrphanedConsumers(true);
}
/**
* @param useManagement true = it will use a management operation to make the connection failure, false through ping
* @throws Exception
*/
private void internalTestOrphanedConsumers(boolean useManagement) throws Exception {
final int NUMBER_OF_MESSAGES = 2;
server = createServer(true, true);
server.start();
staticServer = server;
// We are not interested on consumer-window-size on this test
// We want that every message is delivered
// as we asserting for number of consumers available and round-robin on delivery
locator.setConsumerWindowSize(-1).setBlockOnNonDurableSend(false).setBlockOnDurableSend(false).setBlockOnAcknowledge(true).setConnectionTTL(1000).setClientFailureCheckPeriod(100).setReconnectAttempts(0);
ClientSessionFactoryImpl sf = (ClientSessionFactoryImpl) createSessionFactory(locator);
ClientSession session = sf.createSession(true, true, 0);
session.createQueue(new QueueConfiguration("queue1").setAddress("queue"));
session.createQueue(new QueueConfiguration("queue2").setAddress("queue"));
ClientProducer prod = session.createProducer("queue");
ClientConsumer consumer = session.createConsumer("queue1");
ClientConsumer consumer2 = session.createConsumer("queue2");
Queue queue1 = server.locateQueue(new SimpleString("queue1"));
Queue queue2 = server.locateQueue(new SimpleString("queue2"));
session.start();
if (!useManagement) {
sf.stopPingingAfterOne();
for (long timeout = System.currentTimeMillis() + 6000; timeout > System.currentTimeMillis() && server.getConnectionCount() != 0; ) {
Thread.sleep(100);
}
// an extra second to avoid races of something closing the session while we are asserting it
Thread.sleep(1000);
} else {
server.getActiveMQServerControl().closeConnectionsForAddress("127.0.0.1");
}
if (verification != null) {
throw verification;
}
assertEquals(0, queue1.getConsumerCount());
assertEquals(0, queue2.getConsumerCount());
setConditionActive(false);
locator = internalCreateNonHALocator(true).setBlockOnNonDurableSend(false).setBlockOnDurableSend(false).setBlockOnAcknowledge(true).setReconnectAttempts(0).setConsumerWindowSize(-1);
sf = (ClientSessionFactoryImpl) locator.createSessionFactory();
session = sf.createSession(true, true, 0);
session.start();
prod = session.createProducer("queue");
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
ClientMessage message = session.createMessage(true);
message.putIntProperty("i", i);
prod.send(message);
}
consumer = session.createConsumer("queue1");
consumer2 = session.createConsumer("queue2");
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
assertNotNull(consumer.receive(5000));
assertNotNull(consumer2.receive(5000));
}
session.close();
}
}

View File

@ -1,95 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
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 org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQMessageConsumer;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class PacketFailureTest extends JMSTestBase {
private Queue queue;
static boolean pause = false;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
queue = createQueue("TestQueue");
}
@Test(timeout = 20000)
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQSessionContext",
targetMethod = "handleReceivedMessagePacket(org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionReceiveMessage)",
targetLocation = "ENTRY",
action = "throw new Exception()")
public void testFailureToHandlePacket() throws Exception {
final int MESSAGE_COUNT = 20;
Connection sendConnection = null;
Connection connection = null;
try {
((ActiveMQConnectionFactory)cf).setReconnectAttempts(0);
sendConnection = cf.createConnection();
final Session sendSession = sendConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageProducer producer = sendSession.createProducer(queue);
for (int j = 0; j < MESSAGE_COUNT; j++) {
TextMessage message = sendSession.createTextMessage();
message.setText("Message" + j);
producer.send(message);
}
producer.close();
sendSession.close();
connection = cf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
Message message = consumer.receive(1000);
assertNull(message);
assertTrue(((ActiveMQMessageConsumer) consumer).isClosed());
} finally {
if (connection != null) {
connection.close();
}
if (sendConnection != null) {
sendConnection.close();
}
}
}
}

View File

@ -1,208 +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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.nio.ByteBuffer;
import java.util.HashMap;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class PagingOMETest extends ActiveMQTestBase {
private ServerLocator locator;
private ActiveMQServer server;
private ClientSessionFactory sf;
static final int MESSAGE_SIZE = 1024; // 1k
private static final int RECEIVE_TIMEOUT = 5000;
private static final int PAGE_MAX = 100 * 1024;
private static final int PAGE_SIZE = 10 * 1024;
static final SimpleString ADDRESS = new SimpleString("SimpleAddress");
static boolean failureActive = false;
public static void refCheck() {
if (failureActive) {
throw new OutOfMemoryError("fake error");
}
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
failureActive = false;
locator = createInVMNonHALocator();
}
@Test
@BMRules(
rules = {
@BMRule(
name = "fakeOME",
targetClass = "org.apache.activemq.artemis.core.paging.cursor.PagedReferenceImpl",
targetMethod = "getPagedMessage",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.PagingOMETest.refCheck()")})
public void testPageCleanup() throws Exception {
clearDataRecreateServerDirs();
Configuration config = createDefaultConfig(false);
config.setJournalSyncNonTransactional(false);
HashMap<String, AddressSettings> map = new HashMap<>();
AddressSettings value = new AddressSettings();
map.put(ADDRESS.toString(), value);
server = createServer(true, config, PAGE_SIZE, PAGE_MAX, map);
server.start();
final int numberOfMessages = 2;
locator = createInVMNonHALocator();
locator.setBlockOnNonDurableSend(true);
locator.setBlockOnDurableSend(true);
locator.setBlockOnAcknowledge(false);
locator.setConsumerWindowSize(0);
sf = createSessionFactory(locator);
ClientSession session = sf.createSession(false, false, false);
session.createQueue(new QueueConfiguration(ADDRESS));
Queue queue = server.locateQueue(ADDRESS);
queue.getPageSubscription().getPagingStore().startPaging();
Assert.assertTrue(queue.getPageSubscription().getPagingStore().isPaging());
ClientProducer producer = session.createProducer(PagingOMETest.ADDRESS);
ClientMessage message = null;
byte[] body = new byte[MESSAGE_SIZE];
ByteBuffer bb = ByteBuffer.wrap(body);
for (int j = 1; j <= MESSAGE_SIZE; j++) {
bb.put(getSamplebyte(j));
}
for (int i = 0; i < numberOfMessages; i++) {
message = session.createMessage(true);
ActiveMQBuffer bodyLocal = message.getBodyBuffer();
bodyLocal.writeBytes(body);
producer.send(message);
if (i % 1000 == 0) {
session.commit();
}
}
session.commit();
session = sf.createSession(false, false, false);
session.start();
Wait.assertTrue(() -> numberOfMessages == queue.getMessageCount());
// The consumer has to be created after the queue.getMessageCount assertion
// otherwise delivery could alter the messagecount and give us a false failure
ClientConsumer consumer = session.createConsumer(PagingOMETest.ADDRESS);
ClientMessage msg = null;
msg = consumer.receive(1000);
failureActive = true;
msg.individualAcknowledge();
try {
session.commit();
Assert.fail("exception expected");
} catch (Exception expected) {
}
failureActive = false;
session.rollback();
session.close();
sf.close();
locator.close();
server.stop();
server.start();
locator = createInVMNonHALocator();
locator.setBlockOnNonDurableSend(true);
locator.setBlockOnDurableSend(true);
locator.setBlockOnAcknowledge(false);
locator.setConsumerWindowSize(0);
sf = createSessionFactory(locator);
session = sf.createSession(false, false, false);
consumer = session.createConsumer(PagingOMETest.ADDRESS);
session.start();
for (int i = 0; i < numberOfMessages; i++) {
msg = consumer.receive(1000);
Assert.assertNotNull(msg);
msg.individualAcknowledge();
}
Assert.assertNull(consumer.receiveImmediate());
session.commit();
session.close();
sf.close();
server.stop();
}
}

View File

@ -1,48 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.util.UUID;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class QueueDeploymentFailedTest extends ActiveMQTestBase {
@Test
@BMRule(name = "blow up queue deployment",
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "createQueue(SimpleString,RoutingType,SimpleString,SimpleString,SimpleString,boolean,boolean,boolean,boolean,boolean,int,boolean,boolean,boolean,int,long,boolean",
targetLocation = "EXIT",
action = "throw new IllegalStateException(\"test exception\")")
public void testQueueDeploymentFailure() throws Exception {
ActiveMQServer server = createServer(false, createDefaultNettyConfig());
String address = UUID.randomUUID().toString();
server.getConfiguration().addAddressConfiguration(new CoreAddressConfiguration().setName(address).addRoutingType(RoutingType.ANYCAST).addQueueConfiguration(new QueueConfiguration(UUID.randomUUID().toString()).setRoutingType(RoutingType.ANYCAST).setAddress(address)));
server.start();
assertTrue(server.getRemotingService().isStarted());
}
}

View File

@ -1,191 +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.activemq.artemis.tests.extras.byteman;
import java.util.Set;
import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal;
import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class RaceOnClosingConsumerWhileReconnecting extends ActiveMQTestBase {
static RemotingConnection conn;
static ClientConsumer consumer;
protected ActiveMQServer server = null;
protected ClientSessionFactoryInternal sf = null;
protected ClientSessionInternal session = null;
protected final SimpleString queueName1 = new SimpleString("my_queue_one");
@Override
@Before
public void setUp() throws Exception {
super.setUp();
conn = null;
consumer = null;
server = createServer(true, true);
server.start();
SimpleString addressName1 = new SimpleString("my_address_one");
server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST));
final long retryInterval = 500;
final double retryMultiplier = 1d;
final int reconnectAttempts = 10;
ServerLocator locator = createFactory(true).setCallFailoverTimeout(0).setCallTimeout(2000).setRetryInterval(retryInterval).setRetryIntervalMultiplier(retryMultiplier).setReconnectAttempts(reconnectAttempts).setConfirmationWindowSize(-1);
sf = (ClientSessionFactoryInternal) createSessionFactory(locator);
session = (ClientSessionInternal)sf.createSession(false, true, true);
}
@Override
@After
public void tearDown() throws Exception {
if (session != null) {
session.close();
}
if (sf != null) {
sf.close();
}
if (server != null) {
server.stop();
}
conn = null;
consumer = null;
super.tearDown();
}
@Test
@BMRules(
rules = {
@BMRule(
name = "session.removeConsumer wait",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "removeConsumer(org.apache.activemq.artemis.core.client.impl.ClientConsumerInternal)",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnClosingConsumerWhileReconnecting.waitForReconnection();")})
public void testClosingConsumerBeforeReconnecting() throws Exception {
conn = session.getConnection();
ClientConsumer clientConsumer1 = session.createConsumer(queueName1);
ClientConsumer clientConsumer2 = session.createConsumer(queueName1);
clientConsumer1.close();
Thread.sleep(500);
Set<ServerConsumer> serverConsumers = server.getSessionByID(session.getName()).getServerConsumers();
ServerConsumer serverConsumer = serverConsumers.iterator().next();
assertEquals(1, serverConsumers.size());
assertEquals(clientConsumer2.getConsumerContext().getId(), serverConsumer.getID());
}
@Test
@BMRules(
rules = {
@BMRule(
name = "session.closeConsumer before recreating consumer",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "handleFailover",
targetLocation = "AFTER WRITE $consumerInternal 1",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnClosingConsumerWhileReconnecting.closeConsumer();")})
public void testClosingConsumerBeforeRecreatingOneConsumer() throws Exception {
RemotingConnection conn = session.getConnection();
ClientConsumer clientConsumer1 = session.createConsumer(queueName1);
consumer = clientConsumer1;
conn.fail(new ActiveMQNotConnectedException());
Thread.sleep(500);
Set<ServerConsumer> serverConsumers = server.getSessionByID(session.getName()).getServerConsumers();
assertEquals(0, serverConsumers.size());
}
@Test
@BMRules(
rules = {
@BMRule(
name = "session.closeConsumer before recreating consumer",
targetClass = "org.apache.activemq.artemis.core.client.impl.ClientSessionImpl",
targetMethod = "handleFailover",
targetLocation = "AFTER WRITE $consumerInternal 1",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnClosingConsumerWhileReconnecting.closeConsumer();")})
public void testClosingConsumerBeforeRecreatingTwoConsumers() throws Exception {
RemotingConnection conn = session.getConnection();
ClientConsumer clientConsumer1 = session.createConsumer(queueName1);
ClientConsumer clientConsumer2 = session.createConsumer(queueName1);
consumer = clientConsumer1;
conn.fail(new ActiveMQNotConnectedException());
Thread.sleep(500);
ServerSession serverSession = server.getSessionByID(session.getName());
assertNotNull(serverSession);
Set<ServerConsumer> serverConsumers = serverSession.getServerConsumers();
ServerConsumer serverConsumer = serverConsumers.iterator().next();
assertEquals(1, serverConsumers.size());
assertEquals(clientConsumer2.getConsumerContext().getId(), serverConsumer.getID());
}
public static void closeConsumer() {
if (consumer != null) {
try {
consumer.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
consumer = null;
}
}
}
public static void waitForReconnection() {
if (conn != null) {
try {
conn.fail(new ActiveMQNotConnectedException());
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}
}

View File

@ -1,209 +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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.util.HashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.message.impl.CoreMessage;
import org.apache.activemq.artemis.core.paging.PagingStore;
import org.apache.activemq.artemis.core.paging.cursor.PagedReference;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.impl.RoutingContextImpl;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class RaceOnCursorIteratorTest extends ActiveMQTestBase {
private static ServerLocator locator;
private static ActiveMQServer server;
private static ClientSessionFactory sf;
private static ClientSession session;
private static Queue queue;
private static final ReentrantReadWriteLock.ReadLock lock = new ReentrantReadWriteLock().readLock();
private static final int PAGE_MAX = 100 * 1024;
private static final int PAGE_SIZE = 10 * 1024;
static final SimpleString ADDRESS = new SimpleString("SimpleAddress");
static boolean skipLivePageCache = false;
static boolean skipNullPageCache = false;
static boolean moveNextPageCalled = false;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
skipLivePageCache = false;
skipNullPageCache = false;
moveNextPageCalled = false;
locator = createInVMNonHALocator();
clearDataRecreateServerDirs();
Configuration config = createDefaultConfig(false);
config.setJournalSyncNonTransactional(false);
HashMap<String, AddressSettings> map = new HashMap<>();
AddressSettings value = new AddressSettings();
map.put(ADDRESS.toString(), value);
server = createServer(true, config, PAGE_SIZE, PAGE_MAX, map);
server.start();
locator = createInVMNonHALocator();
locator.setBlockOnNonDurableSend(true);
locator.setBlockOnDurableSend(true);
locator.setBlockOnAcknowledge(false);
locator.setConsumerWindowSize(0);
sf = createSessionFactory(locator);
session = sf.createSession(false, true, true);
session.createQueue(new QueueConfiguration(ADDRESS));
queue = server.locateQueue(ADDRESS);
queue.getPageSubscription().getPagingStore().startPaging();
}
@Override
@After
public void tearDown() throws Exception {
session.close();
sf.close();
locator.close();
server.stop();
super.tearDown();
}
public static void raceAddLivePageCache() throws Exception {
if (skipLivePageCache) {
createMessage(1);
queue.getPageSubscription().getPagingStore().forceAnotherPage();
createMessage(2);
}
moveNextPageCalled = true;
}
public static void raceAddTwoCaches() throws Exception {
if (skipNullPageCache && moveNextPageCalled) {
createMessage(1);
queue.getPageSubscription().getPagingStore().forceAnotherPage();
createMessage(2);
}
}
@Test
@BMRules(
rules = {
@BMRule(
name = "raceLiveCache",
targetClass = "org.apache.activemq.artemis.core.paging.cursor.impl.PageSubscriptionImpl",
targetMethod = "moveNextPage",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnCursorIteratorTest.raceAddLivePageCache()")})
public void testSkipLivePageCache() {
skipLivePageCache = true;
// Simulate scenario #1 depicted in https://issues.apache.org/jira/browse/ARTEMIS-2418
PagedReference ref = queue.getPageSubscription().iterator().next();
assertTrue("first msg should not be " + (ref == null ? "null" : ref.getPagedMessage().getMessage().getMessageID()),
ref == null || ref.getPagedMessage().getMessage().getMessageID() == 1);
}
@Test
@BMRules(
rules = {
@BMRule(
name = "raceLiveCache",
targetClass = "org.apache.activemq.artemis.core.paging.cursor.impl.PageSubscriptionImpl",
targetMethod = "moveNextPage",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnCursorIteratorTest.raceAddLivePageCache()"),
@BMRule(
name = "raceNullCache",
targetClass = "org.apache.activemq.artemis.core.paging.cursor.impl.PageCursorProviderImpl",
targetMethod = "getPageCache",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnCursorIteratorTest.raceAddTwoCaches()")})
public void testSkipNullPageCache() throws Exception {
skipNullPageCache = true;
// Simulate scenario #2 depicted in https://issues.apache.org/jira/browse/ARTEMIS-2418
queue.getPageSubscription().getPagingStore().getCurrentPage().close(false);
PagedReference ref = queue.getPageSubscription().iterator().next();
assertTrue("first msg should not be " + (ref == null ? "null" : ref.getPagedMessage().getMessage().getMessageID()),
ref == null || ref.getPagedMessage().getMessage().getMessageID() == 1);
}
private static CoreMessage createMessage(final long id) throws Exception {
ActiveMQBuffer buffer = createRandomBuffer(0, 10);
PagingStore pagingStore = queue.getPageSubscription().getPagingStore();
CoreMessage msg = new CoreMessage(id, 50 + buffer.capacity());
msg.setAddress(ADDRESS);
msg.getBodyBuffer().resetReaderIndex();
msg.getBodyBuffer().resetWriterIndex();
msg.getBodyBuffer().writeBytes(buffer, buffer.capacity());
final RoutingContextImpl ctx = new RoutingContextImpl(null);
ctx.addQueue(ADDRESS, queue);
pagingStore.page(msg, ctx.getTransaction(), ctx.getContextListing(ADDRESS));
return msg;
}
protected static ActiveMQBuffer createRandomBuffer(final long id, final int size) {
return RandomUtil.randomBuffer(size, id);
}
}

View File

@ -1,282 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.FailoverEventListener;
import org.apache.activemq.artemis.api.core.client.FailoverEventType;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.CoreQueueConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.SharedNothingBackupActivation;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.ReplicatedBackupUtils;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* This test will add more bytes to the large message while still syncing.
* At the time of writing I couldn't replicate any issues, but I'm keeping it here to validate the impl
*/
@RunWith(BMUnitRunner.class)
public class RaceOnSyncLargeMessageOverReplication2Test extends ActiveMQTestBase {
private static final Logger log = Logger.getLogger(RaceOnSyncLargeMessageOverReplication2Test.class);
public static int messageChunkCount = 0;
private static ActiveMQServer backupServer;
private static ActiveMQServer liveServer;
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?minLargeMessageSize=10000&HA=true&retryInterval=100&reconnectAttempts=-1&producerWindowSize=10000");
ActiveMQConnection connection;
Session session;
Queue queue;
MessageProducer producer;
Configuration backupConfig;
Configuration liveConfig;
// To inform the main thread the condition is met
static final ReusableLatch flagChunkEntered = new ReusableLatch(1);
// To wait while the condition is worked out
static final ReusableLatch flagChunkWait = new ReusableLatch(1);
// To inform the main thread the condition is met
static final ReusableLatch flagSyncEntered = new ReusableLatch(1);
// To wait while the condition is worked out
static final ReusableLatch flagSyncWait = new ReusableLatch(1);
@Override
@Before
public void setUp() throws Exception {
super.setUp();
log.debug("Tmp::" + getTemporaryDir());
flagChunkEntered.setCount(1);
flagChunkWait.setCount(1);
flagSyncEntered.setCount(1);
flagSyncWait.setCount(1);
messageChunkCount = 0;
TransportConfiguration liveConnector = TransportConfigurationUtils.getNettyConnector(true, 0);
TransportConfiguration liveAcceptor = TransportConfigurationUtils.getNettyAcceptor(true, 0);
TransportConfiguration backupConnector = TransportConfigurationUtils.getNettyConnector(false, 0);
TransportConfiguration backupAcceptor = TransportConfigurationUtils.getNettyAcceptor(false, 0);
backupConfig = createDefaultInVMConfig().setBindingsDirectory(getBindingsDir(0, true)).
setJournalDirectory(getJournalDir(0, true)).setPagingDirectory(getPageDir(0, true)).
setLargeMessagesDirectory(getLargeMessagesDir(0, true));
liveConfig = createDefaultInVMConfig();
ReplicatedBackupUtils.configureReplicationPair(backupConfig, backupConnector, backupAcceptor, liveConfig, liveConnector, liveAcceptor);
liveServer = createServer(liveConfig);
liveServer.getConfiguration().addQueueConfiguration(new CoreQueueConfiguration().setName("Queue").setAddress("Queue"));
liveServer.start();
waitForServerToStart(liveServer);
// Just to make sure the expression worked
Assert.assertEquals(10000, factory.getMinLargeMessageSize());
Assert.assertEquals(10000, factory.getProducerWindowSize());
Assert.assertEquals(100, factory.getRetryInterval());
Assert.assertEquals(-1, factory.getReconnectAttempts());
Assert.assertTrue(factory.isHA());
connection = (ActiveMQConnection) factory.createConnection();
session = connection.createSession(true, Session.SESSION_TRANSACTED);
queue = session.createQueue("Queue");
producer = session.createProducer(queue);
}
private void startBackup() throws Exception {
backupServer = createServer(backupConfig);
backupServer.start();
waitForServerToStart(backupServer);
}
@After
public void stopServers() throws Exception {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
}
}
if (backupServer != null) {
backupServer.stop();
backupServer = null;
}
if (liveServer != null) {
liveServer.stop();
liveServer = null;
}
backupServer = liveServer = null;
}
@Test
@BMRules(
rules = {
@BMRule(
name = "InterruptSending",
targetClass = "org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQSessionContext",
targetMethod = "sendLargeMessageChunk",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnSyncLargeMessageOverReplication2Test.messageChunkSent();"),
@BMRule(
name = "InterruptSync",
targetClass = "org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager",
targetMethod = "sendLargeMessageFiles",
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnSyncLargeMessageOverReplication2Test.syncLargeMessage();")})
public void testSendLargeMessage() throws Exception {
final CountDownLatch failedOver = new CountDownLatch(1);
connection.setFailoverListener(new FailoverEventListener() {
@Override
public void failoverEvent(FailoverEventType eventType) {
failedOver.countDown();
}
});
Thread t;
{
final MapMessage message = createLargeMessage();
t = new Thread() {
@Override
public void run() {
try {
producer.send(message);
session.commit();
} catch (JMSException expected) {
expected.printStackTrace();
}
}
};
}
t.start();
// I'm trying to simulate the following race here:
// The message is syncing while the client is already sending the body of the message
Assert.assertTrue(flagChunkEntered.await(10, TimeUnit.SECONDS));
startBackup();
Assert.assertTrue(flagSyncEntered.await(10, TimeUnit.SECONDS));
flagChunkWait.countDown();
t.join(5000);
log.debug("Thread joined");
Assert.assertFalse(t.isAlive());
flagSyncWait.countDown();
Assert.assertTrue(((SharedNothingBackupActivation) backupServer.getActivation()).waitForBackupSync(10, TimeUnit.SECONDS));
waitForRemoteBackup(connection.getSessionFactory(), 30);
liveServer.fail(true);
Assert.assertTrue(failedOver.await(10, TimeUnit.SECONDS));
{
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
MapMessage message = (MapMessage) consumer.receive(5000);
Assert.assertNotNull(message);
for (int i = 0; i < 10; i++) {
Assert.assertEquals(1024 * 1024, message.getBytes("test" + i).length);
}
session.commit();
}
}
public static void syncLargeMessage() {
try {
flagSyncEntered.countDown();
flagSyncWait.await(100, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void messageChunkSent() {
messageChunkCount++;
try {
if (messageChunkCount == 1) {
flagChunkEntered.countDown();
flagChunkWait.await(10, TimeUnit.SECONDS);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private MapMessage createLargeMessage() throws JMSException {
MapMessage message = session.createMapMessage();
for (int i = 0; i < 10; i++) {
message.setBytes("test" + i, new byte[1024 * 1024]);
}
return message;
}
}

View File

@ -1,246 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.FailoverEventListener;
import org.apache.activemq.artemis.api.core.client.FailoverEventType;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.CoreQueueConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.ReplicatedBackupUtils;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* This test will validate the sync of large messages will not lose any messages in a specific scenario.
*/
@RunWith(BMUnitRunner.class)
public class RaceOnSyncLargeMessageOverReplicationTest extends ActiveMQTestBase {
private static final Logger log = Logger.getLogger(RaceOnSyncLargeMessageOverReplicationTest.class);
private static ActiveMQServer backupServer;
private static ActiveMQServer liveServer;
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?minLargeMessageSize=10000&HA=true&retryInterval=100&reconnectAttempts=-1&producerWindowSize=10000");
ActiveMQConnection connection;
Session session;
Queue queue;
MessageProducer producer;
Configuration backupConfig;
Configuration liveConfig;
// To inform the main thread the condition is met
static final ReusableLatch flagArrived = new ReusableLatch(1);
// To wait while the condition is worked out
static final ReusableLatch flagWait = new ReusableLatch(1);
@Override
@Before
public void setUp() throws Exception {
super.setUp();
log.debug("Tmp::" + getTemporaryDir());
flagArrived.setCount(1);
flagWait.setCount(1);
TransportConfiguration liveConnector = TransportConfigurationUtils.getNettyConnector(true, 0);
TransportConfiguration liveAcceptor = TransportConfigurationUtils.getNettyAcceptor(true, 0);
TransportConfiguration backupConnector = TransportConfigurationUtils.getNettyConnector(false, 0);
TransportConfiguration backupAcceptor = TransportConfigurationUtils.getNettyAcceptor(false, 0);
backupConfig = createDefaultInVMConfig().setBindingsDirectory(getBindingsDir(0, true)).
setJournalDirectory(getJournalDir(0, true)).setPagingDirectory(getPageDir(0, true)).
setLargeMessagesDirectory(getLargeMessagesDir(0, true));
liveConfig = createDefaultInVMConfig();
ReplicatedBackupUtils.configureReplicationPair(backupConfig, backupConnector, backupAcceptor, liveConfig, liveConnector, liveAcceptor);
liveServer = createServer(liveConfig);
liveServer.getConfiguration().addQueueConfiguration(new CoreQueueConfiguration().setName("Queue").setAddress("Queue"));
liveServer.start();
waitForServerToStart(liveServer);
// Just to make sure the expression worked
Assert.assertEquals(10000, factory.getMinLargeMessageSize());
Assert.assertEquals(10000, factory.getProducerWindowSize());
Assert.assertEquals(100, factory.getRetryInterval());
Assert.assertEquals(-1, factory.getReconnectAttempts());
Assert.assertTrue(factory.isHA());
connection = (ActiveMQConnection) factory.createConnection();
session = connection.createSession(true, Session.SESSION_TRANSACTED);
queue = session.createQueue("Queue");
producer = session.createProducer(queue);
}
private void startBackup() throws Exception {
backupServer = createServer(backupConfig);
backupServer.start();
waitForServerToStart(backupServer);
}
@After
public void stopServers() throws Exception {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
}
}
if (backupServer != null) {
backupServer.stop();
backupServer = null;
}
if (liveServer != null) {
liveServer.stop();
liveServer = null;
}
backupServer = liveServer = null;
}
/*
* simple test to induce a potential race condition where the server's acceptors are active, but the server's
* state != STARTED
*/
@Test
@BMRules(
rules = {
@BMRule(
name = "InterruptSync",
targetClass = "org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager",
targetMethod = "createLargeMessage(long,org.apache.activemq.artemis.core.message.impl.MessageInternal)",
targetLocation = "EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.RaceOnSyncLargeMessageOverReplicationTest.syncLargeMessage();")})
public void testSendLargeMessage() throws Exception {
final CountDownLatch failedOver = new CountDownLatch(1);
connection.setFailoverListener(new FailoverEventListener() {
@Override
public void failoverEvent(FailoverEventType eventType) {
failedOver.countDown();
}
});
Thread t;
{
final MapMessage message = createLargeMessage();
t = new Thread() {
@Override
public void run() {
try {
producer.send(message);
session.commit();
} catch (JMSException expected) {
expected.printStackTrace();
}
}
};
}
t.start();
// I'm trying to simulate the following race here:
// The message is syncing while the client is already sending the body of the message
Assert.assertTrue(flagArrived.await(10, TimeUnit.SECONDS));
startBackup();
waitForRemoteBackup(connection.getSessionFactory(), 30);
flagWait.countDown();
t.join(5000);
log.debug("Thread joined");
Assert.assertFalse(t.isAlive());
liveServer.fail(true);
Assert.assertTrue(failedOver.await(10, TimeUnit.SECONDS));
{
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
MapMessage message = (MapMessage) consumer.receive(5000);
Assert.assertNotNull(message);
for (int i = 0; i < 10; i++) {
Assert.assertEquals(1024 * 1024, message.getBytes("test" + i).length);
}
session.commit();
}
}
public static void syncLargeMessage() {
try {
flagArrived.countDown();
flagWait.await(10, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
private MapMessage createLargeMessage() throws JMSException {
MapMessage message = session.createMapMessage();
for (int i = 0; i < 10; i++) {
message.setBytes("test" + i, new byte[1024 * 1024]);
}
return message;
}
}

View File

@ -1,98 +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.activemq.artemis.tests.extras.byteman;
import java.util.concurrent.CountDownLatch;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.ReplicatedBackupUtils;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ReplicationBackupTest extends ActiveMQTestBase {
private static final CountDownLatch ruleFired = new CountDownLatch(1);
private ActiveMQServer backupServer;
private ActiveMQServer liveServer;
/*
* simple test to induce a potential race condition where the server's acceptors are active, but the server's
* state != STARTED
*/
@Test
@BMRules(
rules = {
@BMRule(
name = "prevent backup annoucement",
targetClass = "org.apache.activemq.artemis.core.server.impl.SharedNothingLiveActivation",
targetMethod = "run",
targetLocation = "AT EXIT",
action = "org.apache.activemq.artemis.tests.extras.byteman.ReplicationBackupTest.breakIt();")})
public void testReplicatedBackupAnnouncement() throws Exception {
TransportConfiguration liveConnector = TransportConfigurationUtils.getNettyConnector(true, 0);
TransportConfiguration liveAcceptor = TransportConfigurationUtils.getNettyAcceptor(true, 0);
TransportConfiguration backupConnector = TransportConfigurationUtils.getNettyConnector(false, 0);
TransportConfiguration backupAcceptor = TransportConfigurationUtils.getNettyAcceptor(false, 0);
Configuration backupConfig = createDefaultInVMConfig().setBindingsDirectory(getBindingsDir(0, true)).setJournalDirectory(getJournalDir(0, true)).setPagingDirectory(getPageDir(0, true)).setLargeMessagesDirectory(getLargeMessagesDir(0, true));
Configuration liveConfig = createDefaultInVMConfig();
ReplicatedBackupUtils.configureReplicationPair(backupConfig, backupConnector, backupAcceptor, liveConfig, liveConnector, liveAcceptor);
liveServer = createServer(liveConfig);
// start the live server in a new thread so we can start the backup simultaneously to induce a potential race
Thread startThread = new Thread(new Runnable() {
@Override
public void run() {
try {
liveServer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
startThread.start();
ruleFired.await();
backupServer = createServer(backupConfig);
backupServer.start();
ActiveMQTestBase.waitForRemoteBackup(null, 3, true, backupServer);
}
public static void breakIt() {
ruleFired.countDown();
try {
/* before the fix this sleep would put the "live" server into a state where the acceptors were started
* but the server's state != STARTED which would cause the backup to fail to announce
*/
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View File

@ -1,174 +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.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.core.config.ScaleDownConfiguration;
import org.apache.activemq.artemis.core.config.ha.LiveOnlyPolicyConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
import org.apache.activemq.artemis.tests.integration.cluster.distribution.ClusterTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ScaleDownFailoverTest extends ClusterTestBase {
private static final Logger log = Logger.getLogger(ScaleDownFailoverTest.class);
protected static int stopCount = 0;
private static ActiveMQServer[] staticServers;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
stopCount = 0;
setupLiveServer(0, isFileStorage(), HAType.SharedNothingReplication, isNetty(), true);
setupLiveServer(1, isFileStorage(), HAType.SharedNothingReplication, isNetty(), true);
setupLiveServer(2, isFileStorage(), HAType.SharedNothingReplication, isNetty(), true);
ScaleDownConfiguration scaleDownConfiguration = new ScaleDownConfiguration();
ScaleDownConfiguration scaleDownConfiguration2 = new ScaleDownConfiguration();
scaleDownConfiguration2.setEnabled(false);
ScaleDownConfiguration scaleDownConfiguration3 = new ScaleDownConfiguration();
scaleDownConfiguration3.setEnabled(false);
((LiveOnlyPolicyConfiguration) servers[0].getConfiguration().getHAPolicyConfiguration()).setScaleDownConfiguration(scaleDownConfiguration);
((LiveOnlyPolicyConfiguration) servers[1].getConfiguration().getHAPolicyConfiguration()).setScaleDownConfiguration(scaleDownConfiguration2);
((LiveOnlyPolicyConfiguration) servers[2].getConfiguration().getHAPolicyConfiguration()).setScaleDownConfiguration(scaleDownConfiguration3);
if (isGrouped()) {
scaleDownConfiguration.setGroupName("bill");
scaleDownConfiguration2.setGroupName("bill");
scaleDownConfiguration3.setGroupName("bill");
}
staticServers = servers;
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 0, 1, 2);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 1, 0, 2);
setupClusterConnection("cluster2", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 2, 0, 1);
scaleDownConfiguration.getConnectors().addAll(servers[0].getConfiguration().getClusterConfigurations().iterator().next().getStaticConnectors());
scaleDownConfiguration2.getConnectors().addAll(servers[1].getConfiguration().getClusterConfigurations().iterator().next().getStaticConnectors());
scaleDownConfiguration3.getConnectors().addAll(servers[2].getConfiguration().getClusterConfigurations().iterator().next().getStaticConnectors());
startServers(0, 1, 2);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
setupSessionFactory(2, isNetty());
}
protected boolean isNetty() {
return true;
}
protected boolean isGrouped() {
return false;
}
@Test
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.api.core.client.ServerLocator",
targetMethod = "createSessionFactory(org.apache.activemq.artemis.api.core.TransportConfiguration, int, boolean)",
isInterface = true,
targetLocation = "ENTRY",
action = "org.apache.activemq.artemis.tests.extras.byteman.ScaleDownFailoverTest.fail($1);")
public void testScaleDownWhenFirstServerFails() throws Exception {
final int TEST_SIZE = 2;
final String addressName = "testAddress";
final String queueName1 = "testQueue1";
final String queueName2 = "testQueue2";
// create 2 queues on each node mapped to the same address
createQueue(0, addressName, queueName1, null, false);
createQueue(0, addressName, queueName2, null, false);
createQueue(1, addressName, queueName1, null, false);
createQueue(1, addressName, queueName2, null, false);
createQueue(2, addressName, queueName1, null, false);
createQueue(2, addressName, queueName2, null, false);
// send messages to node 0
send(0, addressName, TEST_SIZE, false, null);
// consume a message from node 0
addConsumer(0, 0, queueName2, null);
ClientMessage clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
removeConsumer(0);
servers[0].stop();
// verify that at least one server stopped
Assert.assertTrue(!servers[1].isStarted() || !servers[2].isStarted());
int remainingServer;
if (servers[1].isStarted())
remainingServer = 1;
else
remainingServer = 2;
// get the 2 messages from queue 1
addConsumer(0, remainingServer, queueName1, null);
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
// ensure there are no more messages on queue 1
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNull(clientMessage);
removeConsumer(0);
// get the 1 message from queue 2
addConsumer(0, remainingServer, queueName2, null);
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
// ensure there are no more messages on queue 1
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNull(clientMessage);
removeConsumer(0);
}
public static void fail(TransportConfiguration tc) {
// only kill one server
if (stopCount == 0) {
try {
for (ActiveMQServer activeMQServer : staticServers) {
if (activeMQServer != null) {
for (TransportConfiguration transportConfiguration : activeMQServer.getConfiguration().getAcceptorConfigurations()) {
if (transportConfiguration.getParams().get(TransportConstants.PORT_PROP_NAME).equals(tc.getParams().get(TransportConstants.PORT_PROP_NAME))) {
activeMQServer.stop();
stopCount++;
log.debug("Stopping server listening at: " + tc.getParams().get(TransportConstants.PORT_PROP_NAME));
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@ -1,98 +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.activemq.artemis.tests.extras.byteman;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.core.config.ScaleDownConfiguration;
import org.apache.activemq.artemis.core.config.ha.LiveOnlyPolicyConfiguration;
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
import org.apache.activemq.artemis.tests.integration.cluster.distribution.ClusterTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class ScaleDownFailureTest extends ClusterTestBase {
@Override
@Before
public void setUp() throws Exception {
super.setUp();
setupLiveServer(0, isFileStorage(), HAType.SharedNothingReplication, isNetty(), true);
setupLiveServer(1, isFileStorage(), HAType.SharedNothingReplication, isNetty(), true);
if (isGrouped()) {
ScaleDownConfiguration scaleDownConfiguration = new ScaleDownConfiguration();
scaleDownConfiguration.setGroupName("bill");
((LiveOnlyPolicyConfiguration) servers[0].getConfiguration().getHAPolicyConfiguration()).setScaleDownConfiguration(scaleDownConfiguration);
((LiveOnlyPolicyConfiguration) servers[1].getConfiguration().getHAPolicyConfiguration()).setScaleDownConfiguration(scaleDownConfiguration);
}
setupClusterConnection("cluster0", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 0, 1);
setupClusterConnection("cluster1", "queues", MessageLoadBalancingType.ON_DEMAND, 1, isNetty(), 1, 0);
startServers(0, 1);
setupSessionFactory(0, isNetty());
setupSessionFactory(1, isNetty());
}
protected boolean isNetty() {
return true;
}
protected boolean isGrouped() {
return false;
}
@Test
@BMRule(
name = "blow-up",
targetClass = "org.apache.activemq.artemis.api.core.client.ServerLocator",
targetMethod = "createSessionFactory(org.apache.activemq.artemis.api.core.TransportConfiguration, int, boolean)",
isInterface = true,
targetLocation = "ENTRY",
action = "throw new Exception()")
public void testScaleDownWhenRemoteServerIsUnavailable() throws Exception {
final int TEST_SIZE = 1;
final String addressName = "testAddress";
final String queueName1 = "testQueue1";
final String queueName2 = "testQueue2";
// create 2 queues on each node mapped to the same address
createQueue(0, addressName, queueName1, null, false);
createQueue(0, addressName, queueName2, null, false);
createQueue(1, addressName, queueName1, null, false);
createQueue(1, addressName, queueName2, null, false);
// send messages to node 0
send(0, addressName, TEST_SIZE, false, null);
// consume a message from node 0
addConsumer(0, 0, queueName2, null, false);
ClientMessage clientMessage = consumers[0].getConsumer().receive();
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
consumers[0].getSession().commit();
removeConsumer(0);
servers[0].stop();
addConsumer(0, 1, queueName1, null);
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNull(clientMessage);
}
}

View File

@ -1,25 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
public class ScaleDownGroupedFailoverTest extends ScaleDownFailoverTest {
@Override
protected boolean isGrouped() {
return true;
}
}

View File

@ -1,25 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
public class ScaleDownGroupedFailureTest extends ScaleDownFailureTest {
@Override
protected boolean isGrouped() {
return true;
}
}

View File

@ -1,136 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration;
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
import org.apache.activemq.artemis.tests.unit.util.InVMNamingContext;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* This test validates a deadlock identified by https://bugzilla.redhat.com/show_bug.cgi?id=959616
*/
@RunWith(BMUnitRunner.class)
public class StartStopDeadlockTest extends ActiveMQTestBase {
private static final Logger log = Logger.getLogger(StartStopDeadlockTest.class);
private static void debugLog(String message) {
log.debug(message);
}
/*
* simple test to make sure connect still works with some network latency built into netty
* */
@Test
@BMRules(
rules = {
@BMRule(
name = "Server.start wait-init",
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "initialisePart2",
targetLocation = "ENTRY",
condition = "incrementCounter(\"server-Init\") == 2",
action = "org.apache.activemq.artemis.tests.extras.byteman.StartStopDeadlockTest.debugLog(\"server backup init\"), waitFor(\"start-init\")"),
@BMRule(
name = "JMSServer.stop wait-init",
targetClass = "org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl",
targetMethod = "stop",
targetLocation = "ENTRY",
action = "signalWake(\"start-init\", true)"),
@BMRule(
name = "StartStopDeadlockTest tearDown",
targetClass = "org.apache.activemq.artemis.tests.extras.byteman.StartStopDeadlockTest",
targetMethod = "tearDown",
targetLocation = "ENTRY",
action = "deleteCounter(\"server-Init\")")})
public void testDeadlock() throws Exception {
// A live server that will always be crashed
Configuration confLive = createDefaultNettyConfig().setHAPolicyConfiguration(new SharedStoreMasterPolicyConfiguration());
final ActiveMQServer serverLive = addServer(ActiveMQServers.newActiveMQServer(confLive));
serverLive.start();
// A backup that will be waiting to be activated
Configuration config = createDefaultNettyConfig().setHAPolicyConfiguration(new SharedStoreSlavePolicyConfiguration());
final ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(config, true));
final JMSServerManagerImpl jmsServer = new JMSServerManagerImpl(server);
final InVMNamingContext context = new InVMNamingContext();
jmsServer.setRegistry(new JndiBindingRegistry(context));
jmsServer.start();
final AtomicInteger errors = new AtomicInteger(0);
final CountDownLatch align = new CountDownLatch(2);
final CountDownLatch startLatch = new CountDownLatch(1);
Thread tCrasher = new Thread("tStart") {
@Override
public void run() {
try {
align.countDown();
startLatch.await();
log.debug("Crashing....");
serverLive.fail(true);
} catch (Exception e) {
errors.incrementAndGet();
e.printStackTrace();
}
}
};
Thread tStop = new Thread("tStop") {
@Override
public void run() {
try {
align.countDown();
startLatch.await();
jmsServer.stop();
} catch (Exception e) {
errors.incrementAndGet();
e.printStackTrace();
}
}
};
tCrasher.start();
tStop.start();
align.await();
startLatch.countDown();
tCrasher.join();
tStop.join();
assertEquals(0, errors.get());
}
}

View File

@ -1,114 +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.activemq.artemis.tests.extras.byteman;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.core.management.CoreNotificationType;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManagerFactory;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class StompInternalStateTest extends ActiveMQTestBase {
private static final String STOMP_QUEUE_NAME = "StompTestQueue";
private String resultTestStompProtocolManagerLeak = null;
protected ActiveMQServer server = null;
@Test
@BMRules(
rules = {
@BMRule(
name = "StompProtocolManager Leak Server Rule",
targetClass = "org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManager",
targetMethod = "onNotification(org.apache.activemq.artemis.core.server.management.Notification)",
targetLocation = "EXIT",
helper = "org.apache.activemq.artemis.tests.extras.byteman.StompInternalStateTest",
action = "verifyBindingAddRemove($1, $0.destinations)")})
public void testStompProtocolManagerLeak() throws Exception {
ClientSession session = null;
try {
assertNull(resultTestStompProtocolManagerLeak);
ServerLocator locator = createNettyNonHALocator();
ClientSessionFactory factory = createSessionFactory(locator);
session = factory.createSession();
session.createQueue(new QueueConfiguration(STOMP_QUEUE_NAME).setDurable(false).setTemporary(true));
session.deleteQueue(STOMP_QUEUE_NAME);
assertNull(resultTestStompProtocolManagerLeak);
} finally {
if (session != null) {
session.close();
}
}
}
@Override
protected Configuration createDefaultConfig(final boolean netty) throws Exception {
Map<String, Object> params = new HashMap<>();
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME);
params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_STOMP_PORT);
params.put(TransportConstants.STOMP_CONSUMERS_CREDIT, "-1");
TransportConfiguration stompTransport = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
Configuration config = super.createDefaultConfig(netty).setPersistenceEnabled(false).addAcceptorConfiguration(stompTransport);
return config;
}
@SuppressWarnings("unchecked")
public void verifyBindingAddRemove(Notification noti, Object obj) {
Set<String> destinations = (Set<String>) obj;
if (noti.getType() == CoreNotificationType.BINDING_ADDED) {
if (!destinations.contains(STOMP_QUEUE_NAME)) {
resultTestStompProtocolManagerLeak += "didn't save the queue when binding added " + destinations;
}
} else if (noti.getType() == CoreNotificationType.BINDING_REMOVED) {
if (destinations.contains(STOMP_QUEUE_NAME)) {
resultTestStompProtocolManagerLeak = "didn't remove the queue when binding removed " + destinations;
}
}
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server = createServer(createDefaultNettyConfig());
server.start();
}
}

View File

@ -1,219 +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.activemq.artemis.tests.extras.byteman;
import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.XAConnection;
import javax.jms.XASession;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class TimeoutXATest extends ActiveMQTestBase {
protected ActiveMQServer server = null;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server = createServer(createDefaultNettyConfig());
server.getConfiguration().setTransactionTimeout(1000);
server.getConfiguration().setTransactionTimeoutScanPeriod(1100);
server.getConfiguration().setJournalSyncNonTransactional(false);
server.start();
server.createQueue(new QueueConfiguration("Queue1").setRoutingType(RoutingType.ANYCAST));
removingTXEntered0 = new CountDownLatch(1);
removingTXAwait0 = new CountDownLatch(1);
removingTXEntered1 = new CountDownLatch(1);
removingTXAwait1 = new CountDownLatch(1);
entered = 0;
enteredRollback = 0;
enteredRollbackLatch = new CountDownLatch(1);
waitingRollbackLatch = new CountDownLatch(1);
}
static int entered;
static CountDownLatch removingTXEntered0;
static CountDownLatch removingTXAwait0;
static CountDownLatch removingTXEntered1;
static CountDownLatch removingTXAwait1;
static int enteredRollback;
static CountDownLatch enteredRollbackLatch;
static CountDownLatch waitingRollbackLatch;
@Test
@BMRules(
rules = {
@BMRule(
name = "removing TX",
targetClass = "org.apache.activemq.artemis.core.transaction.impl.ResourceManagerImpl",
targetMethod = "removeTransaction(javax.transaction.xa.Xid)",
targetLocation = "ENTRY",
helper = "org.apache.activemq.artemis.tests.extras.byteman.TimeoutXATest",
action = "removingTX()"),
@BMRule(
name = "afterRollback TX",
targetClass = "org.apache.activemq.artemis.core.transaction.impl.TransactionImpl",
targetMethod = "afterRollback",
targetLocation = "ENTRY",
helper = "org.apache.activemq.artemis.tests.extras.byteman.TimeoutXATest",
action = "afterRollback()")})
public void testTimeoutOnTX2() throws Exception {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
XAConnection connection = connectionFactory.createXAConnection();
Connection connction2 = connectionFactory.createConnection();
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Queue queue = session.createQueue("Queue1");
MessageProducer producer = session.createProducer(queue);
for (int i = 0; i < 10; i++) {
producer.send(session.createTextMessage("hello " + 1));
}
session.commit();
final XASession xaSession = connection.createXASession();
final Xid xid = newXID();
xaSession.getXAResource().start(xid, XAResource.TMNOFLAGS);
MessageConsumer consumer = xaSession.createConsumer(queue);
connection.start();
for (int i = 0; i < 10; i++) {
Assert.assertNotNull(consumer.receive(5000));
}
xaSession.getXAResource().end(xid, XAResource.TMSUCCESS);
final CountDownLatch latchStore = new CountDownLatch(1000);
Thread storingThread = new Thread() {
@Override
public void run() {
try {
for (int i = 0; i < 100000; i++) {
latchStore.countDown();
server.getStorageManager().storeDuplicateID(SimpleString.toSimpleString("crebis"), new byte[]{1}, server.getStorageManager().generateID());
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
removingTXEntered0.await();
Thread t = new Thread() {
@Override
public void run() {
try {
xaSession.getXAResource().rollback(xid);
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
removingTXEntered1.await();
storingThread.start();
latchStore.await();
removingTXAwait1.countDown();
Thread.sleep(1000);
removingTXAwait0.countDown();
Assert.assertTrue(enteredRollbackLatch.await(10, TimeUnit.SECONDS));
waitingRollbackLatch.countDown();
t.join();
consumer.close();
consumer = session.createConsumer(queue);
for (int i = 0; i < 10; i++) {
Assert.assertNotNull(consumer.receive(5000));
}
Assert.assertNull(consumer.receiveNoWait());
connection.close();
connction2.close();
}
public void afterRollback() {
if (enteredRollback++ == 0) {
enteredRollbackLatch.countDown();
try {
waitingRollbackLatch.await();
} catch (Throwable e) {
}
}
}
public void removingTX() {
int xent = entered++;
if (xent == 0) {
removingTXEntered0.countDown();
try {
removingTXAwait0.await();
} catch (Throwable ignored) {
ignored.printStackTrace();
}
} else if (xent == 1) {
removingTXEntered1.countDown();
try {
removingTXAwait1.await();
} catch (Throwable ignored) {
ignored.printStackTrace();
}
}
}
}

View File

@ -1,92 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman.critical.analyzer;
import javax.jms.DeliveryMode;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
import org.junit.Before;
public abstract class CriticalAnalyzerFaultInjectionTestBase extends JMSTestBase {
// Critical Analyzer Settings
private static long CHECK_PERIOD = 100;
private static long TIMEOUT = 3000;
protected SimpleString address = SimpleString.toSimpleString("faultInjectionTestAddress");
private Thread t;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server.addAddressInfo(new AddressInfo(address, RoutingType.ANYCAST));
server.createQueue(new QueueConfiguration(address).setRoutingType(RoutingType.ANYCAST));
conn = nettyCf.createConnection();
}
/*
Checks every 100ms timesout after 3000ms. Test should wait no longer than 3100s + Shutdown time.
*/
@Override
protected Configuration createDefaultConfig(boolean netty) throws Exception {
return super.createDefaultConfig(netty).setCriticalAnalyzerPolicy(CriticalAnalyzerPolicy.SHUTDOWN).setCriticalAnalyzer(true).setCriticalAnalyzerCheckPeriod(CHECK_PERIOD).setCriticalAnalyzerTimeout(TIMEOUT).setJournalType(JournalType.NIO);
}
@Override
public boolean usePersistence() {
return true;
}
void testSendDurableMessage() throws Exception {
try {
t = new Thread(() -> {
try {
Session s = conn.createSession(true, Session.SESSION_TRANSACTED);
Queue jmsQueue = s.createQueue(address.toString());
MessageProducer p = s.createProducer(jmsQueue);
p.setDeliveryMode(DeliveryMode.PERSISTENT);
conn.start();
for (int i = 0; i < 10; i++) {
p.send(s.createTextMessage("payload"));
}
s.commit();
} catch (Throwable e) {
e.printStackTrace();
}
});
t.start();
Wait.assertFalse(server::isStarted);
} finally {
t.interrupt();
}
}
}

View File

@ -1,81 +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.activemq.artemis.tests.extras.byteman.critical.analyzer;
import java.lang.reflect.Field;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.activemq.artemis.core.persistence.impl.journal.AbstractJournalStorageManager;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class DeadlockStorageManagerTest extends CriticalAnalyzerFaultInjectionTestBase {
private static Thread lockT;
@BMRules(
rules = {
@BMRule(
name = "Deadlock on Storage Manager",
targetClass = "org.apache.activemq.artemis.core.persistence.impl.journal.AbstractJournalStorageManager",
targetMethod = "commit",
targetLocation = "ENTRY",
condition = "!flagged(\"testDeadlockOnStorageManager\")",
action = "org.apache.activemq.artemis.tests.extras.byteman.critical.analyzer.DeadlockStorageManagerTest.acquireStorageManagerLock($0);"),
@BMRule(
name = "Release Suspended Thread during Server Shutdown", // Releases wakes up suspended threads to allow shutdown to complete
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "stop",
targetLocation = "ENTRY",
action = "flag(\"testDeadlockOnStorageManager\"); org.apache.activemq.artemis.tests.extras.byteman.critical.analyzer.DeadlockStorageManagerTest.releaseStorageManagerLock()" )
})
@Test(timeout = 60000)
public void testDeadlockOnStorageManager() throws Exception {
testSendDurableMessage();
}
public static void acquireStorageManagerLock(final Object o) throws Exception {
// We're attempting to cause a deadlock on the readlock. This means we need to grab the write lock
// in a separate thread.
if (lockT == null) {
lockT = new Thread(() -> {
try {
Field field = AbstractJournalStorageManager.class.getDeclaredField("storageManagerLock");
field.setAccessible(true);
ReentrantReadWriteLock lock = ((ReentrantReadWriteLock) field.get(o));
lock.writeLock().lock();
try {
Thread.sleep(10000);
} catch (InterruptedException ie) {
lock.writeLock().unlock();
}
} catch (Exception e) {
fail();
}
});
lockT.start();
}
}
public static void releaseStorageManagerLock() throws NoSuchFieldException, IllegalAccessException {
lockT.interrupt();
}
}

View File

@ -1,48 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.byteman.critical.analyzer;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class DeadlockedQueueTest extends CriticalAnalyzerFaultInjectionTestBase {
@BMRules(
rules = {
@BMRule(
name = "Deadlock during Queue Delivery",
targetClass = "org.apache.activemq.artemis.core.server.impl.QueueImpl",
targetMethod = "deliver",
targetLocation = "AFTER SYNCHRONIZE",
condition = "!flagged(\"testDeadlockOnQueue\")",
action = "waitFor(\"testDeadlockOnQueue\")"),
@BMRule(
name = "Release Suspended Thread during Server Shutdown", // Releases wakes up suspended threads to allow shutdown to complete
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "stop",
targetLocation = "ENTRY",
action = "flag(\"testDeadlockOnQueue\"); signalWake(\"testDeadlockOnQueue\")")
})
@Test(timeout = 60000)
public void testDeadlockOnQueue() throws Exception {
testSendDurableMessage();
}
}

View File

@ -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.activemq.artemis.tests.extras.byteman.critical.analyzer;
import javax.jms.DeliveryMode;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMRules;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BMUnitRunner.class)
public class FileSystemSyncBlockedTest extends CriticalAnalyzerFaultInjectionTestBase {
private static final Logger log = Logger.getLogger(FileSystemSyncBlockedTest.class);
@BMRules(rules = {
@BMRule(
name = "Simulate Slow Disk Sync",
targetClass = "org.apache.activemq.artemis.core.io.nio.NIOSequentialFile",
targetMethod = "sync",
targetLocation = "ENTRY",
condition = "!flagged(\"testSlowDiskSync\")", // Once the server shutdowns we stop applying this rule.
action = "waitFor(\"testSlowDiskSync\")"),
@BMRule(
// We ensure that no more
name = "Release Suspended Thread during Server Shutdown", // Releases wakes up suspended threads to allow shutdown to complete
targetClass = "org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl",
targetMethod = "stop",
targetLocation = "ENTRY",
action = "flag(\"testSlowDiskSync\"); signalWake(\"testSlowDiskSync\")")})
@Test(timeout = 60000)
public void testSlowDiskSync() throws Exception {
testSendDurableMessage();
}
@Test
public void testManyFiles() throws Exception {
Session s = conn.createSession(true, Session.SESSION_TRANSACTED);
Queue jmsQueue = s.createQueue(address.toString());
MessageProducer p = s.createProducer(jmsQueue);
p.setDeliveryMode(DeliveryMode.PERSISTENT);
conn.start();
for (int i = 0; i < 1000; i++) {
p.send(s.createTextMessage("payload"));
server.getStorageManager().getMessageJournal().forceMoveNextFile();
}
s.commit();
// if you have more than 100 components, then you have a leak!
Assert.assertTrue(server.getStorageManager().getJournalSequentialFileFactory().getCriticalAnalyzer().getNumberOfComponents() < 10);
log.debug("Number of components:" + server.getStorageManager().getJournalSequentialFileFactory().getCriticalAnalyzer().getNumberOfComponents());
}
}

View File

@ -1,488 +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.activemq.artemis.tests.extras.jms.bridge;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
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 javax.jms.Topic;
import javax.jms.XAConnectionFactory;
import javax.transaction.TransactionManager;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.management.AddressControl;
import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.core.server.management.ManagementService;
import org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory;
import org.apache.activemq.artemis.jms.bridge.DestinationFactory;
import org.apache.activemq.artemis.jms.bridge.QualityOfServiceMode;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQMessage;
import org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
public abstract class BridgeTestBase extends ActiveMQTestBase {
protected ConnectionFactoryFactory cff0, cff1;
protected ConnectionFactoryFactory cff0xa, cff1xa;
protected ConnectionFactory cf0, cf1;
protected XAConnectionFactory cf0xa, cf1xa;
protected DestinationFactory sourceQueueFactory;
protected DestinationFactory targetQueueFactory;
protected DestinationFactory localTargetQueueFactory;
protected DestinationFactory sourceTopicFactory;
protected Queue sourceQueue, targetQueue, localTargetQueue;
protected Topic sourceTopic;
protected ActiveMQServer server0;
protected ActiveMQServer server1;
protected HashMap<String, Object> params1;
protected ConnectionFactoryFactory cff0LowProducerWindow;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
// Start the servers
Configuration conf0 = createBasicConfig().setJournalDirectory(getJournalDir(0, false)).setBindingsDirectory(getBindingsDir(0, false)).addAcceptorConfiguration(new TransportConfiguration(INVM_ACCEPTOR_FACTORY));
server0 = addServer(ActiveMQServers.newActiveMQServer(conf0, false));
server0.start();
params1 = new HashMap<>();
params1.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
Configuration conf1 = createBasicConfig().setJournalDirectory(getJournalDir(1, false)).setBindingsDirectory(getBindingsDir(1, false)).addAcceptorConfiguration(new TransportConfiguration(INVM_ACCEPTOR_FACTORY, params1));
server1 = addServer(ActiveMQServers.newActiveMQServer(conf1, false));
server1.start();
setUpAdministeredObjects();
TxControl.enable();
// We need a local transaction and recovery manager
// We must start this after the remote servers have been created or it won't
// have deleted the database and the recovery manager may attempt to recover transactions
}
protected void createQueue(final String queueName, final int index) throws Exception {
ActiveMQServer server = server0;
if (index == 1) {
server = server1;
}
assertTrue("queue '/queue/" + queueName + "' created", server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST)) != null);
}
@Override
@After
public void tearDown() throws Exception {
checkEmpty(sourceQueue, 0);
checkEmpty(localTargetQueue, 0);
checkEmpty(targetQueue, 1);
// Check no subscriptions left lying around
checkNoSubscriptions(sourceTopic, 0);
if (cff0 instanceof ActiveMQConnectionFactory) {
((ActiveMQConnectionFactory) cff0).close();
}
if (cff1 instanceof ActiveMQConnectionFactory) {
((ActiveMQConnectionFactory) cff1).close();
}
stopComponent(server0);
stopComponent(server1);
cff0 = cff1 = null;
cff0xa = cff1xa = null;
cf0 = cf1 = null;
cf0xa = cf1xa = null;
sourceQueueFactory = targetQueueFactory = localTargetQueueFactory = sourceTopicFactory = null;
sourceQueue = targetQueue = localTargetQueue = null;
sourceTopic = null;
server0 = null;
server1 = null;
// Shutting down Arjuna threads
TxControl.disable(true);
TransactionReaper.terminate(false);
super.tearDown();
}
protected void setUpAdministeredObjects() throws Exception {
cff0LowProducerWindow = new ConnectionFactoryFactory() {
@Override
public ConnectionFactory createConnectionFactory() throws Exception {
ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
// Note! We disable automatic reconnection on the session factory. The bridge needs to do the reconnection
cf.setReconnectAttempts(0);
cf.setBlockOnNonDurableSend(true);
cf.setBlockOnDurableSend(true);
cf.setCacheLargeMessagesClient(true);
cf.setProducerWindowSize(100);
return cf;
}
};
cff0 = new ConnectionFactoryFactory() {
@Override
public ConnectionFactory createConnectionFactory() throws Exception {
ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
// Note! We disable automatic reconnection on the session factory. The bridge needs to do the reconnection
cf.setReconnectAttempts(0);
cf.setBlockOnNonDurableSend(true);
cf.setBlockOnDurableSend(true);
cf.setCacheLargeMessagesClient(true);
return cf;
}
};
cff0xa = new ConnectionFactoryFactory() {
@Override
public Object createConnectionFactory() throws Exception {
ActiveMQXAConnectionFactory cf = (ActiveMQXAConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.XA_CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
// Note! We disable automatic reconnection on the session factory. The bridge needs to do the reconnection
cf.setReconnectAttempts(0);
cf.setBlockOnNonDurableSend(true);
cf.setBlockOnDurableSend(true);
cf.setCacheLargeMessagesClient(true);
return cf;
}
};
cf0 = (ConnectionFactory) cff0.createConnectionFactory();
cf0xa = (XAConnectionFactory) cff0xa.createConnectionFactory();
cff1 = new ConnectionFactoryFactory() {
@Override
public ConnectionFactory createConnectionFactory() throws Exception {
ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY, params1));
// Note! We disable automatic reconnection on the session factory. The bridge needs to do the reconnection
cf.setReconnectAttempts(0);
cf.setBlockOnNonDurableSend(true);
cf.setBlockOnDurableSend(true);
cf.setCacheLargeMessagesClient(true);
return cf;
}
};
cff1xa = new ConnectionFactoryFactory() {
@Override
public XAConnectionFactory createConnectionFactory() throws Exception {
ActiveMQXAConnectionFactory cf = (ActiveMQXAConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.XA_CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY, params1));
// Note! We disable automatic reconnection on the session factory. The bridge needs to do the reconnection
cf.setReconnectAttempts(0);
cf.setBlockOnNonDurableSend(true);
cf.setBlockOnDurableSend(true);
cf.setCacheLargeMessagesClient(true);
return cf;
}
};
cf1 = (ConnectionFactory) cff1.createConnectionFactory();
cf1xa = (XAConnectionFactory) cff1xa.createConnectionFactory();
sourceQueueFactory = new DestinationFactory() {
@Override
public Destination createDestination() throws Exception {
return ActiveMQDestination.createDestination("/queue/sourceQueue", ActiveMQDestination.TYPE.QUEUE);
}
};
sourceQueue = (Queue) sourceQueueFactory.createDestination();
targetQueueFactory = new DestinationFactory() {
@Override
public Destination createDestination() throws Exception {
return ActiveMQDestination.createDestination("/queue/targetQueue", ActiveMQDestination.TYPE.QUEUE);
}
};
targetQueue = (Queue) targetQueueFactory.createDestination();
sourceTopicFactory = new DestinationFactory() {
@Override
public Destination createDestination() throws Exception {
return ActiveMQDestination.createDestination("/topic/sourceTopic", ActiveMQDestination.TYPE.TOPIC);
}
};
sourceTopic = (Topic) sourceTopicFactory.createDestination();
localTargetQueueFactory = new DestinationFactory() {
@Override
public Destination createDestination() throws Exception {
return ActiveMQDestination.createDestination("/queue/localTargetQueue", ActiveMQDestination.TYPE.QUEUE);
}
};
localTargetQueue = (Queue) localTargetQueueFactory.createDestination();
}
protected void sendMessages(final ConnectionFactory cf,
final Destination dest,
final int start,
final int numMessages,
final boolean persistent,
final boolean largeMessage) throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sess.createProducer(dest);
prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
for (int i = start; i < start + numMessages; i++) {
if (largeMessage) {
BytesMessage msg = sess.createBytesMessage();
((ActiveMQMessage) msg).setInputStream(ActiveMQTestBase.createFakeLargeStream(1024L * 1024L));
msg.setStringProperty("msg", "message" + i);
prod.send(msg);
} else {
TextMessage tm = sess.createTextMessage("message" + i);
prod.send(tm);
}
}
} finally {
if (conn != null) {
conn.close();
}
}
}
protected void checkMessagesReceived(final ConnectionFactory cf,
final Destination dest,
final QualityOfServiceMode qosMode,
final int numMessages,
final boolean longWaitForFirst,
final boolean largeMessage) throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
conn.start();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons = sess.createConsumer(dest);
// Consume the messages
Set<String> msgs = new HashSet<>();
int count = 0;
// We always wait longer for the first one - it may take some time to arrive especially if we are
// waiting for recovery to kick in
while (true) {
Message tm = cons.receive(count == 0 ? (longWaitForFirst ? 60000 : 10000) : 5000);
if (tm == null) {
break;
}
// log.info("Got message " + tm.getText());
if (largeMessage) {
BytesMessage bmsg = (BytesMessage) tm;
msgs.add(tm.getStringProperty("msg"));
byte[] buffRead = new byte[1024];
for (int i = 0; i < 1024; i++) {
Assert.assertEquals(1024, bmsg.readBytes(buffRead));
}
} else {
msgs.add(((TextMessage) tm).getText());
}
count++;
}
if (qosMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE || qosMode == QualityOfServiceMode.DUPLICATES_OK) {
// All the messages should be received
for (int i = 0; i < numMessages; i++) {
Assert.assertTrue("quality=" + qosMode + ", #=" + i + ", message=" + msgs, msgs.contains("message" + i));
}
// Should be no more
if (qosMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE) {
Assert.assertEquals(numMessages, msgs.size());
}
} else if (qosMode == QualityOfServiceMode.AT_MOST_ONCE) {
// No *guarantee* that any messages will be received
// but you still might get some depending on how/where the crash occurred
}
} finally {
if (conn != null) {
conn.close();
}
}
}
protected void checkAllMessageReceivedInOrder(final ConnectionFactory cf,
final Destination dest,
final int start,
final int numMessages,
final boolean largeMessage) throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
conn.start();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons = sess.createConsumer(dest);
// Consume the messages
for (int i = 0; i < numMessages; i++) {
Message tm = cons.receive(3000);
Assert.assertNotNull(tm);
if (largeMessage) {
BytesMessage bmsg = (BytesMessage) tm;
Assert.assertEquals("message" + (i + start), tm.getStringProperty("msg"));
byte[] buffRead = new byte[1024];
for (int j = 0; j < 1024; j++) {
Assert.assertEquals(1024, bmsg.readBytes(buffRead));
}
} else {
Assert.assertEquals("message" + (i + start), ((TextMessage) tm).getText());
}
}
} finally {
if (conn != null) {
conn.close();
}
}
}
public boolean checkEmpty(final Queue queue, final int index) throws Exception {
ManagementService managementService = server0.getManagementService();
if (index == 1) {
managementService = server1.getManagementService();
}
QueueControl queueControl = (QueueControl) managementService.getResource(ResourceNames.QUEUE + queue.getQueueName());
//server may be closed
if (queueControl != null) {
queueControl.flushExecutor();
Long messageCount = queueControl.getMessageCount();
if (messageCount > 0) {
queueControl.removeMessages(null);
}
}
return true;
}
protected void checkNoSubscriptions(final Topic topic, final int index) throws Exception {
ManagementService managementService = server0.getManagementService();
if (index == 1) {
managementService = server1.getManagementService();
}
AddressControl topicControl = (AddressControl) managementService.getResource(ResourceNames.ADDRESS + topic.getTopicName());
if (topicControl != null) {
Assert.assertEquals(0, topicControl.getQueueNames().length);
}
}
protected void removeAllMessages(final String queueName, final int index) throws Exception {
ManagementService managementService = server0.getManagementService();
if (index == 1) {
managementService = server1.getManagementService();
}
QueueControl queueControl = (QueueControl) managementService.getResource("queue." + queueName);
if (queueControl != null) {
queueControl.removeMessages(null);
}
}
protected TransactionManager newTransactionManager() {
return new TransactionManagerImple();
}
}

View File

@ -1,257 +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.activemq.artemis.tests.extras.jms.bridge;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.FailoverEventListener;
import org.apache.activemq.artemis.api.core.client.FailoverEventType;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicatedPolicyConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory;
import org.apache.activemq.artemis.jms.bridge.DestinationFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.After;
import org.junit.Before;
/**
* A ClusteredBridgeTestBase
* This class serves as a base class for jms bridge tests in
* clustered scenarios.
*/
public abstract class ClusteredBridgeTestBase extends ActiveMQTestBase {
private static int index = 0;
private static final int QUORUM_VOTE_WAIT_TIME_SEC = 30;
protected Map<String, ServerGroup> groups = new HashMap<>();
@Override
@Before
public void setUp() throws Exception {
super.setUp();
Iterator<ServerGroup> iter = groups.values().iterator();
while (iter.hasNext()) {
iter.next().start();
}
TxControl.enable();
}
@Override
@After
public void tearDown() throws Exception {
Iterator<ServerGroup> iter = groups.values().iterator();
while (iter.hasNext()) {
iter.next().stop();
}
TxControl.disable(true);
TransactionReaper.terminate(false);
super.tearDown();
}
//create a live/backup pair.
protected ServerGroup createServerGroup(String name) throws Exception {
ServerGroup server = groups.get(name);
if (server == null) {
server = new ServerGroup(name, groups.size());
server.create();
groups.put(name, server);
}
return server;
}
//each ServerGroup represents a live/backup pair
protected class ServerGroup {
private static final int ID_OFFSET = 100;
private String name;
private int id;
private ActiveMQServer liveNode;
private ActiveMQServer backupNode;
private TransportConfiguration liveConnector;
private TransportConfiguration backupConnector;
private ServerLocator locator;
private ClientSessionFactory sessionFactory;
/**
* @param name - name of the group
* @param id - id of the live (should be < 100)
*/
public ServerGroup(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void create() throws Exception {
Map<String, Object> params0 = new HashMap<>();
params0.put(TransportConstants.SERVER_ID_PROP_NAME, id);
liveConnector = new TransportConfiguration(INVM_CONNECTOR_FACTORY, params0, "in-vm-live");
Map<String, Object> params = new HashMap<>();
params.put(TransportConstants.SERVER_ID_PROP_NAME, id + ID_OFFSET);
backupConnector = new TransportConfiguration(INVM_CONNECTOR_FACTORY, params, "in-vm-backup");
//live
Configuration conf0 = createBasicConfig().setJournalDirectory(getJournalDir(id, false)).setBindingsDirectory(getBindingsDir(id, false)).addAcceptorConfiguration(new TransportConfiguration(INVM_ACCEPTOR_FACTORY, params0)).addConnectorConfiguration(liveConnector.getName(), liveConnector).setHAPolicyConfiguration(new ReplicatedPolicyConfiguration()).addClusterConfiguration(basicClusterConnectionConfig(liveConnector.getName()));
liveNode = addServer(ActiveMQServers.newActiveMQServer(conf0, true));
//backup
ReplicaPolicyConfiguration replicaPolicyConfiguration = new ReplicaPolicyConfiguration();
replicaPolicyConfiguration.setQuorumVoteWait(QUORUM_VOTE_WAIT_TIME_SEC);
Configuration config = createBasicConfig().setJournalDirectory(getJournalDir(id, true)).setBindingsDirectory(getBindingsDir(id, true)).addAcceptorConfiguration(new TransportConfiguration(INVM_ACCEPTOR_FACTORY, params)).addConnectorConfiguration(backupConnector.getName(), backupConnector).addConnectorConfiguration(liveConnector.getName(), liveConnector).setHAPolicyConfiguration(replicaPolicyConfiguration).addClusterConfiguration(basicClusterConnectionConfig(backupConnector.getName(), liveConnector.getName()));
backupNode = addServer(ActiveMQServers.newActiveMQServer(config, true));
}
public void start() throws Exception {
liveNode.start();
waitForServerToStart(liveNode);
backupNode.start();
waitForRemoteBackupSynchronization(backupNode);
locator = ActiveMQClient.createServerLocatorWithHA(liveConnector).setReconnectAttempts(15);
sessionFactory = locator.createSessionFactory();
}
public void stop() throws Exception {
sessionFactory.close();
locator.close();
liveNode.stop();
backupNode.stop();
}
public void createQueue(String queueName) throws Exception {
liveNode.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));
}
public ConnectionFactoryFactory getConnectionFactoryFactory() {
ConnectionFactoryFactory cff = new ConnectionFactoryFactory() {
@Override
public ConnectionFactory createConnectionFactory() throws Exception {
ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.XA_CF, liveConnector);
cf.getServerLocator().setReconnectAttempts(15);
return cf;
}
};
return cff;
}
public DestinationFactory getDestinationFactory(final String queueName) {
DestinationFactory destFactory = new DestinationFactory() {
@Override
public Destination createDestination() throws Exception {
return ActiveMQDestination.createDestination(queueName, ActiveMQDestination.TYPE.QUEUE);
}
};
return destFactory;
}
public void sendMessages(String queueName, int num) throws ActiveMQException {
ClientSession session = sessionFactory.createSession();
ClientProducer producer = session.createProducer(queueName);
for (int i = 0; i < num; i++) {
ClientMessage m = session.createMessage(true);
m.putStringProperty("bridge-message", "hello " + index);
index++;
producer.send(m);
}
session.close();
}
public void receiveMessages(String queueName, int num, boolean checkDup) throws ActiveMQException {
ClientSession session = sessionFactory.createSession();
session.start();
ClientConsumer consumer = session.createConsumer(queueName);
for (int i = 0; i < num; i++) {
ClientMessage m = consumer.receive(30000);
assertNotNull("i=" + i, m);
assertNotNull(m.getStringProperty("bridge-message"));
m.acknowledge();
}
ClientMessage m = consumer.receive(500);
if (checkDup) {
assertNull(m);
} else {
//drain messages
while (m != null) {
m = consumer.receive(200);
}
}
session.close();
}
public void crashLive() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
sessionFactory.addFailoverListener(new FailoverEventListener() {
@Override
public void failoverEvent(FailoverEventType eventType) {
if (eventType == FailoverEventType.FAILOVER_COMPLETED) {
latch.countDown();
}
}
});
liveNode.stop();
boolean ok = latch.await(10000, TimeUnit.MILLISECONDS);
assertTrue(ok);
}
}
}

View File

@ -1,168 +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.activemq.artemis.tests.extras.jms.bridge;
import com.arjuna.ats.arjuna.common.Uid;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
public class FailingTransactionManager implements TransactionManager {
private final TransactionManager tm;
private int calls;
private final int limit;
private final AtomicInteger failures = new AtomicInteger(0);
private final Map<Uid, FailingTransaction> transactions = Collections.synchronizedMap(new HashMap<>(10));
public FailingTransactionManager(TransactionManager tm, int limit) {
this.tm = tm;
this.calls = 0;
this.limit = limit;
}
@Override
public void begin() throws NotSupportedException, SystemException {
tm.begin();
}
@Override
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
transactions.remove(((com.arjuna.ats.jta.transaction.Transaction) tm.getTransaction()).get_uid()).commit();
}
@Override
public void rollback() throws IllegalStateException, SecurityException, SystemException {
transactions.remove(((com.arjuna.ats.jta.transaction.Transaction) tm.getTransaction()).get_uid()).rollback();
}
@Override
public void setRollbackOnly() throws IllegalStateException, SystemException {
tm.setRollbackOnly();
}
@Override
public int getStatus() throws SystemException {
return tm.getStatus();
}
@Override
public Transaction getTransaction() throws SystemException {
com.arjuna.ats.jta.transaction.Transaction real = (com.arjuna.ats.jta.transaction.Transaction) tm.getTransaction();
if (transactions.containsKey(real.get_uid())) {
return transactions.get(real.get_uid());
}
FailingTransaction tx = new FailingTransaction(real, calls++);
transactions.put(real.get_uid(), tx);
return tx;
}
@Override
public void setTransactionTimeout(int i) throws SystemException {
tm.setTransactionTimeout(i);
}
@Override
public Transaction suspend() throws SystemException {
Transaction real = tm.suspend();
if (real == null) {
return null;
}
return transactions.get(((com.arjuna.ats.jta.transaction.Transaction) real).get_uid());
}
public int getFailures() {
return failures.get();
}
@Override
public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException, SystemException {
tm.resume(((FailingTransaction)transaction).transaction);
}
private final class FailingTransaction implements Transaction {
private final com.arjuna.ats.jta.transaction.Transaction transaction;
private final int number;
private FailingTransaction(com.arjuna.ats.jta.transaction.Transaction transaction, int number) {
this.transaction = transaction;
this.number = number;
}
@Override
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
if (number < limit) {
transaction.commit();
transactions.remove(transaction.get_uid());
} else {
int fails = failures.incrementAndGet();
RollbackException ex = new RollbackException("Expected rollback for test");
throw ex;
}
}
@Override
public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException {
return transaction.delistResource(arg0, arg1);
}
@Override
public boolean enlistResource(XAResource arg0) throws RollbackException, IllegalStateException, SystemException {
return transaction.enlistResource(arg0);
}
@Override
public int getStatus() throws SystemException {
return transaction.getStatus();
}
@Override
public void registerSynchronization(Synchronization arg0) throws RollbackException, IllegalStateException, SystemException {
transaction.registerSynchronization(arg0);
}
@Override
public void rollback() throws IllegalStateException, SystemException {
transaction.rollback();
transactions.remove(transaction.get_uid());
}
@Override
public void setRollbackOnly() throws IllegalStateException, SystemException {
transaction.setRollbackOnly();
}
@Override
public String toString() {
return "FailingTransaction{" + "transaction=" + transaction.get_uid() + ", number=" + number + '}';
}
}
}

View File

@ -1,222 +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.activemq.artemis.tests.extras.jms.bridge;
import javax.transaction.TransactionManager;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory;
import org.apache.activemq.artemis.jms.bridge.DestinationFactory;
import org.apache.activemq.artemis.jms.bridge.QualityOfServiceMode;
import org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl;
import org.jboss.logging.Logger;
import org.junit.Before;
import org.junit.Test;
/**
* A JMSBridgeClusteredTest
* <br>
* Tests of jms bridge using HA connection factories.
*/
public class JMSBridgeClusteredTest extends ClusteredBridgeTestBase {
private static final Logger log = Logger.getLogger(JMSBridgeClusteredTest.class);
private ServerGroup sourceServer;
private ServerGroup targetServer;
private String sourceQueueName = "SourceQueue";
private String targetQueueName = "TargetQueue";
@Override
@Before
public void setUp() throws Exception {
super.setUp();
sourceServer = createServerGroup("source-server");
targetServer = createServerGroup("target-server");
sourceServer.start();
targetServer.start();
sourceServer.createQueue(sourceQueueName);
targetServer.createQueue(targetQueueName);
}
@Test
public void testBridgeOnFailoverXA() throws Exception {
performSourceAndTargetCrashAndFailover(QualityOfServiceMode.ONCE_AND_ONLY_ONCE);
}
@Test
public void testBridgeOnFailoverDupsOk() throws Exception {
performSourceAndTargetCrashAndFailover(QualityOfServiceMode.DUPLICATES_OK);
}
@Test
public void testBridgeOnFailoverAtMostOnce() throws Exception {
performSourceAndTargetCrashAndFailover(QualityOfServiceMode.AT_MOST_ONCE);
}
@Test
public void testCrashAndFailoverWithMessagesXA() throws Exception {
performSourceAndTargetCrashAndFailoverWithMessages(QualityOfServiceMode.ONCE_AND_ONLY_ONCE);
}
//test messages are correctly bridged when failover happens during a batch send.
//first send some messages, make sure bridge doesn't send it (below batch size)
//then crash the live
//then send more messages
//then receive those messages, no more, no less.
//this test are valid for ONCE_AND_ONLY_ONCE and AT_MOST_ONCE.
//with DUPS_OK the test failed because some messages are delivered again
//after failover, which is fine as in this mode duplication is allowed.
public void performSourceAndTargetCrashAndFailoverWithMessages(QualityOfServiceMode mode) throws Exception {
JMSBridgeImpl bridge = null;
TransactionManager txMgr = null;
try {
ConnectionFactoryFactory sourceCFF = sourceServer.getConnectionFactoryFactory();
ConnectionFactoryFactory targetCFF = targetServer.getConnectionFactoryFactory();
DestinationFactory sourceQueueFactory = sourceServer.getDestinationFactory(sourceQueueName);
DestinationFactory targetQueueFactory = targetServer.getDestinationFactory(targetQueueName);
//even number
final int batchSize = 4;
bridge = new JMSBridgeImpl(sourceCFF, targetCFF, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, mode, batchSize, -1, null, null, false).setBridgeName("test-bridge");
txMgr = newTransactionManager();
bridge.setTransactionManager(txMgr);
//start the bridge
bridge.start();
log.debug("started bridge");
final int NUM_MESSAGES = batchSize / 2;
//send some messages to source
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
//receive from target, no message should be received.
receiveMessages(targetServer, targetQueueName, 0);
//now crash target server
targetServer.crashLive();
//send more
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
receiveMessages(targetServer, targetQueueName, batchSize);
//send some again
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
//check no messages arrived.
receiveMessages(targetServer, targetQueueName, 0);
//now crash source server
sourceServer.crashLive();
//verify bridge still work
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
receiveMessages(targetServer, targetQueueName, batchSize);
} finally {
if (bridge != null) {
bridge.stop();
}
}
}
/*
* Deploy a bridge, source and target queues are in
* separate live/backup pairs. Source and Target CF are ha.
* Test the bridge work when the live servers crash.
*/
private void performSourceAndTargetCrashAndFailover(QualityOfServiceMode mode) throws Exception {
JMSBridgeImpl bridge = null;
TransactionManager txMgr = null;
try {
ConnectionFactoryFactory sourceCFF = sourceServer.getConnectionFactoryFactory();
ConnectionFactoryFactory targetCFF = targetServer.getConnectionFactoryFactory();
DestinationFactory sourceQueueFactory = sourceServer.getDestinationFactory(sourceQueueName);
DestinationFactory targetQueueFactory = targetServer.getDestinationFactory(targetQueueName);
bridge = new JMSBridgeImpl(sourceCFF, targetCFF, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, mode, 10, 1000, null, null, false).setBridgeName("test-bridge");
txMgr = newTransactionManager();
bridge.setTransactionManager(txMgr);
//start the bridge
bridge.start();
final int NUM_MESSAGES = 10;
//send some messages to source
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
//receive from target
receiveMessages(targetServer, targetQueueName, NUM_MESSAGES);
//now crash target server
targetServer.crashLive();
//verify bridge still works
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
receiveMessages(targetServer, targetQueueName, NUM_MESSAGES);
//now crash source server
sourceServer.crashLive();
//verify bridge still work
sendMessages(sourceServer, sourceQueueName, NUM_MESSAGES);
receiveMessages(targetServer, targetQueueName, NUM_MESSAGES, mode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE);
} finally {
if (bridge != null) {
bridge.stop();
}
}
}
private void sendMessages(ServerGroup server, String queueName, int num) throws ActiveMQException {
server.sendMessages(queueName, num);
}
private void receiveMessages(ServerGroup server,
String queueName,
int num,
boolean checkDup) throws ActiveMQException {
try {
server.receiveMessages(queueName, num, checkDup);
} catch (ActiveMQException e) {
e.printStackTrace();
throw e;
}
}
private void receiveMessages(ServerGroup server, String queueName, int num) throws ActiveMQException {
try {
server.receiveMessages(queueName, num, false);
} catch (ActiveMQException e) {
e.printStackTrace();
throw e;
}
}
protected TransactionManager newTransactionManager() {
return new TransactionManagerImple();
}
}

View File

@ -1,413 +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.activemq.artemis.tests.extras.jms.bridge;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.xa.XAResource;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.jms.bridge.ConnectionFactoryFactory;
import org.apache.activemq.artemis.jms.bridge.QualityOfServiceMode;
import org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory;
import org.apache.activemq.artemis.tests.integration.ra.DummyTransactionManager;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Test;
public class JMSBridgeReconnectionTest extends BridgeTestBase {
private static final Logger log = Logger.getLogger(JMSBridgeReconnectionTest.class);
private static final int TIME_WAIT = 5000;
// Crash and reconnect
// Once and only once
@Test
public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_P() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, false);
}
@Test
public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_P_LargeMessage() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, true);
}
@Test
public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_NP() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, false);
}
// dups ok
@Test
public void testCrashAndReconnectDestBasic_DuplicatesOk_P() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.DUPLICATES_OK, true, false);
}
@Test
public void testCrashAndReconnectDestBasic_DuplicatesOk_NP() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.DUPLICATES_OK, false, false);
}
// At most once
@Test
public void testCrashAndReconnectDestBasic_AtMostOnce_P() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.AT_MOST_ONCE, true, false);
}
@Test
public void testCrashAndReconnectDestBasic_AtMostOnce_NP() throws Exception {
performCrashAndReconnectDestBasic(QualityOfServiceMode.AT_MOST_ONCE, false, false);
}
// Crash tests specific to XA transactions
@Test
public void testCrashAndReconnectDestCrashBeforePrepare_P() throws Exception {
performCrashAndReconnectDestCrashBeforePrepare(true);
}
@Test
public void testCrashAndReconnectDestCrashBeforePrepare_NP() throws Exception {
performCrashAndReconnectDestCrashBeforePrepare(false);
}
// Crash before bridge is started
@Test
public void testRetryConnectionOnStartup() throws Exception {
server1.stop();
JMSBridgeImpl bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, QualityOfServiceMode.DUPLICATES_OK, 10, -1, null, null, false).setBridgeName("test-bridge");
bridge.setTransactionManager(newTransactionManager());
addActiveMQComponent(bridge);
bridge.start();
Assert.assertFalse(bridge.isStarted());
Assert.assertTrue(bridge.isFailed());
// Restart the server
server1.start();
createQueue("targetQueue", 1);
setUpAdministeredObjects();
Thread.sleep(3000);
Assert.assertTrue(bridge.isStarted());
Assert.assertFalse(bridge.isFailed());
}
/**
* https://jira.jboss.org/jira/browse/HORNETQ-287
*/
@Test
public void testStopBridgeWithFailureWhenStarted() throws Exception {
server1.stop();
JMSBridgeImpl bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 500, -1, QualityOfServiceMode.DUPLICATES_OK, 10, -1, null, null, false).setBridgeName("test-bridge");
bridge.setTransactionManager(newTransactionManager());
bridge.start();
Assert.assertFalse(bridge.isStarted());
Assert.assertTrue(bridge.isFailed());
bridge.stop();
Assert.assertFalse(bridge.isStarted());
// we restart and setup the server for the test's tearDown checks
server1.start();
createQueue("targetQueue", 1);
setUpAdministeredObjects();
}
/*
* Send some messages
* Crash the destination server
* Bring the destination server back up
* Send some more messages
* Verify all messages are received
*/
private void performCrashAndReconnectDestBasic(final QualityOfServiceMode qosMode,
final boolean persistent,
final boolean largeMessage) throws Exception {
JMSBridgeImpl bridge = null;
ConnectionFactoryFactory factInUse0 = cff0;
ConnectionFactoryFactory factInUse1 = cff1;
if (qosMode.equals(QualityOfServiceMode.ONCE_AND_ONLY_ONCE)) {
factInUse0 = cff0xa;
factInUse1 = cff1xa;
}
bridge = new JMSBridgeImpl(factInUse0, factInUse1, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, qosMode, 10, -1, null, null, false).setBridgeName("test-bridge");
addActiveMQComponent(bridge);
bridge.setTransactionManager(newTransactionManager());
bridge.start();
final int NUM_MESSAGES = 10;
// Send some messages
sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent, largeMessage);
// Verify none are received
checkEmpty(targetQueue, 1);
// Now crash the dest server
instanceLog.debug("About to crash server");
server1.stop();
// Wait a while before starting up to simulate the dest being down for a while
instanceLog.debug("Waiting 5 secs before bringing server back up");
Thread.sleep(TIME_WAIT);
instanceLog.debug("Done wait");
// Restart the server
instanceLog.debug("Restarting server");
server1.start();
// jmsServer1.createQueue(false, "targetQueue", null, true, "queue/targetQueue");
createQueue("targetQueue", 1);
setUpAdministeredObjects();
// Send some more messages
instanceLog.debug("Sending more messages");
sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent, largeMessage);
instanceLog.debug("Sent messages");
server1.stop();
bridge.stop();
log.debug("JMSBridgeReconnectionTest.performCrashAndReconnectDestBasic");
}
@Test
public void performCrashDestinationStopBridge() throws Exception {
ConnectionFactoryFactory factInUse0 = cff0;
ConnectionFactoryFactory factInUse1 = cff1;
final JMSBridgeImpl bridge = new JMSBridgeImpl(factInUse0, factInUse1, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, QualityOfServiceMode.DUPLICATES_OK, 10, -1, null, null, false).setBridgeName("test-bridge");
addActiveMQComponent(bridge);
bridge.setTransactionManager(newTransactionManager());
bridge.start();
Thread clientThread = new Thread(new Runnable() {
@Override
public void run() {
while (bridge.isStarted()) {
try {
sendMessages(cf0, sourceQueue, 0, 1, false, false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
clientThread.start();
checkAllMessageReceivedInOrder(cf1, targetQueue, 0, 1, false);
instanceLog.debug("About to crash server");
server1.stop();
// Wait a while before starting up to simulate the dest being down for a while
instanceLog.debug("Waiting 5 secs before bringing server back up");
Thread.sleep(TIME_WAIT);
instanceLog.debug("Done wait");
bridge.stop();
clientThread.join(5000);
assertTrue(!clientThread.isAlive());
}
@Test
public void performCrashAndReconnect() throws Exception {
performCrashAndReconnect(true);
}
@Test
public void performCrashAndNoReconnect() throws Exception {
performCrashAndReconnect(false);
}
private void performCrashAndReconnect(boolean restart) throws Exception {
cff1xa = new ConnectionFactoryFactory() {
@Override
public Object createConnectionFactory() throws Exception {
ActiveMQXAConnectionFactory cf = (ActiveMQXAConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.XA_CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY, params1));
// Note! We disable automatic reconnection on the session factory. The bridge needs to do the reconnection
cf.setReconnectAttempts(-1);
cf.setBlockOnNonDurableSend(true);
cf.setBlockOnDurableSend(true);
cf.setCacheLargeMessagesClient(true);
return cf;
}
};
DummyTransactionManager tm = new DummyTransactionManager();
DummyTransaction tx = new DummyTransaction();
tm.tx = tx;
JMSBridgeImpl bridge = new JMSBridgeImpl(cff0xa, cff1xa, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, QualityOfServiceMode.ONCE_AND_ONLY_ONCE, 10, 5000, null, null, false).setBridgeName("test-bridge");
addActiveMQComponent(bridge);
bridge.setTransactionManager(tm);
bridge.start();
// Now crash the dest server
instanceLog.debug("About to crash server");
server1.stop();
if (restart) {
server1.start();
}
// Wait a while before starting up to simulate the dest being down for a while
instanceLog.debug("Waiting 5 secs before bringing server back up");
Thread.sleep(TIME_WAIT);
instanceLog.debug("Done wait");
bridge.stop();
if (restart) {
assertTrue(tx.rolledback);
assertTrue(tx.targetConnected);
} else {
assertTrue(tx.rolledback);
assertFalse(tx.targetConnected);
}
}
private class DummyTransaction implements Transaction {
boolean rolledback = false;
ClientSession targetSession;
boolean targetConnected = false;
@Override
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, SystemException {
}
@Override
public void rollback() throws IllegalStateException, SystemException {
rolledback = true;
targetConnected = !targetSession.isClosed();
}
@Override
public void setRollbackOnly() throws IllegalStateException, SystemException {
}
@Override
public int getStatus() throws SystemException {
return 0;
}
@Override
public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException {
targetSession = (ClientSession) xaResource;
return false;
}
@Override
public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException {
return false;
}
@Override
public void registerSynchronization(Synchronization synchronization) throws RollbackException, IllegalStateException, SystemException {
}
}
/*
* Send some messages
* Crash the destination server
* Set the max batch time such that it will attempt to send the batch while the dest server is down
* Bring up the destination server
* Send some more messages
* Verify all messages are received
*/
private void performCrashAndReconnectDestCrashBeforePrepare(final boolean persistent) throws Exception {
JMSBridgeImpl bridge = new JMSBridgeImpl(cff0xa, cff1xa, sourceQueueFactory, targetQueueFactory, null, null, null, null, null, 1000, -1, QualityOfServiceMode.ONCE_AND_ONLY_ONCE, 10, 5000, null, null, false).setBridgeName("test-bridge");
addActiveMQComponent(bridge);
bridge.setTransactionManager(newTransactionManager());
bridge.start();
final int NUM_MESSAGES = 10;
// Send some messages
sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent, false);
// verify none are received
checkEmpty(targetQueue, 1);
// Now crash the dest server
instanceLog.debug("About to crash server");
server1.stop();
// Wait a while before starting up to simulate the dest being down for a while
instanceLog.debug("Waiting 5 secs before bringing server back up");
Thread.sleep(TIME_WAIT);
instanceLog.debug("Done wait");
// Restart the server
server1.start();
createQueue("targetQueue", 1);
setUpAdministeredObjects();
sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent, false);
checkMessagesReceived(cf1, targetQueue, QualityOfServiceMode.ONCE_AND_ONLY_ONCE, NUM_MESSAGES, false, false);
}
}

View File

@ -1,36 +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.activemq.artemis.tests.extras.jms.bridge;
import javax.transaction.TransactionManager;
import org.apache.activemq.artemis.service.extensions.transactions.TransactionManagerLocator;
public class TransactionManagerLocatorImpl implements TransactionManagerLocator {
private static TransactionManager tm = null;
@Override
public TransactionManager getTransactionManager() {
return tm;
}
public static void setTransactionManager(TransactionManager transactionManager) {
tm = transactionManager;
}
}

View File

@ -1,544 +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.activemq.artemis.tests.extras.jms.ra;
import javax.jms.Message;
import javax.resource.ResourceException;
import javax.resource.spi.LocalTransactionException;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.ra.ActiveMQResourceAdapter;
import org.apache.activemq.artemis.ra.inflow.ActiveMQActivation;
import org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.integration.ra.ActiveMQRATestBase;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Simulates several messages being received over multiple instances with reconnects during the process.
*/
public class MDBMultipleHandlersServerDisconnectTest extends ActiveMQRATestBase {
private static final Logger log = Logger.getLogger(MDBMultipleHandlersServerDisconnectTest.class);
final ConcurrentHashMap<Integer, AtomicInteger> mapCounter = new ConcurrentHashMap<>();
volatile ActiveMQResourceAdapter resourceAdapter;
ServerLocator nettyLocator;
// This thread will keep bugging the handlers.
// if they behave well with XA, the test pass!
final AtomicBoolean running = new AtomicBoolean(true);
private volatile boolean playTXTimeouts = true;
private volatile boolean playServerClosingSession = true;
private volatile boolean playServerClosingConsumer = true;
@Override
@Before
public void setUp() throws Exception {
nettyLocator = createNettyNonHALocator();
nettyLocator.setRetryInterval(100);
nettyLocator.setReconnectAttempts(300);
mapCounter.clear();
resourceAdapter = null;
super.setUp();
createQueue(true, "outQueue");
DummyTMLocator.startTM();
running.set(true);
}
@Override
@After
public void tearDown() throws Exception {
DummyTMLocator.stopTM();
super.tearDown();
}
@Override
protected boolean usePersistence() {
return true;
}
@Override
public boolean useSecurity() {
return false;
}
@Test
public void testReconnectMDBNoMessageLoss() throws Exception {
AddressSettings settings = new AddressSettings();
settings.setRedeliveryDelay(100);
settings.setMaxDeliveryAttempts(-1);
server.getAddressSettingsRepository().clear();
server.getAddressSettingsRepository().addMatch("#", settings);
ActiveMQResourceAdapter qResourceAdapter = newResourceAdapter();
resourceAdapter = qResourceAdapter;
resourceAdapter.setConfirmationWindowSize(-1);
resourceAdapter.setCallTimeout(1000L);
resourceAdapter.setConsumerWindowSize(1024 * 1024);
resourceAdapter.setReconnectAttempts(-1);
resourceAdapter.setRetryInterval(100L);
// qResourceAdapter.setTransactionManagerLocatorClass(DummyTMLocator.class.getName());
// qResourceAdapter.setTransactionManagerLocatorMethod("getTM");
MyBootstrapContext ctx = new MyBootstrapContext();
qResourceAdapter.setConnectorClassName(NETTY_CONNECTOR_FACTORY);
qResourceAdapter.start(ctx);
final int NUMBER_OF_SESSIONS = 10;
ActiveMQActivationSpec spec = new ActiveMQActivationSpec();
spec.setTransactionTimeout(1);
spec.setMaxSession(NUMBER_OF_SESSIONS);
spec.setSetupAttempts(-1);
spec.setSetupInterval(100L);
spec.setResourceAdapter(qResourceAdapter);
spec.setUseJNDI(false);
spec.setDestinationType("javax.jms.Queue");
spec.setDestination(MDBQUEUE);
// Some the routines would be screwed up if using the default one
Assert.assertFalse(spec.isHasBeenUpdated());
TestEndpointFactory endpointFactory = new TestEndpointFactory(true);
qResourceAdapter.endpointActivation(endpointFactory, spec);
Assert.assertEquals(1, resourceAdapter.getActivations().values().size());
ActiveMQActivation activation = resourceAdapter.getActivations().values().toArray(new ActiveMQActivation[1])[0];
final int NUMBER_OF_MESSAGES = 1000;
Thread producer = new Thread() {
@Override
public void run() {
try {
ServerLocator locator = createInVMLocator(0);
ClientSessionFactory factory = locator.createSessionFactory();
ClientSession session = factory.createSession(false, false);
ClientProducer clientProducer = session.createProducer(MDBQUEUEPREFIXED);
StringBuffer buffer = new StringBuffer();
for (int b = 0; b < 500; b++) {
buffer.append("ab");
}
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString(buffer.toString() + i);
message.putIntProperty("i", i);
clientProducer.send(message);
if (i % 100 == 0) {
session.commit();
}
}
session.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
};
producer.start();
final AtomicBoolean metaDataFailed = new AtomicBoolean(false);
Thread buggerThread = new Thread() {
@Override
public void run() {
while (running.get()) {
try {
Thread.sleep(RandomUtil.randomInterval(100, 200));
} catch (InterruptedException intex) {
intex.printStackTrace();
return;
}
List<ServerSession> serverSessions = lookupServerSessions("resource-adapter", NUMBER_OF_SESSIONS);
System.err.println("Contains " + serverSessions.size() + " RA sessions");
if (serverSessions.size() != NUMBER_OF_SESSIONS) {
System.err.println("the server was supposed to have " + NUMBER_OF_MESSAGES + " RA Sessions but it only contained accordingly to the meta-data");
metaDataFailed.set(true);
} else if (serverSessions.size() == NUMBER_OF_SESSIONS) {
// it became the same after some reconnect? which would be acceptable
metaDataFailed.set(false);
}
if (playServerClosingSession && serverSessions.size() > 0) {
int randomBother = RandomUtil.randomInterval(0, serverSessions.size() - 1);
log.debug("bugging session " + randomBother);
ServerSession serverSession = serverSessions.get(randomBother);
if (playServerClosingConsumer && RandomUtil.randomBoolean()) {
// will play this randomly, only half of the times
for (ServerConsumer consumer : serverSession.getServerConsumers()) {
try {
// Simulating a rare race that could happen in production
// where the consumer is closed while things are still happening
consumer.close(true);
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
RemotingConnection connection = serverSession.getRemotingConnection();
connection.fail(new ActiveMQException("failed at random " + randomBother));
}
}
}
};
buggerThread.start();
ServerLocator locator = createInVMLocator(0);
ClientSessionFactory factory = locator.createSessionFactory();
ClientSession session = factory.createSession(false, false);
session.start();
ClientConsumer consumer = session.createConsumer("outQueue");
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
ClientMessage message = consumer.receive(60000);
if (message == null) {
break;
}
if (i == NUMBER_OF_MESSAGES * 0.50) {
// This is to make sure the MDBs will survive a reboot
// and no duplications or message loss will happen because of this
System.err.println("Rebooting the MDBs at least once!");
activation.startReconnectThread("I");
}
if (i == NUMBER_OF_MESSAGES * 0.90) {
log.debug("Disabled failures at " + i);
playTXTimeouts = false;
playServerClosingSession = false;
playServerClosingConsumer = false;
}
log.debug("Received " + i + " messages");
doReceiveMessage(message);
if (i % 200 == 0) {
log.debug("received " + i);
session.commit();
}
}
session.commit();
while (true) {
ClientMessage message = consumer.receiveImmediate();
if (message == null) {
break;
}
log.debug("Received extra message " + message);
doReceiveMessage(message);
}
session.commit();
Assert.assertNull(consumer.receiveImmediate());
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
boolean failed = false;
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
AtomicInteger atomicInteger = mapCounter.get(Integer.valueOf(i));
if (atomicInteger == null) {
out.println("didn't receive message with i=" + i);
failed = true;
} else if (atomicInteger.get() > 1) {
out.println("message with i=" + i + " received " + atomicInteger.get() + " times");
failed = true;
}
}
running.set(false);
buggerThread.join();
producer.join();
qResourceAdapter.stop();
session.close();
if (failed) {
log.debug(writer.toString());
}
Assert.assertFalse(writer.toString(), failed);
log.debug("Received " + NUMBER_OF_MESSAGES + " messages");
Assert.assertFalse("There was meta-data failures, some sessions didn't reconnect properly", metaDataFailed.get());
}
private void doReceiveMessage(ClientMessage message) throws Exception {
Assert.assertNotNull(message);
message.acknowledge();
Integer value = message.getIntProperty("i");
AtomicInteger mapCount = new AtomicInteger(1);
mapCount = mapCounter.putIfAbsent(value, mapCount);
if (mapCount != null) {
mapCount.incrementAndGet();
}
}
private List<ServerSession> lookupServerSessions(String parameter, int numberOfSessions) {
long timeout = System.currentTimeMillis() + 50000;
List<ServerSession> serverSessions = new LinkedList<>();
do {
if (!serverSessions.isEmpty()) {
System.err.println("Retry on serverSessions!!! currently with " + serverSessions.size());
serverSessions.clear();
try {
Thread.sleep(100);
} catch (Exception e) {
break;
}
}
serverSessions.clear();
for (ServerSession session : server.getSessions()) {
if (session.getMetaData(parameter) != null) {
serverSessions.add(session);
}
}
}
while (running.get() && serverSessions.size() != numberOfSessions && timeout > System.currentTimeMillis());
System.err.println("Returning " + serverSessions.size() + " sessions");
return serverSessions;
}
protected class TestEndpointFactory implements MessageEndpointFactory {
private final boolean isDeliveryTransacted;
public TestEndpointFactory(boolean deliveryTransacted) {
isDeliveryTransacted = deliveryTransacted;
}
@Override
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
TestEndpoint retEnd = new TestEndpoint();
if (xaResource != null) {
retEnd.setXAResource(xaResource);
}
return retEnd;
}
@Override
public MessageEndpoint createEndpoint(XAResource xaResource, long l) throws UnavailableException {
return null;
}
@Override
public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException {
return isDeliveryTransacted;
}
@Override
public String getActivationName() {
return null;
}
@Override
public Class<?> getEndpointClass() {
return TestEndpoint.class;
}
}
public class TestEndpoint extends DummyMessageEndpoint {
ClientSessionFactory factory;
ClientSession endpointSession;
ClientProducer producer;
Transaction currentTX;
public TestEndpoint() {
super(null);
try {
factory = nettyLocator.createSessionFactory();
// buggingList.add(factory);
endpointSession = factory.createSession(true, false, false);
producer = endpointSession.createProducer("outQueue");
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
super.beforeDelivery(method);
try {
DummyTMLocator.tm.begin();
currentTX = DummyTMLocator.tm.getTransaction();
currentTX.enlistResource(xaResource);
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public void onMessage(Message message) {
Integer value = 0;
try {
value = message.getIntProperty("i");
} catch (Exception e) {
}
super.onMessage(message);
try {
currentTX.enlistResource(endpointSession);
ClientMessage message1 = endpointSession.createMessage(true);
message1.putIntProperty("i", value);
producer.send(message1);
currentTX.delistResource(endpointSession, XAResource.TMSUCCESS);
if (playTXTimeouts) {
if (RandomUtil.randomInterval(0, 5) == 3) {
Thread.sleep(2000);
}
}
} catch (Exception e) {
e.printStackTrace();
try {
currentTX.setRollbackOnly();
} catch (Exception ex) {
}
e.printStackTrace();
// throw new RuntimeException(e);
}
}
@Override
public void afterDelivery() throws ResourceException {
// This is a copy & paste of what the Application server would do here
try {
if (currentTX.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
DummyTMLocator.tm.rollback();
} else {
DummyTMLocator.tm.commit();
}
} catch (HeuristicMixedException e) {
throw new LocalTransactionException(e);
} catch (SystemException e) {
throw new LocalTransactionException(e);
} catch (HeuristicRollbackException e) {
throw new LocalTransactionException(e);
} catch (RollbackException e) {
throw new LocalTransactionException(e);
}
super.afterDelivery();
}
}
public static class DummyTMLocator {
public static TransactionManagerImple tm;
public static void stopTM() {
try {
TransactionReaper.terminate(true);
TxControl.disable(true);
} catch (Exception e) {
e.printStackTrace();
}
tm = null;
}
public static void startTM() {
tm = new TransactionManagerImple();
TxControl.enable();
}
public TransactionManager getTM() {
return tm;
}
}
}

View File

@ -1,734 +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.activemq.artemis.tests.extras.jms.xa;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
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 javax.jms.Topic;
import javax.jms.XAConnection;
import javax.jms.XAConnectionFactory;
import javax.jms.XASession;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* A JMSXDeliveryCountTest
*/
public class JMSXDeliveryCountTest extends JMSTestBase {
Queue queue1;
Topic topic1;
protected XAConnectionFactory xacf;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
xacf = ActiveMQJMSClient.createConnectionFactory("tcp://localhost:61616", "test");
queue1 = createQueue("queue1");
topic1 = createTopic("topic1");
TxControl.enable();
}
@Override
@After
public void tearDown() throws Exception {
TxControl.disable(true);
TransactionReaper.terminate(false);
super.tearDown();
}
@Test
public void testSimpleJMSXDeliveryCount() throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = s.createProducer(queue1);
p.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
p.send(s.createTextMessage("xoxo"));
s.close();
s = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer c = s.createConsumer(queue1);
conn.start();
TextMessage tm = (TextMessage) c.receive(1000);
Assert.assertEquals("xoxo", tm.getText());
Assert.assertTrue("JMSXDeliveryCount is supposed to exist as a property", tm.propertyExists("JMSXDeliveryCount"));
Assert.assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
s.recover();
tm = (TextMessage) c.receive(1000);
Assert.assertEquals("xoxo", tm.getText());
Assert.assertTrue("JMSXDeliveryCount is supposed to exist as a property", tm.propertyExists("JMSXDeliveryCount"));
Assert.assertEquals(2, tm.getIntProperty("JMSXDeliveryCount"));
tm.acknowledge();
conn.close();
} finally {
if (conn != null) {
conn.close();
}
}
}
@Test
public void testJMSXDeliveryCountNotDeliveredMessagesNotUpdated() throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
Session s = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageProducer p = s.createProducer(queue1);
p.send(s.createTextMessage("message1"));
p.send(s.createTextMessage("message2"));
p.send(s.createTextMessage("message3"));
p.send(s.createTextMessage("message4"));
p.send(s.createTextMessage("message5"));
MessageConsumer c = s.createConsumer(queue1);
conn.start();
TextMessage tm = (TextMessage) c.receive(1000);
Assert.assertEquals("message1", tm.getText());
Assert.assertFalse(tm.getJMSRedelivered());
Assert.assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
s.close();
s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
c = s.createConsumer(queue1);
tm = (TextMessage) c.receive(1000);
Assert.assertEquals("message1", tm.getText());
Assert.assertTrue(tm.getJMSRedelivered());
Assert.assertEquals(2, tm.getIntProperty("JMSXDeliveryCount"));
tm = (TextMessage) c.receive(1000);
Assert.assertEquals("message2", tm.getText());
Assert.assertFalse(tm.getJMSRedelivered());
Assert.assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
tm = (TextMessage) c.receive(1000);
Assert.assertEquals("message3", tm.getText());
Assert.assertFalse(tm.getJMSRedelivered());
Assert.assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
tm = (TextMessage) c.receive(1000);
Assert.assertEquals("message4", tm.getText());
Assert.assertFalse(tm.getJMSRedelivered());
Assert.assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
tm = (TextMessage) c.receive(1000);
Assert.assertEquals("message5", tm.getText());
Assert.assertFalse(tm.getJMSRedelivered());
Assert.assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
tm.acknowledge();
} finally {
if (conn != null) {
conn.close();
}
}
}
@Test
public void testRedeliveryOnQueue() throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
Session sess1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sess1.createProducer(queue1);
prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
final int NUM_MESSAGES = 100;
final int NUM_RECOVERIES = 8;
for (int i = 0; i < NUM_MESSAGES; i++) {
TextMessage tm = sess1.createTextMessage();
tm.setText("testing" + i);
prod.send(tm);
}
Session sess2 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer cons = sess2.createConsumer(queue1);
conn.start();
TextMessage tm = null;
for (int j = 0; j < NUM_RECOVERIES; j++) {
for (int i = 0; i < NUM_MESSAGES; i++) {
tm = (TextMessage) cons.receive(3000);
Assert.assertNotNull(tm);
Assert.assertEquals("testing" + i, tm.getText());
Assert.assertTrue("JMSXDeliveryCount is supposed to exist as a property", tm.propertyExists("JMSXDeliveryCount"));
Assert.assertEquals(j + 1, tm.getIntProperty("JMSXDeliveryCount"));
}
if (j != NUM_RECOVERIES - 1) {
sess2.recover();
}
}
tm.acknowledge();
} finally {
if (conn != null) {
conn.close();
}
}
}
@Test
public void testRedeliveryOnTopic() throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
conn.setClientID("myclientid");
Session sess1 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Session sess2 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Session sess3 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer cons1 = sess1.createConsumer(topic1);
MessageConsumer cons2 = sess2.createConsumer(topic1);
MessageConsumer cons3 = sess3.createDurableSubscriber(topic1, "subxyz");
conn.start();
final int NUM_MESSAGES = 100;
final int NUM_RECOVERIES = 9;
Receiver r1 = new Receiver("R1", sess1, cons1, NUM_MESSAGES, NUM_RECOVERIES);
Receiver r2 = new Receiver("R2", sess2, cons2, NUM_MESSAGES, NUM_RECOVERIES);
Receiver r3 = new Receiver("R3", sess3, cons3, NUM_MESSAGES, NUM_RECOVERIES);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
t3.start();
Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sessSend.createProducer(topic1);
prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
for (int i = 0; i < NUM_MESSAGES; i++) {
TextMessage tm1 = sessSend.createTextMessage("testing" + i);
prod.send(tm1);
}
t1.join();
t2.join();
t3.join();
Assert.assertFalse(r1.failed);
Assert.assertFalse(r2.failed);
Assert.assertFalse(r3.failed);
cons3.close();
sess3.unsubscribe("subxyz");
} finally {
if (conn != null) {
conn.close();
}
}
}
@Test
public void testDeliveryCountUpdatedOnCloseTransacted() throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
Session producerSess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(true, Session.SESSION_TRANSACTED);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
TextMessage tm = producerSess.createTextMessage("message1");
producer.send(tm);
TextMessage rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertTrue("JMSXDeliveryCount is supposed to exist as a property", tm.propertyExists("JMSXDeliveryCount"));
Assert.assertEquals(1, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertFalse(rm.getJMSRedelivered());
consumerSess.rollback();
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(2, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
consumerSess.rollback();
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(3, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
// Now close the session without committing
consumerSess.close();
consumerSess = conn.createSession(true, Session.SESSION_TRANSACTED);
consumer = consumerSess.createConsumer(queue1);
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(4, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
consumerSess.commit();
} finally {
if (conn != null) {
conn.close();
}
}
}
@Test
public void testDeliveryCountUpdatedOnCloseClientAck() throws Exception {
Connection conn = null;
try {
conn = cf.createConnection();
Session producerSess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
Session consumerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer consumer = consumerSess.createConsumer(queue1);
conn.start();
TextMessage tm = producerSess.createTextMessage("message1");
producer.send(tm);
TextMessage rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(1, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertFalse(rm.getJMSRedelivered());
consumerSess.recover();
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(2, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
consumerSess.recover();
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(3, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
// Now close the session without committing
consumerSess.close();
consumerSess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
consumer = consumerSess.createConsumer(queue1);
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(4, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
rm.acknowledge();
} finally {
if (conn != null) {
conn.close();
}
}
}
@Test
public void testDeliveryCountUpdatedOnCloseXA() throws Exception {
XAConnection xaConn = null;
Connection conn = null;
TransactionManager mgr = new TransactionManagerImple();
Transaction toResume = null;
Transaction tx = null;
try {
toResume = mgr.suspend();
conn = cf.createConnection();
// Send a message
Session producerSess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = producerSess.createProducer(queue1);
TextMessage tm = producerSess.createTextMessage("message1");
producer.send(tm);
xaConn = xacf.createXAConnection();
XASession consumerSess = xaConn.createXASession();
MessageConsumer consumer = consumerSess.createConsumer(queue1);
xaConn.start();
DummyXAResource res = new DummyXAResource();
mgr.begin();
tx = mgr.getTransaction();
tx.enlistResource(res);
tx.enlistResource(consumerSess.getXAResource());
TextMessage rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(1, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertFalse(rm.getJMSRedelivered());
tx.delistResource(res, XAResource.TMSUCCESS);
tx.delistResource(consumerSess.getXAResource(), XAResource.TMSUCCESS);
mgr.rollback();
mgr.begin();
tx = mgr.getTransaction();
tx.enlistResource(res);
tx.enlistResource(consumerSess.getXAResource());
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(2, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
tx.delistResource(res, XAResource.TMSUCCESS);
tx.delistResource(consumerSess.getXAResource(), XAResource.TMSUCCESS);
mgr.rollback();
mgr.begin();
tx = mgr.getTransaction();
tx.enlistResource(res);
tx.enlistResource(consumerSess.getXAResource());
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(3, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
tx.delistResource(res, XAResource.TMSUCCESS);
tx.delistResource(consumerSess.getXAResource(), XAResource.TMSUCCESS);
mgr.rollback();
// Must close consumer first
consumer.close();
consumerSess.close();
consumerSess = xaConn.createXASession();
consumer = consumerSess.createConsumer(queue1);
mgr.begin();
tx = mgr.getTransaction();
tx.enlistResource(res);
tx.enlistResource(consumerSess.getXAResource());
rm = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(rm);
Assert.assertEquals(tm.getText(), rm.getText());
Assert.assertEquals(4, rm.getIntProperty("JMSXDeliveryCount"));
Assert.assertTrue(rm.getJMSRedelivered());
tx.delistResource(res, XAResource.TMSUCCESS);
tx.delistResource(consumerSess.getXAResource(), XAResource.TMSUCCESS);
} finally {
if (conn != null) {
conn.close();
}
if (tx != null) {
try {
mgr.commit();
} catch (Exception ignore) {
}
}
if (xaConn != null) {
xaConn.close();
}
if (toResume != null) {
try {
mgr.resume(toResume);
} catch (Exception ignore) {
}
}
}
}
class Receiver implements Runnable {
MessageConsumer cons;
int numMessages;
int numRecoveries;
boolean failed;
Session sess;
String name;
Receiver(final String name,
final Session sess,
final MessageConsumer cons,
final int numMessages,
final int numRecoveries) {
this.sess = sess;
this.cons = cons;
this.numMessages = numMessages;
this.numRecoveries = numRecoveries;
this.name = name;
}
@Override
public void run() {
try {
Message lastMessage = null;
for (int j = 0; j < numRecoveries; j++) {
for (int i = 0; i < numMessages; i++) {
TextMessage tm = (TextMessage) cons.receive();
lastMessage = tm;
if (tm == null) {
failed = true;
} else if (!tm.getText().equals("testing" + i)) {
failed = true;
} else if (tm.getIntProperty("JMSXDeliveryCount") != j + 1) {
failed = true;
}
}
if (j != numRecoveries - 1) {
sess.recover();
}
}
lastMessage.acknowledge();
} catch (Exception e) {
failed = true;
}
}
}
static class DummyXAResource implements XAResource {
DummyXAResource() {
}
@Override
public void commit(final Xid arg0, final boolean arg1) throws XAException {
}
@Override
public void end(final Xid arg0, final int arg1) throws XAException {
}
@Override
public void forget(final Xid arg0) throws XAException {
}
@Override
public int getTransactionTimeout() throws XAException {
return 0;
}
@Override
public boolean isSameRM(final XAResource arg0) throws XAException {
return false;
}
@Override
public int prepare(final Xid arg0) throws XAException {
return XAResource.XA_OK;
}
@Override
public Xid[] recover(final int arg0) throws XAException {
return null;
}
@Override
public void rollback(final Xid arg0) throws XAException {
}
@Override
public boolean setTransactionTimeout(final int arg0) throws XAException {
return false;
}
@Override
public void start(final Xid arg0, final int arg1) throws XAException {
}
}
}

View File

@ -1,120 +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.activemq.artemis.tests.extras.protocols.hornetq;
import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.core.config.CoreQueueConfiguration;
import org.apache.activemq.artemis.core.protocol.hornetq.client.HornetQClientProtocolManagerFactory;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQQueue;
import org.apache.activemq.artemis.ra.recovery.RecoveryManager;
import org.apache.activemq.artemis.service.extensions.xa.recovery.XARecoveryConfig;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* These tests attempt to mimic a legacy client without actually using a legacy versions of the client libraries.
*/
public class HornetQProtocolManagerTest extends ActiveMQTestBase {
ActiveMQServer server;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
server = createServer(createDefaultConfig(false)
.setPersistenceEnabled(false)
.clearAcceptorConfigurations()
.addAcceptorConfiguration("legacy", "tcp://localhost:61616?protocols=HORNETQ")
.addAcceptorConfiguration("corepr", "tcp://localhost:61617?protocols=CORE")
.addQueueConfiguration(new CoreQueueConfiguration()
.setName("testQueue")
.setAddress("testQueue")
.setRoutingType(RoutingType.ANYCAST)));
server.start();
}
@Test
public void testLegacy() throws Exception {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616?protocolManagerFactoryStr=" + HornetQClientProtocolManagerFactory.class.getName());
connectionFactory.createConnection().close();
ActiveMQConnectionFactory connectionFactory2 = new ActiveMQConnectionFactory("tcp://localhost:61617");
connectionFactory2.createConnection().close();
RecoveryManager manager = new RecoveryManager();
manager.register(connectionFactory, null, null, new ConcurrentHashMap<String, String>());
manager.register(connectionFactory2, null, null, new ConcurrentHashMap<String, String>());
for (XARecoveryConfig resource : manager.getResources()) {
try (ServerLocator locator = resource.createServerLocator();
ClientSessionFactory factory = locator.createSessionFactory();
ClientSession session = factory.createSession()) {
// Nothing
}
}
}
/** This test will use an ArtemisConnectionFactory with clientProtocolManager=*/
@Test
public void testLegacy2() throws Exception {
// WORKAROUND: the 2.0.0 broker introduced addressing change and the 2.2.0 broker added compatibility for old
// client libraries relying on the legacy prefixes. The new client being used in this test needs prefix explicitly.
Queue queue = new ActiveMQQueue("jms.queue.testQueue");
ActiveMQConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactory("tcp://localhost:61616?protocolManagerFactoryStr=" + HornetQClientProtocolManagerFactory.class.getName(), "legacy");
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage("Test");
for (int i = 0; i < 5; i++) {
message.setStringProperty(Message.HDR_DUPLICATE_DETECTION_ID.toString(), "duplicate");
producer.send(message);
}
connection.start();
MessageConsumer consumer = session.createConsumer(queue);
TextMessage messageRec = (TextMessage) consumer.receive(5000);
Assert.assertNotNull(messageRec);
Assert.assertEquals("Test", messageRec.getText());
Assert.assertNull(consumer.receiveNoWait());
connection.close();
connectionFactory.close();
}
}

View File

@ -1,333 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.extras.protocols.hornetq;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.hornetq.api.core.HornetQException;
import org.hornetq.api.core.client.HornetQClient;
import org.hornetq.utils.UUIDGenerator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HornetQProtocolTest extends ActiveMQTestBase {
protected ActiveMQServer server;
private static final Logger LOG = LoggerFactory.getLogger(HornetQProtocolTest.class);
@Override
@Before
public void setUp() throws Exception {
HashMap<String, Object> params = new HashMap<>();
params.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, "" + 5445);
params.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PROTOCOLS_PROP_NAME, "HORNETQ");
TransportConfiguration transportConfig = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
super.setUp();
server = createServer(true, true);
server.getConfiguration().getAcceptorConfigurations().add(transportConfig);
LOG.info("Added connector {} to broker", "HornetQ");
server.start();
waitForServerToStart(server);
}
@Override
@After
public void tearDown() throws Exception {
org.hornetq.core.client.impl.ServerLocatorImpl.clearThreadPools();
super.tearDown();
}
@Test
public void testMessagePropertiesAreTransformedBetweenCoreAndHQProtocols() throws Exception {
org.hornetq.api.core.client.ClientSession hqSession = createHQClientSession();
ClientSession coreSession = createCoreClientSession();
// Create Queue
String queueName = "test.hq.queue";
hqSession.createQueue(queueName, queueName, true);
// HornetQ Client Objects
hqSession.start();
org.hornetq.api.core.client.ClientProducer hqProducer = hqSession.createProducer(queueName);
org.hornetq.api.core.client.ClientConsumer hqConsumer = hqSession.createConsumer(queueName);
// Core Client Objects
coreSession.start();
ClientConsumer coreConsumer = coreSession.createConsumer(queueName);
// Check that HornetQ Properties are correctly converted to core properties.
for (int i = 0; i < 2; i++) {
hqProducer.send(createHQTestMessage(hqSession));
}
ClientMessage coreMessage1 = coreConsumer.receive(1000);
System.err.println("Messages::==" + coreMessage1);
assertTrue(coreMessage1.containsProperty(Message.HDR_DUPLICATE_DETECTION_ID));
coreSession.close();
// Check that HornetQ Properties are correctly transformed from then to HornetQ properties
org.hornetq.api.core.client.ClientMessage hqMessage1 = hqConsumer.receive(1000);
assertTrue(hqMessage1.containsProperty(org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID));
hqSession.close();
}
@Test
public void testCreateConsumerHQSelectorIsTransformed() throws Exception {
try (org.hornetq.api.core.client.ClientSession hqSession = createHQClientSession()) {
// Create Queue
String queueName = "test.hq.queue";
hqSession.createQueue(queueName, queueName, true);
hqSession.start();
// Send message with UserID set
org.hornetq.utils.UUID userID = UUIDGenerator.getInstance().generateUUID();
try (org.hornetq.api.core.client.ClientProducer hqProducer = hqSession.createProducer(queueName)) {
org.hornetq.api.core.client.ClientMessage message = createHQTestMessage(hqSession);
message.setUserID(userID);
hqProducer.send(message);
}
// Verify that selector using AMQ field works
verifyConsumerWithSelector(hqSession, queueName,
String.format("AMQUserID = 'ID:%s'", userID.toString()), userID);
// Verify that selector using HornetQ field works
verifyConsumerWithSelector(hqSession, queueName,
String.format("HQUserID = 'ID:%s'", userID.toString()), userID);
}
}
@Test
public void testCreateQueueHQFilterIsTransformed() throws Exception {
testQueueWithHQFilter(false);
}
@Test
public void testCreateTemporaryQueueHQFilterIsTransformed() throws Exception {
testQueueWithHQFilter(true);
}
@Test
public void testLargeMessagesOverHornetQClients() throws Exception {
org.hornetq.api.core.client.ClientSession hqSession = createHQClientSession();
// Create Queue
String queueName = "test.hq.queue";
hqSession.createQueue(queueName, queueName, true);
// HornetQ Client Objects
hqSession.start();
org.hornetq.api.core.client.ClientProducer hqProducer = hqSession.createProducer(queueName);
org.hornetq.api.core.client.ClientConsumer hqConsumer = hqSession.createConsumer(queueName);
for (int i = 0; i < 2; i++) {
org.hornetq.api.core.client.ClientMessage hqMessage = hqSession.createMessage(true);
hqMessage.setBodyInputStream(ActiveMQTestBase.createFakeLargeStream(10 * 1024));
hqProducer.send(hqMessage);
}
hqSession.commit();
for (int i = 0; i < 2; i++) {
org.hornetq.api.core.client.ClientMessage coreMessage1 = hqConsumer.receive(1000);
coreMessage1.acknowledge();
System.err.println("Messages::==" + coreMessage1);
for (int j = 0; j < 10 * 1024; j++) {
Assert.assertEquals(ActiveMQTestBase.getSamplebyte(j), coreMessage1.getBodyBuffer().readByte());
}
}
hqSession.close();
}
@Test
public void testDuplicateIDPropertyWithHornetQProtocol() throws Exception {
org.hornetq.api.core.client.ClientSession session = createHQClientSession();
String queueName = "test.hq.queue";
session.createQueue(queueName, queueName, true);
org.hornetq.api.core.client.ClientProducer producer = session.createProducer(queueName);
org.hornetq.api.core.client.ClientConsumer consumer = session.createConsumer(queueName);
org.hornetq.api.core.client.ClientMessage message = session.createMessage(false);
String messageId = UUID.randomUUID().toString();
message.putStringProperty(org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID.toString(), messageId);
session.start();
producer.send(message);
org.hornetq.api.core.client.ClientMessage m = consumer.receive(1000);
assertTrue(m.containsProperty(org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID));
assertNotNull(m);
producer.send(message);
m = consumer.receive(1000);
assertNull(m);
producer.send(message);
m = consumer.receive(1000);
assertNull(m);
session.close();
}
@Test
public void testDuplicateIDPropertyWithHornetQAndCoreProtocol() throws Exception {
org.hornetq.api.core.client.ClientSession hqSession = createHQClientSession();
String queueName = "test.hq.queue";
hqSession.createQueue(queueName, queueName, true);
org.hornetq.api.core.client.ClientProducer hqProducer = hqSession.createProducer(queueName);
org.hornetq.api.core.client.ClientMessage message = hqSession.createMessage(false);
String messageId = UUID.randomUUID().toString();
message.putStringProperty(org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID.toString(), messageId);
ClientSession coreSession = createCoreClientSession();
ClientConsumer coreConsumer = coreSession.createConsumer(queueName);
hqSession.start();
coreSession.start();
hqProducer.send(message);
Message m = coreConsumer.receive(1000);
assertTrue(m.containsProperty(Message.HDR_DUPLICATE_DETECTION_ID));
assertNotNull(m);
hqProducer.send(message);
m = coreConsumer.receive(1000);
assertNull(m);
hqProducer.send(message);
m = coreConsumer.receive(1000);
assertNull(m);
}
private org.hornetq.api.core.client.ClientMessage createHQTestMessage(org.hornetq.api.core.client.ClientSession session) {
org.hornetq.api.core.client.ClientMessage message = session.createMessage(true);
String v = UUID.randomUUID().toString();
message.putStringProperty(org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID.toString(), v);
return message;
}
private ClientMessage createCoreTestMessage(ClientSession session) {
ClientMessage message = session.createMessage(true);
String v = UUID.randomUUID().toString();
message.putStringProperty(org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID.toString(), v);
return message;
}
private org.hornetq.api.core.client.ClientSession createHQClientSession() throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("host", "localhost");
map.put("port", 5445);
org.hornetq.api.core.client.ServerLocator serverLocator = HornetQClient.createServerLocatorWithoutHA(new org.hornetq.api.core.TransportConfiguration(org.hornetq.core.remoting.impl.netty.NettyConnectorFactory.class.getName(), map));
org.hornetq.api.core.client.ClientSessionFactory sf = serverLocator.createSessionFactory();
return sf.createSession();
}
private ClientSession createCoreClientSession() throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("host", "localhost");
map.put("port", 61616);
ServerLocator serverLocator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(NettyConnectorFactory.class.getName(), map));
ClientSessionFactory sf = serverLocator.createSessionFactory();
return sf.createSession();
}
private static void verifyConsumerWithSelector(org.hornetq.api.core.client.ClientSession hqSession, String queueName,
String selector, org.hornetq.utils.UUID expectedUserID)
throws HornetQException {
try (org.hornetq.api.core.client.ClientConsumer hqConsumer =
hqSession.createConsumer(queueName, selector, true)) {
org.hornetq.api.core.client.ClientMessage message = hqConsumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals(expectedUserID, message.getUserID());
}
}
private void testQueueWithHQFilter(boolean temporary) throws Exception {
try (org.hornetq.api.core.client.ClientSession hqSession = createHQClientSession()) {
org.hornetq.utils.UUID userID = UUIDGenerator.getInstance().generateUUID();
// Create queue with filter
String queueName = "test.hq.queue";
String filter = String.format("HQUserID = 'ID:%s'", userID.toString());
if (temporary) {
hqSession.createTemporaryQueue(queueName, queueName, filter);
} else {
hqSession.createQueue(queueName, queueName, filter, true);
}
hqSession.start();
// Send two messages with different UserIDs
try (org.hornetq.api.core.client.ClientProducer hqProducer = hqSession.createProducer(queueName)) {
org.hornetq.api.core.client.ClientMessage message = createHQTestMessage(hqSession);
message.setUserID(userID);
hqProducer.send(message);
message = createHQTestMessage(hqSession);
message.setUserID(UUIDGenerator.getInstance().generateUUID());
hqProducer.send(message);
}
// Only the message matching the queue filter should be present
try (org.hornetq.api.core.client.ClientConsumer hqConsumer =
hqSession.createConsumer(queueName, true)) {
org.hornetq.api.core.client.ClientMessage message = hqConsumer.receiveImmediate();
Assert.assertNotNull(message);
Assert.assertEquals(userID, message.getUserID());
message = hqConsumer.receiveImmediate();
Assert.assertNull(message);
}
}
}
}

View File

@ -1 +0,0 @@
org.apache.activemq.artemis.tests.extras.jms.bridge.TransactionManagerLocatorImpl

View File

@ -79,14 +79,6 @@
</build>
<profiles>
<profile>
<id>extra-tests</id>
<modules>
<!-- to run extra-tests you must define -DskipExtraTests=false
or run it with the tests profile -->
<module>extra-tests</module>
</modules>
</profile>
<profile>
<id>jmh</id>
<modules>
@ -116,7 +108,6 @@
<id>release</id>
<modules>
<module>activemq5-unit-tests</module>
<module>extra-tests</module>
<module>performance-jmh</module>
</modules>
<properties>