From 9ef90f8defdce6845b6d01cb03613111972ecabd Mon Sep 17 00:00:00 2001 From: Clebert Suconic Date: Wed, 13 Dec 2017 21:53:19 -0500 Subject: [PATCH] ARTEMIS-1546 Adding tests to validate compatibility https://issues.apache.org/jira/browse/ARTEMIS-1546 - the dependency scan is changed to allow adding an extra repository - adding groovy so we won't require compilation dependencies (just runtime) without needing reflection (thanks Groovy :) ) - Adding hornetq to the mesh of version tests --- .../maven/ArtemisDependencyScanPlugin.java | 22 + .../send-acknowledgements-fail/pom.xml | 94 ++++ .../send-acknowledgements-fail/readme.html | 140 ++++++ .../example/SendAcknowledgementsExample.java | 151 ++++++ .../src/main/resources/jndi.properties | 20 + pom.xml | 6 + tests/compatibility-tests/pom.xml | 475 ++++++++++++++++++ .../tests/compatibility/GroovyRun.java | 118 +++++ .../resources/clients/artemisClient.groovy | 31 ++ .../resources/clients/hornetqClient.groovy | 33 ++ .../resources/meshTest/sendMessages.groovy | 205 ++++++++ .../sendAckTest/sendAckMessages.groovy | 97 ++++ .../src/main/resources/serial/serial.groovy | 54 ++ .../resources/servers/artemisServer.groovy | 61 +++ .../resources/servers/hornetqServer.groovy | 54 ++ .../artemis/tests/compatibility/MeshTest.java | 79 +++ .../tests/compatibility/SendAckTest.java | 78 +++ .../compatibility/SerializationTest.java | 76 +++ .../compatibility/VersionedBaseTest.java | 179 +++++++ .../tests/compatibility/package-info.java | 23 + tests/pom.xml | 1 + .../artemis/tests/util/SpawnedVMSupport.java | 63 ++- 22 files changed, 2057 insertions(+), 3 deletions(-) create mode 100644 examples/features/standard/send-acknowledgements-fail/pom.xml create mode 100644 examples/features/standard/send-acknowledgements-fail/readme.html create mode 100644 examples/features/standard/send-acknowledgements-fail/src/main/java/org/apache/activemq/artemis/jms/example/SendAcknowledgementsExample.java create mode 100644 examples/features/standard/send-acknowledgements-fail/src/main/resources/jndi.properties create mode 100644 tests/compatibility-tests/pom.xml create mode 100644 tests/compatibility-tests/src/main/java/org/apache/activemq/artemis/tests/compatibility/GroovyRun.java create mode 100644 tests/compatibility-tests/src/main/resources/clients/artemisClient.groovy create mode 100644 tests/compatibility-tests/src/main/resources/clients/hornetqClient.groovy create mode 100644 tests/compatibility-tests/src/main/resources/meshTest/sendMessages.groovy create mode 100644 tests/compatibility-tests/src/main/resources/sendAckTest/sendAckMessages.groovy create mode 100644 tests/compatibility-tests/src/main/resources/serial/serial.groovy create mode 100644 tests/compatibility-tests/src/main/resources/servers/artemisServer.groovy create mode 100644 tests/compatibility-tests/src/main/resources/servers/hornetqServer.groovy create mode 100644 tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java create mode 100644 tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java create mode 100644 tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java create mode 100644 tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java create mode 100644 tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/package-info.java diff --git a/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisDependencyScanPlugin.java b/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisDependencyScanPlugin.java index e59bc366c8..4f1d1d8aaf 100644 --- a/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisDependencyScanPlugin.java +++ b/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisDependencyScanPlugin.java @@ -19,6 +19,8 @@ package org.apache.activemq.artemis.maven; import java.io.File; import java.nio.file.Files; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; @@ -29,6 +31,7 @@ import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; +import org.eclipse.aether.repository.RemoteRepository; @Mojo(name = "dependency-scan", defaultPhase = LifecyclePhase.VERIFY) public class ArtemisDependencyScanPlugin extends ArtemisAbstractPlugin { @@ -47,6 +50,9 @@ public class ArtemisDependencyScanPlugin extends ArtemisAbstractPlugin { @Parameter private String[] libList; + @Parameter + private String[] extraRepositories; + @Parameter private String variableName; @@ -64,6 +70,16 @@ public class ArtemisDependencyScanPlugin extends ArtemisAbstractPlugin { @Override protected void doExecute() throws MojoExecutionException, MojoFailureException { + + int repositories = 0; + List listRepo = new ArrayList<>(); + if (extraRepositories != null) { + for (String strRepo: extraRepositories) { + RemoteRepository repo = new RemoteRepository.Builder("repo" + (repositories++), "default", strRepo).build(); + listRepo.add(repo); + remoteRepos.add(repo); + } + } getLog().info("Local " + localRepository); MavenProject project = (MavenProject) getPluginContext().get("project"); @@ -102,7 +118,13 @@ public class ArtemisDependencyScanPlugin extends ArtemisAbstractPlugin { } catch (Throwable e) { getLog().error(e); throw new MojoFailureException(e.getMessage()); + } finally { + for (RemoteRepository repository : listRepo) { + remoteRepos.remove(repository); + } } + + } } diff --git a/examples/features/standard/send-acknowledgements-fail/pom.xml b/examples/features/standard/send-acknowledgements-fail/pom.xml new file mode 100644 index 0000000000..369f94e720 --- /dev/null +++ b/examples/features/standard/send-acknowledgements-fail/pom.xml @@ -0,0 +1,94 @@ + + + + + 4.0.0 + + + org.apache.activemq.examples.broker + jms-examples + 2.5.0-SNAPSHOT + + + send-acknowledgements-fail + jar + ActiveMQ Artemis JMS Send Acknowledgements Example + + + ${project.basedir}/../../../.. + + + + + org.apache.activemq + artemis-jms-client-all + ${project.version} + + + org.apache.activemq + artemis-cli + ${project.version} + + + + + + + org.apache.activemq + artemis-maven-plugin + + + create + + create + + + ${basedir}/target/server0 + + --global-max-size + 10M + + + + + runClient + + runClient + + + org.apache.activemq.artemis.jms.example.SendAcknowledgementsExample + + ${basedir}/target/server0 + + + + + + + org.apache.activemq.examples.broker + send-acknowledgements-fail + ${project.version} + + + + + + + diff --git a/examples/features/standard/send-acknowledgements-fail/readme.html b/examples/features/standard/send-acknowledgements-fail/readme.html new file mode 100644 index 0000000000..fcc37fcc8c --- /dev/null +++ b/examples/features/standard/send-acknowledgements-fail/readme.html @@ -0,0 +1,140 @@ + + + + + ActiveMQ Artemis Asynchronous Send Acknowledgements Example + + + + + +

Asynchronous Send Acknowledgements Example

+ +
To run the example, simply type mvn verify from this directory, 
or mvn -PnoServer verify if you want to start and create the server manually.
+ + +

