/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS 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.integration.karaf;
import javax.inject.Inject;
import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.security.auth.Subject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import org.apache.karaf.jaas.boot.principal.RolePrincipal;
import org.apache.karaf.jaas.boot.principal.UserPrincipal;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.api.console.SessionFactory;
import org.apache.log4j.Logger;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
import org.ops4j.pax.exam.karaf.options.LogLevelOption;
import org.ops4j.pax.exam.options.UrlReference;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.util.tracker.ServiceTracker;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
// uncomment this to be able to debug it
// import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
/**
* Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
*/
@RunWith(PaxExam.class)
public class ArtemisFeatureTest extends Assert {
private static Logger LOG = Logger.getLogger(ArtemisFeatureTest.class.getName());
@Inject
BundleContext bundleContext;
@Inject
SessionFactory sessionFactory;
ExecutorService executor = Executors.newCachedThreadPool();
public static final long ASSERTION_TIMEOUT = 30000L;
public static final long COMMAND_TIMEOUT = 30000L;
public static final String USER = "karaf";
public static final String PASSWORD = "karaf";
@ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*,org.ops4j.pax.exam.options.*,org.apache.felix.service.*;status=provisional");
return probe;
}
@Configuration
public static Option[] configure() {
return configure("artemis");
}
public static Option[] configure(String... features) {
ArrayList<String> f = new ArrayList<>();
f.addAll(Arrays.asList(features));
Option[] options = new Option[]{karafDistributionConfiguration().frameworkUrl(maven().groupId("org.apache.karaf").artifactId("apache-karaf").type("tar.gz").versionAsInProject()).unpackDirectory(new File("target/paxexam/unpack/")),
KarafDistributionOption.keepRuntimeFolder(), logLevel(LogLevelOption.LogLevel.INFO), editConfigurationFilePut("etc/config.properties", "karaf.startlevel.bundle", "50"),
// uncomment this to debug it.
// debugConfiguration("5005", true),
features(getArtemisMQKarafFeatureUrl(), f.toArray(new String[f.size()]))};
return options;
}
public static UrlReference getArtemisMQKarafFeatureUrl() {
String type = "xml/features";
UrlReference urlReference = mavenBundle().groupId("org.apache.activemq").
artifactId("artemis-features").versionAsInProject().type(type);
LOG.info("FeatureURL: " + urlReference.getURL());
return urlReference;
}
@Test(timeout = 5 * 60 * 1000)
public void test() throws Throwable {
executeCommand("bundle:list");
withinReason(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
assertTrue("artemis bundle installed", verifyBundleInstalled("artemis-server-osgi"));
return true;
}
});
Object service = waitForService("(objectClass=org.apache.activemq.artemis.core.server.ActiveMQServer)", 30000);
assertNotNull(service);
LOG.info("have service " + service);
executeCommand("service:list -n");
Connection connection = null;
try {
JmsConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:5672");
connection = factory.createConnection(USER, PASSWORD);
connection.start();
javax.jms.Session sess = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
Queue queue = sess.createQueue("exampleQueue");
MessageProducer producer = sess.createProducer(queue);
producer.send(sess.createTextMessage("TEST"));
MessageConsumer consumer = sess.createConsumer(queue);
Message msg = consumer.receive(5000);
assertNotNull(msg);
} finally {
if (connection != null) {
connection.close();
}
}
}
protected String executeCommand(final String command, final Long timeout, final Boolean silent) {
String response;
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final PrintStream printStream = new PrintStream(byteArrayOutputStream);
final Session commandSession = sessionFactory.create(System.in, printStream, printStream);
commandSession.put("APPLICATION", System.getProperty("karaf.name", "root"));
commandSession.put("USER", USER);
FutureTask<String> commandFuture = new FutureTask<>(new Callable<String>() {
@Override
public String call() {
Subject subject = new Subject();
subject.getPrincipals().add(new UserPrincipal("admin"));
subject.getPrincipals().add(new RolePrincipal("admin"));
subject.getPrincipals().add(new RolePrincipal("manager"));
subject.getPrincipals().add(new RolePrincipal("viewer"));
return Subject.doAs(subject, new PrivilegedAction<String>() {
@Override
public String run() {
try {
if (!silent) {
System.out.println(command);
System.out.flush();
}
commandSession.execute(command);
} catch (Exception e) {
e.printStackTrace(System.err);
}
printStream.flush();
return byteArrayOutputStream.toString();
}
});
}
});
try {
executor.submit(commandFuture);
response = commandFuture.get(timeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace(System.err);
response = "SHELL COMMAND TIMED OUT: ";
}
LOG.info("Execute: " + command + " - Response:" + response);
return response;
}
protected String executeCommand(final String command) {
return executeCommand(command, COMMAND_TIMEOUT, false);
}
protected boolean withinReason(Callable<Boolean> callable) throws Throwable {
long max = System.currentTimeMillis() + ASSERTION_TIMEOUT;
while (true) {
try {
return callable.call();
} catch (Throwable t) {
if (System.currentTimeMillis() < max) {
TimeUnit.SECONDS.sleep(1);
continue;
} else {
throw t;
}
}
}
}
public boolean verifyBundleInstalled(final String bundleName) throws Exception {
boolean found = false;
for (Bundle bundle : bundleContext.getBundles()) {
LOG.debug("Checking: " + bundle.getSymbolicName());
if (bundle.getSymbolicName().contains(bundleName)) {
found = true;
break;
}
}
return found;
}
protected Object waitForService(String filter, long timeout) throws InvalidSyntaxException, InterruptedException {
ServiceTracker<Object, Object> st = new ServiceTracker<>(bundleContext, bundleContext.createFilter(filter), null);
try {
st.open();
return st.waitForService(timeout);
} finally {
st.close();
}
}
}