diff --git a/tests/integration-tests-utils/pom.xml b/tests/integration-tests-utils/pom.xml index 3593ec50746..ca3608a6315 100644 --- a/tests/integration-tests-utils/pom.xml +++ b/tests/integration-tests-utils/pom.xml @@ -34,6 +34,7 @@ Apache BookKeeper :: Tests :: Utility module for Arquillian based integration tests + 3.0.1 1.13.0 1.15 @@ -45,6 +46,17 @@ ${commons-compress.version} + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven + ${shrinkwrap.version} + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-api + ${shrinkwrap.version} + + org.apache.zookeeper zookeeper @@ -81,4 +93,20 @@ + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + 0 + + + + + diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/MavenClassLoader.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/MavenClassLoader.java new file mode 100644 index 00000000000..6f31f5c7665 --- /dev/null +++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/MavenClassLoader.java @@ -0,0 +1,117 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.bookkeeper.tests; + +import com.google.common.collect.Lists; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.jboss.shrinkwrap.resolver.api.maven.ScopeType; +import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencies; +import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependency; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MavenClassLoader implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(MavenClassLoader.class); + + private MavenClassLoader(URLClassLoader cl) { + this.classloader = cl; + } + + private final URLClassLoader classloader; + + public static MavenClassLoader forArtifact(String mainArtifact) throws Exception { + Optional slf4jVersion = Arrays.stream(Maven.resolver().resolve(mainArtifact) + .withTransitivity().asResolvedArtifact()) + .filter((a) -> a.getCoordinate().getGroupId().equals("org.slf4j") + && a.getCoordinate().getArtifactId().equals("slf4j-log4j12")) + .map((a) -> a.getCoordinate().getVersion()) + .findFirst(); + + List deps = Lists.newArrayList( + MavenDependencies.createDependency( + mainArtifact, ScopeType.COMPILE, false, + MavenDependencies.createExclusion("org.slf4j:slf4j-log4j12"), + MavenDependencies.createExclusion("log4j:log4j"))); + if (slf4jVersion.isPresent()) { + deps.add(MavenDependencies.createDependency("org.slf4j:slf4j-simple:" + slf4jVersion.get(), + ScopeType.COMPILE, false)); + } + + File[] files = Maven.resolver().addDependencies(deps.toArray(new MavenDependency[0])) + .resolve().withTransitivity().asFile(); + URLClassLoader cl = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public URLClassLoader run() { + return new URLClassLoader(Arrays.stream(files) + .map((f) -> { + try { + return f.toURI().toURL(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + }) + .toArray(URL[]::new), + ClassLoader.getSystemClassLoader()); + } + }); + return new MavenClassLoader(cl); + } + + public static MavenClassLoader forBookKeeperVersion(String version) throws Exception { + return forArtifact("org.apache.bookkeeper:bookkeeper-server:" + version); + } + + public Object newInstance(String className, Object... args) throws Exception { + Class klass = Class.forName(className, true, classloader); + return klass.getConstructor(Arrays.stream(args).map((a)-> a.getClass()).toArray(Class[]::new)) + .newInstance(args); + } + + public Object newBookKeeper(String zookeeper) throws Exception { + return newInstance("org.apache.bookkeeper.client.BookKeeper", zookeeper); + } + + public Object digestType(String type) throws Exception { + String className = "org.apache.bookkeeper.client.BookKeeper$DigestType"; + for (Object o : classloader.loadClass(className).getEnumConstants()) { + if (o.toString().equals(type)) { + return o; + } + } + throw new ClassNotFoundException("No such digest type " + type); + } + + public void close() throws Exception { + classloader.close(); + } +} diff --git a/tests/integration-tests-utils/src/test/java/org/apache/bookkeeper/tests/MavenClassLoaderTest.java b/tests/integration-tests-utils/src/test/java/org/apache/bookkeeper/tests/MavenClassLoaderTest.java new file mode 100644 index 00000000000..930355787e2 --- /dev/null +++ b/tests/integration-tests-utils/src/test/java/org/apache/bookkeeper/tests/MavenClassLoaderTest.java @@ -0,0 +1,42 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.bookkeeper.tests; + +import org.junit.Assert; +import org.junit.Test; + +public class MavenClassLoaderTest { + @Test(expected=ClassNotFoundException.class) + public void testLog4JReplacement() throws Exception { + MavenClassLoader.forBookKeeperVersion("4.0.0") + .newInstance("org.apache.log4j.Logger"); + } + + @Test + public void testNoZooKeeperInterference() throws Exception { + // Use KeeperException, because ZooKeeper needs a watcher which would be a pain to construct + Object o = MavenClassLoader.forBookKeeperVersion("4.0.0") + .newInstance("org.apache.zookeeper.KeeperException$NoNodeException"); + Assert.assertFalse(o.getClass().equals( + org.apache.zookeeper.KeeperException.NoNodeException.class)); + } + +}