Asynchronous Send Acknowledgements are an advanced feature of ActiveMQ Artemis which allow you to + receive acknowledgements that messages were successfully received at the server in a separate thread to the sending thread

+

In this example we create a normal JMS session, then set a SendAcknowledgementHandler on the JMS + session's underlying core session. We send many messages to the server without blocking and asynchronously + receive send acknowledgements via the SendAcknowledgementHandler. + +

For more information on Asynchronous Send Acknowledgements please see the user manual

+

Example step-by-step

+

To run the example, simply type mvn verify -Pexample from this directory

+ +
    +
  1. First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the client-jndi.properties file in the directory ../common/config
  2. +
    +           InitialContext initialContext = getContext();
    +        
    + +
  3. We look-up the JMS queue object from JNDI
  4. +
    +           Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");
    +        
    + +
  5. We look-up the JMS connection factory object from JNDI
  6. +
    +           ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");
    +        
    + +
  7. We create a JMS connection
  8. +
    +           connection = cf.createConnection();
    +        
    + +
  9. Define a SendAcknowledgementHandler which will receive asynchronous acknowledgements
  10. +
    +           
    +         class MySendAcknowledgementsHandler implements SendAcknowledgementHandler
    +         {
    +            int count = 0;
    +
    +            public void sendAcknowledged(final Message message)
    +            {
    +               System.out.println("Received send acknowledgement for message " + count++);
    +            }
    +         }
    +           
    +        
    + +
  11. Create a JMS session
  12. +
    +          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    +       
    + +
  13. Set the handler on the underlying core session
  14. +
    +           
    +         ClientSession coreSession = ((ActiveMQSession)session).getCoreSession();
    +
    +         coreSession.setSendAcknowledgementHandler(new MySendAcknowledgementsHandler());
    +
    +           
    +        
    + +
  15. Create a JMS Message Producer
  16. +
    +           
    +         MessageProducer producer = session.createProducer(queue);
    +
    +         producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    +           
    +        
    + +
  17. Send 5000 messages, the handler will get called asynchronously some time later after the messages are sent.
  18. +
    +           
    +         final int numMessages = 5000;
    +
    +         for (int i = 0; i < numMessages; i++)
    +         {
    +            javax.jms.Message jmsMessage = session.createMessage();
    +
    +            producer.send(jmsMessage);
    +
    +            System.out.println("Sent message " + i);
    +         }
    +           
    +        
    + + +
  19. And finally, always remember to close your JMS connections and resources after use, in a finally block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
  20. + +
    +           finally
    +           {
    +              if (initialContext != null)
    +              {
    +                initialContext.close();
    +              }
    +              if (connection != null)
    +              {
    +                 connection.close();
    +              }
    +           }
    +        
    + + + +
+ + diff --git a/examples/features/standard/send-acknowledgements-fail/src/main/java/org/apache/activemq/artemis/jms/example/SendAcknowledgementsExample.java b/examples/features/standard/send-acknowledgements-fail/src/main/java/org/apache/activemq/artemis/jms/example/SendAcknowledgementsExample.java new file mode 100644 index 0000000000..86c4333619 --- /dev/null +++ b/examples/features/standard/send-acknowledgements-fail/src/main/java/org/apache/activemq/artemis/jms/example/SendAcknowledgementsExample.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.jms.example; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.activemq.artemis.api.core.Message; +import org.apache.activemq.artemis.api.core.RoutingType; +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.api.core.client.SendAcknowledgementHandler; +import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.util.ServerUtil; + +/** + * Asynchronous Send Acknowledgements are an advanced feature of ActiveMQ Artemis which allow you to + * receive acknowledgements that messages were successfully received at the server in a separate stream + * to the stream of messages being sent to the server. + * For more information please see the readme.html file + */ +public class SendAcknowledgementsExample { + + private static Process server0; + private static final int numMessages = 30_000; + private static final SimpleString queueName = SimpleString.toSimpleString("testQueue"); + + public static void main(final String[] args) throws Exception { + + for (int i = 0; i < 500; i++) { + System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Running test " + i); + server0 = ServerUtil.startServer(args[0], SendAcknowledgementsExample.class.getSimpleName() + "0", 0, 10000); + sendMessages(); + + server0 = ServerUtil.startServer(args[0], SendAcknowledgementsExample.class.getSimpleName() + "0", 0, 10000); + consumeMessages(); + } + } + + private static void sendMessages() throws Exception { + try { + + ServerLocator locator = ActiveMQClient.createServerLocator("tcp://localhost:61616").setBlockOnDurableSend(false).setConfirmationWindowSize(1024 * 1024); + + ClientSessionFactory factory = locator.createSessionFactory(); + + ClientSession session = factory.createSession(null, null, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE); + + try { + // Tried with and without the createAddress + session.createAddress(queueName, RoutingType.MULTICAST, false); + session.createQueue(queueName.toString(), RoutingType.MULTICAST, queueName.toString(), true); + } catch (Exception e) { + } + + ClientProducer producer = session.createProducer(queueName); + + CountDownLatch latch = new CountDownLatch(numMessages); + + for (int i = 0; i < numMessages; i++) { + + if (i % 10000 == 0) { + System.out.println("Send " + i); + } + ClientMessage message = session.createMessage(true); + message.getBodyBuffer().writeBytes("hello world".getBytes()); + + // tried with producer.send(queueName, message, ...);; // didn't make a difference + + producer.send(message, new SendAcknowledgementHandler() { + @Override + public void sendAcknowledged(Message message) { + latch.countDown(); + if (latch.getCount() % 10_000 == 0) { + System.out.println(latch.getCount() + " to go"); + } + } + }); + } + latch.await(10, TimeUnit.MINUTES); + } finally { + server0.destroy(); + server0.waitFor(); + } + } + + private static void consumeMessages() throws Exception { + try { + + ServerLocator locator = ActiveMQClient.createServerLocator("tcp://localhost:61616").setBlockOnDurableSend(false).setConfirmationWindowSize(-1); + + ClientSessionFactory factory = locator.createSessionFactory(); + + ClientSession session = factory.createSession(null, null, false, false, false, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE); + + ClientConsumer consumer = session.createConsumer(queueName); + + session.start(); + + for (int i = 0; i < numMessages; i++) { + + if (i % 10000 == 0) { + System.out.println("Received " + i); + } + + ClientMessage message = consumer.receive(5000); + message.acknowledge(); + + if (message == null) { + System.err.println("Expected message at " + i); + System.exit(-1); + } + } + + session.commit(); + + ClientMessage message = consumer.receiveImmediate(); + if (message != null) { + System.err.println("Received too many messages"); + System.exit(-1); + } + + session.close(); + locator.close(); + + } finally { + server0.destroy(); + server0.waitFor(); + } + } + +} diff --git a/examples/features/standard/send-acknowledgements-fail/src/main/resources/jndi.properties b/examples/features/standard/send-acknowledgements-fail/src/main/resources/jndi.properties new file mode 100644 index 0000000000..8421f257d4 --- /dev/null +++ b/examples/features/standard/send-acknowledgements-fail/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?confirmationWindowSize=1048576 +queue.queue/exampleQueue=exampleQueue diff --git a/pom.xml b/pom.xml index 885b97049e..1baad38937 100644 --- a/pom.xml +++ b/pom.xml @@ -111,6 +111,9 @@ 0.7.9 0.7.9 + + 2.4.3 + 1.4.3 5.0.1.RELEASE @@ -126,6 +129,7 @@ true true true + true true true true @@ -959,6 +963,7 @@ false false false + false false true false @@ -1005,6 +1010,7 @@ true false false + false diff --git a/tests/compatibility-tests/pom.xml b/tests/compatibility-tests/pom.xml new file mode 100644 index 0000000000..443b0ede03 --- /dev/null +++ b/tests/compatibility-tests/pom.xml @@ -0,0 +1,475 @@ + + + 4.0.0 + + + org.apache.activemq.tests + artemis-tests-pom + 2.5.0-SNAPSHOT + + + compatibility-tests + jar + ActiveMQ Artemis Compatibility Tests + + + ${project.basedir}/../.. + + + + + org.apache.activemq + artemis-server + ${project.version} + test + test-jar + + + org.apache.activemq + artemis-commons + ${project.version} + test + test-jar + + + org.apache.activemq.tests + unit-tests + ${project.version} + test + test-jar + + + org.apache.activemq + artemis-core-client + ${project.version} + test + test-jar + + + org.apache.activemq + artemis-jms-client + ${project.version} + + + org.apache.activemq + artemis-jms-server + ${project.version} + + + org.apache.activemq + artemis-ra + ${project.version} + + + org.apache.activemq + artemis-cli + ${project.version} + + + org.apache.activemq + artemis-commons + ${project.version} + + + org.apache.activemq + artemis-spring-integration + ${project.version} + + + org.apache.activemq + artemis-journal + ${project.version} + + + org.apache.activemq + artemis-jdbc-store + ${project.version} + + + org.apache.activemq + artemis-amqp-protocol + ${project.version} + + + org.apache.activemq + artemis-stomp-protocol + ${project.version} + + + org.apache.activemq + artemis-openwire-protocol + ${project.version} + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + + + + + org.apache.activemq + artemis-hornetq-protocol + ${project.version} + + + org.apache.activemq + artemis-core-client + ${project.version} + + + org.apache.activemq + artemis-server + ${project.version} + + + org.apache.activemq + artemis-native + ${project.version} + + + org.apache.activemq + artemis-service-extensions + ${project.version} + + + org.apache.activemq.tests + artemis-test-support + ${project.version} + + + org.apache.activemq + artemis-features + ${project.version} + pom + + + org.apache.activemq.rest + artemis-rest + 2.5.0-SNAPSHOT + + + org.codehaus.groovy + groovy-all + ${groovy.version} + + + org.apache.activemq + artemis-junit + ${project.version} + test + + + org.apache.activemq + activemq-client + test + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + + + + + org.apache.activemq + artemis-mqtt-protocol + ${project.version} + + + org.fusesource.mqtt-client + mqtt-client + + + org.apache.geronimo.specs + geronimo-json_1.0_spec + test + + + org.apache.geronimo.specs + geronimo-j2ee-connector_1.5_spec + + + org.apache.geronimo.specs + geronimo-jta_1.1_spec + + + org.apache.geronimo.specs + geronimo-jms_2.0_spec + + + org.apache.johnzon + johnzon-core + test + + + io.netty + netty-buffer + + + io.netty + netty-codec-http + + + io.netty + netty-codec-mqtt + ${netty.version} + + + io.netty + netty-handler + + + io.netty + netty-transport + + + junit + junit + + + org.jboss.logging + jboss-logging-processor + provided + true + + + org.jboss.logging + jboss-logging-annotations + provided + true + + + org.jboss.logging + jboss-logging + + + org.jboss.logmanager + jboss-logmanager + + + org.apache.qpid + qpid-jms-client + ${qpid.jms.version} + + + org.apache.qpid + proton-j + + + org.slf4j + slf4j-api + 1.7.5 + + + + + + + src/test/resources + true + + + + + org.apache.maven.plugins + maven-jar-plugin + + + test + + test-jar + + + + + + org.apache.activemq + artemis-maven-plugin + + + + snapshot-check + compile + + dependency-scan + + + + org.apache.activemq:artemis-jms-server:${project.version} + org.apache.activemq:artemis-jms-client:${project.version} + org.apache.activemq:artemis-hornetq-protocol:${project.version} + org.apache.activemq:artemis-amqp-protocol:${project.version} + org.apache.activemq:artemis-hornetq-protocol:${project.version} + org.codehaus.groovy:groovy-all:${groovy.version} + + + org.apache.activemq.tests:compatibility-tests:${project.version} + + ARTEMIS-SNAPSHOT + + + + compile + + dependency-scan + + 240-check + + + org.apache.activemq:artemis-jms-server:2.4.0 + org.apache.activemq:artemis-jms-client:2.4.0 + org.apache.activemq:artemis-hornetq-protocol:2.4.0 + org.apache.activemq:artemis-amqp-protocol:2.4.0 + org.apache.activemq:artemis-hornetq-protocol:2.4.0 + org.codehaus.groovy:groovy-all:${groovy.version} + + + org.apache.activemq.tests:compatibility-tests:${project.version} + + ARTEMIS-240 + + + + 140-check + compile + + dependency-scan + + + + org.apache.activemq:artemis-jms-server:1.4.0 + org.apache.activemq:artemis-jms-client:1.4.0 + org.apache.activemq:artemis-hornetq-protocol:1.4.0 + org.apache.activemq:artemis-amqp-protocol:1.4.0 + org.apache.activemq:artemis-hornetq-protocol:1.4.0 + org.codehaus.groovy:groovy-all:${groovy.version} + + + org.apache.activemq.tests:compatibility-tests:${project.version} + + ARTEMIS-140 + + + + hornetq-235 + compile + + dependency-scan + + + + + https://repository.jboss.org/nexus/content/groups/public + + + org.hornetq:hornetq-jms-server:2.4.7.Final + org.codehaus.groovy:groovy-all:${groovy.version} + + + org.apache.activemq.tests:compatibility-tests:${project.version} + + HORNETQ-235 + + + + hornetq-247 + compile + + dependency-scan + + + + + https://repository.jboss.org/nexus/content/groups/public + + + org.hornetq:hornetq-jms-server:2.4.7.Final + org.codehaus.groovy:groovy-all:${groovy.version} + + + org.apache.activemq.tests:compatibility-tests:${project.version} + + HORNETQ-247 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + ARTEMIS-SNAPSHOT + ${ARTEMIS-SNAPSHOT} + + + ARTEMIS-240 + ${ARTEMIS-240} + + + ARTEMIS-140 + ${ARTEMIS-140} + + + HORNETQ-235 + ${HORNETQ-235} + + + HORNETQ-247 + ${HORNETQ-247} + + + ${skipCompatibilityTests} + -Djgroups.bind_addr=::1 ${activemq-surefire-argline} + + + + org.apache.servicemix.tooling + depends-maven-plugin + 1.2 + + + generate-depends-file + + generate-depends-file + + + + + + + + + + jboss-releases-repository + JBoss Releases Repository + https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ + + + jboss-snapshots-repository + JBoss Snapshots Repository + https://repository.jboss.org/nexus/content/repositories/snapshots/ + + + + + diff --git a/tests/compatibility-tests/src/main/java/org/apache/activemq/artemis/tests/compatibility/GroovyRun.java b/tests/compatibility-tests/src/main/java/org/apache/activemq/artemis/tests/compatibility/GroovyRun.java new file mode 100644 index 0000000000..08e6c34081 --- /dev/null +++ b/tests/compatibility-tests/src/main/java/org/apache/activemq/artemis/tests/compatibility/GroovyRun.java @@ -0,0 +1,118 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.compatibility; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +import groovy.lang.Binding; +import groovy.lang.GroovyShell; + +public class GroovyRun { + + public static final String SNAPSHOT = "ARTEMIS-SNAPSHOT"; + public static final String ONE_FOUR = "ARTEMIS-140"; + public static final String TWO_FOUR = "ARTEMIS-240"; + public static final String HORNETQ_235 = "HORNETQ-235"; + public static final String HORNETQ_247 = "HORNETQ-247"; + + public static final String WORD_START = "**SERVER STARTED**"; + + public static Binding binding = new Binding(); + public static GroovyShell shell = new GroovyShell(binding); + + // Called with reflection + public static void doMain(String script, String... arg) throws Throwable { + int i = 0; + for (String a : arg) { + System.out.println("[" + (i++) + "]=" + a); + } + System.out.println(); + + evaluate(script, "arg", arg); + + System.out.println(WORD_START); + } + + /** + * This can be called from the scripts as well. + * The scripts will use this method instead of its own groovy method. + * As a classloader operation needs to be done here. + */ + public static void evaluate(String script, + String argVariableName, + String[] arg) throws URISyntaxException, IOException { + URL scriptURL = GroovyRun.class.getClassLoader().getResource(script); + if (scriptURL == null) { + throw new RuntimeException("cannot find " + script); + } + URI scriptURI = scriptURL.toURI(); + + binding.setVariable(argVariableName, arg); + + shell.evaluate(scriptURI); + } + + // Called with reflection + public static void execute(String script) throws Throwable { + shell.evaluate(script); + } + + public static void assertNotNull(Object value) { + if (value == null) { + throw new RuntimeException("Null value"); + } + } + + public static void assertNull(Object value) { + if (value != null) { + throw new RuntimeException("Expected Null value"); + } + } + + public static void assertTrue(boolean value) { + if (!value) { + throw new RuntimeException("Expected true"); + } + } + + public static void assertEquals(Object value1, Object value2) { + if (!value1.equals(value2)) { + throw new RuntimeException(value1 + "!=" + value2); + } + } + + public static void assertEquals(int value1, int value2) { + if (value1 != value2) { + throw new RuntimeException(value1 + "!=" + value2); + } + } + + public static void assertEquals(byte[] value1, byte[] value2) { + + assertEquals(value1.length, value2.length); + + for (int i = 0; i < value1.length; i++) { + assertEquals(value1[i], value2[i]); + } + } + + + public static byte getSamplebyte(final long position) { + return (byte) ('a' + position % ('z' - 'a' + 1)); + } +} + diff --git a/tests/compatibility-tests/src/main/resources/clients/artemisClient.groovy b/tests/compatibility-tests/src/main/resources/clients/artemisClient.groovy new file mode 100644 index 0000000000..e729ebb0fa --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/clients/artemisClient.groovy @@ -0,0 +1,31 @@ +package clients +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// Create a client connection factory + +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory +import org.apache.activemq.artemis.tests.compatibility.GroovyRun; + +println("serverType " + serverArg[0]); + +if (serverArg[0].startsWith("HORNETQ")) { + cf = new ActiveMQConnectionFactory("tcp://localhost:61616?protocolManagerFactoryStr=org.apache.activemq.artemis.core.protocol.hornetq.client.HornetQClientProtocolManagerFactory&confirmationWindowSize=1048576&blockOnDurableSend=false"); +} else { + cf = new ActiveMQConnectionFactory("tcp://localhost:61616?confirmationWindowSize=1048576&blockOnDurableSend=false"); +} + + +GroovyRun.assertTrue(!cf.getServerLocator().isBlockOnDurableSend()); +GroovyRun.assertEquals(1048576, cf.getServerLocator().getConfirmationWindowSize()); + diff --git a/tests/compatibility-tests/src/main/resources/clients/hornetqClient.groovy b/tests/compatibility-tests/src/main/resources/clients/hornetqClient.groovy new file mode 100644 index 0000000000..63bf4e6da1 --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/clients/hornetqClient.groovy @@ -0,0 +1,33 @@ +package clients +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 script is called by sendMessages.groovy + +import javax.jms.ConnectionFactory; +import java.util.HashMap; +import java.util.Map; + +import org.hornetq.api.core.TransportConfiguration; +import org.hornetq.api.jms.HornetQJMSConstants; +import org.hornetq.core.message.impl.MessageImpl; +import org.hornetq.core.remoting.impl.netty.NettyConnectorFactory; +import org.hornetq.core.remoting.impl.netty.TransportConstants; +import org.hornetq.jms.client.HornetQJMSConnectionFactory; + + +properties = new HashMap(); +properties.put(TransportConstants.HOST_PROP_NAME, "localhost"); +properties.put(TransportConstants.PORT_PROP_NAME, "61616"); +configuration = new TransportConfiguration(NettyConnectorFactory.class.getName(), properties); +cf = new HornetQJMSConnectionFactory(false, configuration); diff --git a/tests/compatibility-tests/src/main/resources/meshTest/sendMessages.groovy b/tests/compatibility-tests/src/main/resources/meshTest/sendMessages.groovy new file mode 100644 index 0000000000..fdfddee54f --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/meshTest/sendMessages.groovy @@ -0,0 +1,205 @@ +package meshTest + +import org.apache.activemq.artemis.api.core.SimpleString +import org.apache.activemq.artemis.tests.compatibility.GroovyRun + +import javax.jms.* + +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// starts an artemis server +String serverType = arg[0]; +String clientType = arg[1]; +String operation = arg[2]; + + +String queueName = "queue"; + +int LARGE_MESSAGE_SIZE = 10 * 1024; + +String propertyLargeMessage = "JMS_AMQ_InputStream"; +HDR_DUPLICATE_DETECTION_ID = "_AMQ_DUPL_ID"; + +if (clientType.startsWith("HORNETQ")) { + HDR_DUPLICATE_DETECTION_ID = "_HQ_DUPL_ID"; + propertyLargeMessage = "JMS_HQ_InputStream" +} + +BYTES_BODY = new byte[3]; +BYTES_BODY[0] = (byte) 0x77; +BYTES_BODY[1] = (byte) 0x77; +BYTES_BODY[2] = (byte) 0x77; + +String textBody = "a rapadura e doce mas nao e mole nao"; + + +println("serverType " + serverType); + +if (clientType.startsWith("ARTEMIS")) { + // Can't depend directly on artemis, otherwise it wouldn't compile in hornetq + GroovyRun.evaluate("clients/artemisClient.groovy", "serverArg", serverType); +} else { + // Can't depend directly on hornetq, otherwise it wouldn't compile in artemis + GroovyRun.evaluate("clients/hornetqClient.groovy", "serverArg"); +} + + +Connection connection = cf.createConnection(); +Session session = connection.createSession(true, Session.SESSION_TRANSACTED); +Queue queue = session.createQueue(queueName); + +if (operation.equals("sendAckMessages")) { + MessageProducer producer = session.createProducer(queue); + producer.setDeliveryMode(DeliveryMode.PERSISTENT); + + System.out.println("Sending messages"); + + TextMessage message = session.createTextMessage(textBody); + message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, "some-duplicate"); + message.setStringProperty("prop", "test"); + producer.send(message); + + BytesMessage bytesMessage = session.createBytesMessage(); + bytesMessage.writeBytes(BYTES_BODY); + producer.send(bytesMessage); + + + for (int i = 0; i < 10; i++) { + BytesMessage m = session.createBytesMessage(); + m.setIntProperty("count", i); + + m.setObjectProperty(propertyLargeMessage, createFakeLargeStream(LARGE_MESSAGE_SIZE)); + + producer.send(m); + } + + producer.send(session.createObjectMessage("rapadura")); + + MapMessage mapMessage = session.createMapMessage(); + mapMessage.setString("prop", "rapadura") + producer.send(mapMessage); + + StreamMessage streamMessage = session.createStreamMessage(); + streamMessage.writeString("rapadura"); + streamMessage.writeString("doce"); + streamMessage.writeInt(33); + producer.send(streamMessage); + + Message plain = session.createMessage(); + plain.setStringProperty("plain", "doce"); + producer.send(plain); + + session.commit(); + + connection.close(); + System.out.println("Message sent"); +} else if (operation.equals("receiveMessages")) { + MessageConsumer consumer = session.createConsumer(queue); + connection.start(); + + System.out.println("Receiving messages"); + + TextMessage message = (TextMessage) consumer.receive(5000); + GroovyRun.assertNotNull(message); + GroovyRun.assertEquals(textBody, message.getText()); + GroovyRun.assertEquals("test", message.getStringProperty("prop")); + GroovyRun.assertEquals("some-duplicate", message.getStringProperty(HDR_DUPLICATE_DETECTION_ID)); + + BytesMessage bm = (BytesMessage) consumer.receive(5000); + GroovyRun.assertNotNull(bm); + + GroovyRun.assertEquals(3L, bm.getBodyLength()); + + byte[] body = new byte[3]; + bm.readBytes(body); + + GroovyRun.assertEquals(BYTES_BODY, body); + + for (int m = 0; m < 10; m++) { + BytesMessage rm = (BytesMessage) consumer.receive(10000); + GroovyRun.assertNotNull(rm); + GroovyRun.assertEquals(m, rm.getIntProperty("count")); + + byte[] data = new byte[1024]; + + System.out.println("Message = " + rm); + + for (int i = 0; i < LARGE_MESSAGE_SIZE; i += 1024) { + int numberOfBytes = rm.readBytes(data); + GroovyRun.assertEquals(1024, numberOfBytes); + for (int j = 0; j < 1024; j++) { + GroovyRun.assertEquals(GroovyRun.getSamplebyte(i + j), data[j]); + } + } + } + + + ObjectMessage obj = consumer.receive(5000); + GroovyRun.assertNotNull(obj); + GroovyRun.assertEquals("rapadura", obj.getObject().toString()); + + MapMessage mapMessage = consumer.receive(5000); + GroovyRun.assertNotNull(mapMessage); + GroovyRun.assertEquals("rapadura", mapMessage.getString("prop")); + + StreamMessage streamMessage = consumer.receive(5000); + GroovyRun.assertNotNull(streamMessage); + GroovyRun.assertEquals("rapadura", streamMessage.readString()); + GroovyRun.assertEquals("doce", streamMessage.readString()); + GroovyRun.assertTrue(streamMessage.readInt() == 33); + + Message plain = consumer.receive(5000); + GroovyRun.assertNotNull(plain); + GroovyRun.assertEquals("doce", plain.getStringProperty("plain")); + + session.commit(); + connection.close(); + System.out.println("Message received"); +} else { + throw new RuntimeException("Invalid operation " + operation); +} + + +// Creates a Fake LargeStream without using a real file +InputStream createFakeLargeStream(final long size) throws Exception { + return new InputStream() { + private long count; + + private boolean closed = false; + + @Override + void close() throws IOException { + super.close(); + closed = true; + } + + @Override + int read() throws IOException { + if (closed) { + throw new IOException("Stream was closed"); + } + if (count++ < size) { + return GroovyRun.getSamplebyte(count - 1); + } + else { + return -1; + } + } + + }; + +} + + + diff --git a/tests/compatibility-tests/src/main/resources/sendAckTest/sendAckMessages.groovy b/tests/compatibility-tests/src/main/resources/sendAckTest/sendAckMessages.groovy new file mode 100644 index 0000000000..2b994bf04a --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/sendAckTest/sendAckMessages.groovy @@ -0,0 +1,97 @@ +package meshTest + +import org.apache.activemq.artemis.api.core.SimpleString +import org.apache.activemq.artemis.tests.compatibility.GroovyRun + +import javax.jms.* +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// starts an artemis server +String serverType = arg[0]; +String clientType = arg[1]; +String operation = arg[2]; + + +String queueName = "queue"; + + +String textBody = "a rapadura e doce mas nao e mole nao"; + +println("serverType " + serverType); + +if (clientType.startsWith("ARTEMIS")) { + // Can't depend directly on artemis, otherwise it wouldn't compile in hornetq + GroovyRun.evaluate("clients/artemisClient.groovy", "serverArg", serverType); +} else { + // Can't depend directly on hornetq, otherwise it wouldn't compile in artemis + GroovyRun.evaluate("clients/hornetqClient.groovy", "serverArg"); +} + + +Connection connection = cf.createConnection(); +Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); +Queue queue = session.createQueue(queueName); + +if (operation.equals("sendAckMessages")) { + + CountDownLatch latch = new CountDownLatch(10); + + CompletionListener completionListener = new CompletionListener() { + @Override + void onCompletion(Message message) { + latch.countDown(); + } + + @Override + void onException(Message message, Exception exception) { + + } + } + + MessageProducer producer = session.createProducer(queue); + producer.setDeliveryMode(DeliveryMode.PERSISTENT); + for (int i = 0; i < 10; i++) { + producer.send(session.createTextMessage(textBody + i), completionListener); + } + + GroovyRun.assertTrue(latch.await(10, TimeUnit.SECONDS)); + + System.out.println("Sending messages"); + connection.close(); + System.out.println("Message sent"); +} else if (operation.equals("receiveMessages")) { + MessageConsumer consumer = session.createConsumer(queue); + connection.start(); + + System.out.println("Receiving messages"); + + for (int i = 0; i < 10; i++) { + TextMessage message = consumer.receive(1000); + GroovyRun.assertNotNull(message); + GroovyRun.assertEquals(textBody + i, message.getText()); + } + + GroovyRun.assertNull(consumer.receiveNoWait()); + connection.close(); + System.out.println("Message received"); +} else { + throw new RuntimeException("Invalid operation " + operation); +} + + + + diff --git a/tests/compatibility-tests/src/main/resources/serial/serial.groovy b/tests/compatibility-tests/src/main/resources/serial/serial.groovy new file mode 100644 index 0000000000..1fc9dbd8ef --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/serial/serial.groovy @@ -0,0 +1,54 @@ +package clients +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// Create a client connection factory + +import org.apache.activemq.artemis.tests.compatibility.GroovyRun; +import javax.jms.*; +import org.apache.activemq.artemis.jms.client.* + +file = arg[0] +method = arg[1] +System.out.println("File::" + file); + + +if (method.equals("write")) { + cf = new ActiveMQConnectionFactory("tcp://localhost:61616?confirmationWindowSize=1048576&blockOnDurableSend=false"); + queue = new ActiveMQQueue("queue"); + topic = new ActiveMQTopic("topic") + + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file)); + objectOutputStream.writeObject(cf); + objectOutputStream.writeObject(queue) + objectOutputStream.writeObject(topic) + objectOutputStream.close(); +} else { + ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file)) + + cf = inputStream.readObject(); + queue = inputStream.readObject() + topic = inputStream.readObject() + inputStream.close(); +} + +GroovyRun.assertTrue(!cf.getServerLocator().isBlockOnDurableSend()); +GroovyRun.assertEquals(1048576, cf.getServerLocator().getConfirmationWindowSize()); + +Connection connection = cf.createConnection(); +Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); +MessageConsumer consumer = session.createConsumer(queue); +MessageProducer topicProducer = session.createProducer(topic) +connection.close(); + + diff --git a/tests/compatibility-tests/src/main/resources/servers/artemisServer.groovy b/tests/compatibility-tests/src/main/resources/servers/artemisServer.groovy new file mode 100644 index 0000000000..3ec6d319a8 --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/servers/artemisServer.groovy @@ -0,0 +1,61 @@ +package servers +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// starts an artemis server + +import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; +import org.apache.activemq.artemis.core.server.JournalType; +import org.apache.activemq.artemis.core.settings.impl.AddressSettings; +import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl; +import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS +import org.apache.activemq.artemis.tests.compatibility.GroovyRun; + + +String folder = arg[0]; +String id = arg[1]; +String type = arg[2]; +String producer = arg[3]; +String consumer = arg[4]; + +println("type = " + type); + +configuration = new ConfigurationImpl(); +configuration.setJournalType(JournalType.NIO); +System.out.println("folder:: " + folder); +configuration.setBrokerInstance(new File(folder + "/" + id)); +configuration.addAcceptorConfiguration("artemis", "tcp://0.0.0.0:61616"); +configuration.setSecurityEnabled(false); +configuration.setPersistenceEnabled(false); +try { + if (!type.equals("ARTEMIS-140")) { + configuration.addAddressesSetting("#", new AddressSettings().setAutoCreateAddresses(true)); + } +} catch (Throwable e) { + // need to ignore this for 1.4 + e.printStackTrace(); +} + +jmsConfiguration = new JMSConfigurationImpl(); + +server = new EmbeddedJMS(); +server.setConfiguration(configuration); +server.setJmsConfiguration(jmsConfiguration); +server.start(); + +// uncomment this line to validate https://issues.apache.org/jira/browse/ARTEMIS-1561 +// this api exists on both 1.4 and 2.x... so, this one was preferred for this +if (producer.toString().startsWith("HORNETQ")) { + // hornetq servers won't auto-create + server.getJMSServerManager().createQueue(true, "queue", null, true); +} diff --git a/tests/compatibility-tests/src/main/resources/servers/hornetqServer.groovy b/tests/compatibility-tests/src/main/resources/servers/hornetqServer.groovy new file mode 100644 index 0000000000..be92768b1a --- /dev/null +++ b/tests/compatibility-tests/src/main/resources/servers/hornetqServer.groovy @@ -0,0 +1,54 @@ +package servers +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +// starts a hornetq server + +import org.hornetq.api.core.TransportConfiguration +import org.hornetq.core.config.impl.ConfigurationImpl +import org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory +import org.hornetq.core.remoting.impl.netty.TransportConstants +import org.hornetq.jms.server.config.impl.JMSConfigurationImpl +import org.hornetq.jms.server.config.impl.JMSQueueConfigurationImpl +import org.hornetq.jms.server.embedded.EmbeddedJMS + +String folder = arg[0]; +String id = arg[1]; +String type = arg[2]; +String producer = arg[3]; +String consumer = arg[4]; + +configuration = new ConfigurationImpl(); +configuration.setSecurityEnabled(false); +configuration.setJournalDirectory(folder + "/" + id + "/journal"); +configuration.setBindingsDirectory(folder + "/" + id + "/binding"); +configuration.setPagingDirectory(folder + "/" + id + "/paging"); +configuration.setLargeMessagesDirectory(folder + "/" + id + "/largemessage"); +configuration.setJournalType(org.hornetq.core.server.JournalType.NIO); +configuration.setPersistenceEnabled(false); + +HashMap map = new HashMap(); +map.put(TransportConstants.HOST_PROP_NAME, "localhost"); +map.put(TransportConstants.PORT_PROP_NAME, "61616"); +TransportConfiguration tpc = new TransportConfiguration(NettyAcceptorFactory.class.getName(), map); +configuration.getAcceptorConfigurations().add(tpc); + +jmsConfiguration = new JMSConfigurationImpl(); + +JMSQueueConfigurationImpl queueConfiguration = new JMSQueueConfigurationImpl("queue", null, true); +jmsConfiguration.getQueueConfigurations().add(queueConfiguration); +server = new EmbeddedJMS(); +server.setConfiguration(configuration); +server.setJmsConfiguration(jmsConfiguration); +server.start(); + diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java new file mode 100644 index 0000000000..ed7851c20f --- /dev/null +++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.compatibility; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.HORNETQ_235; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.HORNETQ_247; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.ONE_FOUR; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.TWO_FOUR; + +/** + * To run this test on the IDE and debug it, run the compatibility-tests through a command line once: + * + * cd /compatibility-tests + * mvn install -Ptests | tee output.log + * + * on the output.log you will see the output generated by {@link #getClasspathProperty(String)} + * + * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test. + * On Idea you would do the following: + * + * Run->Edit Configuration->Add ArtemisMeshTest and add your properties. + */ +@RunWith(Parameterized.class) +public class MeshTest extends VersionedBaseTest { + + // this will ensure that all tests in this class are run twice, + // once with "true" passed to the class' constructor and once with "false" + @Parameterized.Parameters(name = "server={0}, producer={1}, consumer={2}") + public static Collection getParameters() { + // we don't need every single version ever released.. + // if we keep testing current one against 2.4 and 1.4.. we are sure the wire and API won't change over time + List combinations = new ArrayList<>(); + + /* + // during development sometimes is useful to comment out the combinations + // and add the ones you are interested.. example: + */ + // combinations.add(new Object[]{SNAPSHOT, ONE_FOUR, ONE_FOUR}); + // combinations.add(new Object[]{ONE_FOUR, ONE_FOUR, ONE_FOUR}); + + combinations.addAll(combinatory(new Object[]{SNAPSHOT}, new Object[]{ONE_FOUR, TWO_FOUR, SNAPSHOT, HORNETQ_235}, new Object[]{ONE_FOUR, TWO_FOUR, SNAPSHOT, HORNETQ_235})); + combinations.addAll(combinatory(new Object[]{ONE_FOUR}, new Object[]{ONE_FOUR, SNAPSHOT}, new Object[]{ONE_FOUR, SNAPSHOT})); + combinations.addAll(combinatory(new Object[]{HORNETQ_235}, new Object[]{ONE_FOUR, SNAPSHOT, HORNETQ_235}, new Object[]{ONE_FOUR, SNAPSHOT, HORNETQ_235})); + combinations.addAll(combinatory(new Object[]{HORNETQ_247}, new Object[]{SNAPSHOT, HORNETQ_247}, new Object[]{SNAPSHOT, HORNETQ_247})); + return combinations; + } + + public MeshTest(String server, String sender, String receiver) throws Exception { + super(server, sender, receiver); + } + + @Test + public void testSendReceive() throws Throwable { + callMain(senderClassloader, GroovyRun.class.getName(), "meshTest/sendMessages.groovy", server, sender, "sendAckMessages"); + callMain(receiverClassloader, GroovyRun.class.getName(), "meshTest/sendMessages.groovy", server, receiver, "receiveMessages"); + } + +} + diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java new file mode 100644 index 0000000000..2f217045bd --- /dev/null +++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.compatibility; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.ONE_FOUR; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.TWO_FOUR; + +/** + * To run this test on the IDE and debug it, run the compatibility-tests through a command line once: + * + * cd /compatibility-tests + * mvn install -Ptests | tee output.log + * + * on the output.log you will see the output generated by {@link #getClasspathProperty(String)} + * + * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test. + * On Idea you would do the following: + * + * Run->Edit Configuration->Add ArtemisMeshTest and add your properties. + */ +@RunWith(Parameterized.class) +public class SendAckTest extends VersionedBaseTest { + + // this will ensure that all tests in this class are run twice, + // once with "true" passed to the class' constructor and once with "false" + @Parameterized.Parameters(name = "server={0}, producer={1}, consumer={2}") + public static Collection getParameters() { + // we don't need every single version ever released.. + // if we keep testing current one against 2.4 and 1.4.. we are sure the wire and API won't change over time + List combinations = new ArrayList<>(); + + /* + // during development sometimes is useful to comment out the combinations + // and add the ones you are interested.. example: + */ + // combinations.add(new Object[]{SNAPSHOT, ONE_FOUR, ONE_FOUR}); + // combinations.add(new Object[]{ONE_FOUR, ONE_FOUR, ONE_FOUR}); + + combinations.addAll(combinatory(new Object[]{SNAPSHOT, ONE_FOUR}, new Object[]{ONE_FOUR, SNAPSHOT}, new Object[]{ONE_FOUR, SNAPSHOT})); + + // not every combination on two four would make sense.. as there's a compatibility issue between 2.4 and 1.4 when crossing consumers and producers + combinations.add(new Object[]{TWO_FOUR, SNAPSHOT, SNAPSHOT}); + combinations.add(new Object[]{SNAPSHOT, TWO_FOUR, TWO_FOUR}); + return combinations; + } + + public SendAckTest(String server, String sender, String receiver) throws Exception { + super(server, sender, receiver); + } + + @Test + public void testSendReceive() throws Throwable { + callMain(senderClassloader, GroovyRun.class.getName(), "sendAckTest/sendAckMessages.groovy", server, sender, "sendAckMessages"); + callMain(receiverClassloader, GroovyRun.class.getName(), "sendAckTest/sendAckMessages.groovy", server, receiver, "receiveMessages"); + } + +} + diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java new file mode 100644 index 0000000000..c99e6968cd --- /dev/null +++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.compatibility; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.ONE_FOUR; +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT; + +/** + * To run this test on the IDE and debug it, run the compatibility-tests through a command line once: + * + * cd /compatibility-tests + * mvn install -Ptests | tee output.log + * + * on the output.log you will see the output generated by {@link #getClasspathProperty(String)} + * + * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test. + * On Idea you would do the following: + * + * Run->Edit Configuration->Add ArtemisMeshTest and add your properties. + */ +@RunWith(Parameterized.class) +public class SerializationTest extends VersionedBaseTest { + + // this will ensure that all tests in this class are run twice, + // once with "true" passed to the class' constructor and once with "false" + @Parameterized.Parameters(name = "server={0}, producer={1}, consumer={2}") + public static Collection getParameters() { + // we don't need every single version ever released.. + // if we keep testing current one against 2.4 and 1.4.. we are sure the wire and API won't change over time + List combinations = new ArrayList<>(); + + /* + // during development sometimes is useful to comment out the combinations + // and add the ones you are interested.. example: + */ + // combinations.add(new Object[]{SNAPSHOT, ONE_FOUR, ONE_FOUR}); + // combinations.add(new Object[]{ONE_FOUR, ONE_FOUR, ONE_FOUR}); + + combinations.addAll(combinatory(new Object[]{SNAPSHOT}, new Object[]{ONE_FOUR, SNAPSHOT}, new Object[]{ONE_FOUR, SNAPSHOT})); + return combinations; + } + + public SerializationTest(String server, String sender, String receiver) throws Exception { + super(server, sender, receiver); + } + + @Test + public void testSerializeFactory() throws Throwable { + File file = serverFolder.newFile("objects.ser"); + file.mkdirs(); + callMain(senderClassloader, GroovyRun.class.getName(), "serial/serial.groovy", file.getAbsolutePath(), "write"); + callMain(receiverClassloader, GroovyRun.class.getName(), "serial/serial.groovy", file.getAbsolutePath(), "read"); + } + +} + diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java new file mode 100644 index 0000000000..64183d60cd --- /dev/null +++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java @@ -0,0 +1,179 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.compatibility; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import org.apache.activemq.artemis.utils.FileUtil; +import org.apache.activemq.artemis.utils.RunnableEx; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.rules.TemporaryFolder; + +import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT; + +public abstract class VersionedBaseTest { + + protected final String server; + protected final String sender; + protected final String receiver; + + protected ClassLoader serverClassloader; + protected ClassLoader senderClassloader; + protected ClassLoader receiverClassloader; + + public VersionedBaseTest(String server, String sender, String receiver) throws Exception { + this.server = server; + this.sender = sender; + this.receiver = receiver; + this.serverClassloader = getClasspathProperty(server); + this.senderClassloader = getClasspathProperty(sender); + this.receiverClassloader = getClasspathProperty(receiver); + } + + // This is a test optimization.. + // if false it will span a new VM for each classLoader used. + // this can be a bit faster + public static final boolean USE_CLASSLOADER = true; + + private static HashSet printed = new HashSet<>(); + + @ClassRule + public static TemporaryFolder serverFolder; + + static { + File parent = new File("./target/tmp"); + parent.mkdirs(); + serverFolder = new TemporaryFolder(parent); + } + + @Before + public void startServer() throws Throwable { + FileUtil.deleteDirectory(serverFolder.getRoot()); + + serverFolder.getRoot().mkdirs(); + + System.out.println("Folder::" + serverFolder.getRoot()); + + String scriptToUse; + if (server.startsWith("ARTEMIS")) { + scriptToUse = "servers/artemisServer.groovy"; + } else { + scriptToUse = "servers/hornetqServer.groovy"; + } + + callMain(serverClassloader, GroovyRun.class.getName(), scriptToUse, serverFolder.getRoot().getAbsolutePath(), "1", server, sender, receiver); + } + + @After + public void stopServer() throws Throwable { + callExecute(serverClassloader, GroovyRun.class.getName(), "server.stop()"); + + // GC help!!! + serverClassloader = null; + senderClassloader = null; + receiverClassloader = null; + } + + protected static void callMain(ClassLoader loader, + String className, + String script, + String... arguments) throws Exception { + tclCall(loader, () -> { + Class clazz = loader.loadClass(className); + Method method = clazz.getMethod("doMain", String.class, String[].class); + method.invoke(null, script, arguments); + }); + } + + protected static void callExecute(ClassLoader loader, String className, String script) throws Exception { + tclCall(loader, () -> { + Class clazz = loader.loadClass(className); + Method method = clazz.getMethod("execute", String.class); + method.invoke(null, script); + }); + } + + protected static void tclCall(ClassLoader loader, RunnableEx run) throws Exception { + + ClassLoader original = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(loader); + try { + run.run(); + } finally { + Thread.currentThread().setContextClassLoader(original); + } + } + + protected static ClassLoader defineClassLoader(String classPath) throws MalformedURLException { + String[] classPathArray = classPath.split(File.pathSeparator); + URL[] elements = new URL[classPathArray.length]; + for (int i = 0; i < classPathArray.length; i++) { + elements[i] = new File(classPathArray[i]).toPath().toUri().toURL(); + } + + return new URLClassLoader(elements, null); + } + + protected static ClassLoader getClasspathProperty(String name) throws Exception { + + if (name.equals(SNAPSHOT)) { + return VersionedBaseTest.class.getClassLoader(); + } + String value = System.getProperty(name); + + if (!printed.contains(name)) { + boolean ok = value != null && !value.trim().isEmpty(); + if (!ok) { + System.out.println("Add \"-D" + name + "=\'CLASSPATH\'\" into your VM settings"); + } else { + printed.add(name); + System.out.println("****************************************************************************"); + System.out.println("* If you want to debug this test, add this parameter to your IDE run settings..."); + System.out.println("****************************************************************************"); + System.out.println("-D" + name + "=\"" + value + "\""); + System.out.println("****************************************************************************"); + + } + + Assume.assumeTrue("Cannot run these tests, no classpath found", ok); + } + + return defineClassLoader(value); + } + + protected static List combinatory(Object[] rootSide, Object[] sideLeft, Object[] sideRight) { + LinkedList combinations = new LinkedList<>(); + + for (Object root : rootSide) { + for (Object left : sideLeft) { + for (Object right : sideRight) { + combinations.add(new Object[]{root, left, right}); + } + } + } + + return combinations; + } + +} diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/package-info.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/package-info.java new file mode 100644 index 0000000000..0c3c124613 --- /dev/null +++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 package will contain tests that will validate Artemis within itself in different versions + * and within some specific hornetQ versions. + * + * The integration tests pom will use the artemis-maven-plugin/dependency-scan to lookup for specific verions. + * The tests will only work if the plugin was executed and the system property was filled, + * or if it was manually added within the IDE running for debug purposes. + */ + +package org.apache.activemq.artemis.tests.compatibility; \ No newline at end of file diff --git a/tests/pom.xml b/tests/pom.xml index 145bade547..a281b96ba5 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -126,6 +126,7 @@ timing-tests jms-tests integration-tests + compatibility-tests soak-tests stress-tests performance-tests diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/util/SpawnedVMSupport.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/util/SpawnedVMSupport.java index e66da2c96d..209fe1ef33 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/util/SpawnedVMSupport.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/util/SpawnedVMSupport.java @@ -90,10 +90,68 @@ public final class SpawnedVMSupport { final boolean logErrorOutput, final boolean useLogging, final String... args) throws Exception { - ProcessBuilder builder = new ProcessBuilder(); + return spawnVM(System.getProperty("java.class.path"), wordMatch, wordRunning, className, memoryArg1, memoryArg2, vmargs, logOutput, logErrorOutput, useLogging, args); + + } + + + public static Process spawnVM(String classPath, + String wordMatch, + Runnable wordRunning, + String className, + String memoryArg1, + String memoryArg2, + String[] vmargs, + boolean logOutput, + boolean logErrorOutput, + boolean useLogging, + String... args) throws IOException, ClassNotFoundException { + return spawnVM(classPath, wordMatch, wordRunning, className, memoryArg1,memoryArg2, vmargs, logOutput, logErrorOutput, useLogging, -1, args); + } + + /** + * + * @param classPath + * @param wordMatch + * @param wordRunning + * @param className + * @param memoryArg1 + * @param memoryArg2 + * @param vmargs + * @param logOutput + * @param logErrorOutput + * @param useLogging + * @param debugPort if <=0 it means no debug + * @param args + * @return + * @throws IOException + * @throws ClassNotFoundException + */ + public static Process spawnVM(String classPath, + String wordMatch, + Runnable wordRunning, + String className, + String memoryArg1, + String memoryArg2, + String[] vmargs, + boolean logOutput, + boolean logErrorOutput, + boolean useLogging, + long debugPort, + String... args) throws IOException, ClassNotFoundException { final String javaPath = Paths.get(System.getProperty("java.home"), "bin", "java").toAbsolutePath().toString(); + ProcessBuilder builder = new ProcessBuilder(); + if (memoryArg1 == null) { + memoryArg1 = "-Xms128m"; + } + if (memoryArg2 == null) { + memoryArg2 = "-Xmx128m"; + } builder.command(javaPath, memoryArg1, memoryArg2); - builder.environment().put("CLASSPATH", System.getProperty("java.class.path")); + if (debugPort > 0) { + builder.command().add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + debugPort); + } + builder.environment().put("CLASSPATH", classPath); List commandList = builder.command(); @@ -143,7 +201,6 @@ public final class SpawnedVMSupport { errorLogger.start(); return process; - } /**