Skip to content

Commit

Permalink
Merge pull request #31589 from Ladicek/arc-tck
Browse files Browse the repository at this point in the history
ArC TCKs
  • Loading branch information
Ladicek authored Mar 8, 2023
2 parents df7ca37 + 603ecfa commit a2463b3
Show file tree
Hide file tree
Showing 34 changed files with 2,292 additions and 6 deletions.
48 changes: 48 additions & 0 deletions independent-projects/arc/arquillian/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.quarkus.arc</groupId>
<artifactId>arc-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>arc-arquillian</artifactId>
<name>ArC - Arquillian Container</name>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>${version.arquillian}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.quarkus.arc</groupId>
<artifactId>arc-processor</artifactId>
</dependency>

<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-container-spi</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-container-test-spi</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-container-test-impl-base</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.quarkus.arc.arquillian;

import org.jboss.arquillian.container.spi.ConfigurationException;
import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;

public class ArcContainerConfiguration implements ContainerConfiguration {
@Override
public void validate() throws ConfigurationException {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package io.quarkus.arc.arquillian;

import java.io.File;
import java.io.IOException;

import jakarta.enterprise.event.Shutdown;
import jakarta.enterprise.event.Startup;

import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.container.spi.client.container.DeploymentException;
import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription;
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
import org.jboss.arquillian.container.spi.context.annotation.DeploymentScoped;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.test.spi.TestClass;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.descriptor.api.Descriptor;

import io.quarkus.arc.Arc;
import io.quarkus.arc.ArcContainer;
import io.quarkus.arc.InjectableInstance;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.arc.arquillian.utils.ClassLoading;
import io.quarkus.arc.arquillian.utils.Directories;

public class ArcDeployableContainer implements DeployableContainer<ArcContainerConfiguration> {
@Inject
@DeploymentScoped
private InstanceProducer<DeploymentDir> deploymentDir;

@Inject
@DeploymentScoped
private InstanceProducer<DeploymentClassLoader> deploymentClassLoader;

@Inject
@DeploymentScoped
private InstanceProducer<ArcContainer> runningArc;

@Inject
private Instance<TestClass> testClass;

static Object testInstance;

@Override
public Class<ArcContainerConfiguration> getConfigurationClass() {
return ArcContainerConfiguration.class;
}

@Override
public void setup(ArcContainerConfiguration configuration) {
}

@Override
public ProtocolDescription getDefaultProtocol() {
return new ProtocolDescription("ArC");
}

@Override
public ProtocolMetaData deploy(Archive<?> archive) throws DeploymentException {
if (System.getProperty("saveArchive") != null) {
File file = new File(archive.getName());
archive.as(ZipExporter.class).exportTo(file);
System.out.println("Archive for test " + testClass.get().getName() + " saved in: " + file.getAbsolutePath());
}

if (testClass.get() == null) {
throw new IllegalStateException("Test class not available");
}
String testClassName = testClass.get().getName();

ClassLoader old = Thread.currentThread().getContextClassLoader();
try {
DeploymentDir deploymentDir = new DeploymentDir();
this.deploymentDir.set(deploymentDir);

DeploymentClassLoader deploymentClassLoader = new Deployer(archive, deploymentDir, testClassName).deploy();
this.deploymentClassLoader.set(deploymentClassLoader);

Thread.currentThread().setContextClassLoader(deploymentClassLoader);

ArcContainer arcContainer = Arc.initialize();
runningArc.set(arcContainer);
arcContainer.beanManager().getEvent().fire(new Startup());

Class<?> actualTestClass = Class.forName(testClassName, true, deploymentClassLoader);
testInstance = findTest(arcContainer, actualTestClass);
} catch (Throwable t) {
// clone the exception into the correct class loader
Throwable nt = ClassLoading.cloneExceptionIntoSystemCL(t);
throw new DeploymentException("Unable to start ArC", nt);
} finally {
Thread.currentThread().setContextClassLoader(old);
}

return new ProtocolMetaData();
}

private Object findTest(ArcContainer arc, Class<?> testClass) {
InjectableInstance<?> instance = arc.select(testClass);
if (instance.isResolvable()) {
return instance.get();
}

// fallback for generic test classes, whose set of bean types does not contain a `Class`
// but a `ParameterizedType` instead
for (InstanceHandle<Object> handle : arc.listAll(Object.class)) {
if (testClass.equals(handle.getBean().getBeanClass())) {
return handle.get();
}
}

throw new IllegalStateException("No bean: " + testClass);
}

@Override
public void undeploy(Archive<?> archive) throws DeploymentException {
ClassLoader old = Thread.currentThread().getContextClassLoader();
try {
DeploymentClassLoader deploymentClassLoader = this.deploymentClassLoader.get();

ArcContainer arcContainer = runningArc.get();
if (arcContainer != null) {
Thread.currentThread().setContextClassLoader(deploymentClassLoader);
arcContainer.beanManager().getEvent().fire(new Shutdown());
Arc.shutdown();
}
testInstance = null;

try {
deploymentClassLoader.close();
} catch (IOException e) {
throw new DeploymentException("Failed to close deployment classloader", e);
}

DeploymentDir deploymentDir = this.deploymentDir.get();
if (deploymentDir != null) {
if (System.getProperty("retainDeployment") == null) {
Directories.deleteDirectory(deploymentDir.root);
} else {
System.out.println("Deployment for test " + testClass.get().getName()
+ " retained in: " + deploymentDir.root);
}
}
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}

@Override
public void deploy(Descriptor descriptor) {
throw new UnsupportedOperationException();

}

@Override
public void undeploy(Descriptor descriptor) {
throw new UnsupportedOperationException();

}

@Override
public void start() {
}

@Override
public void stop() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.arc.arquillian;

import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.container.test.spi.client.protocol.Protocol;
import org.jboss.arquillian.core.spi.LoadableExtension;

import io.quarkus.arc.arquillian.utils.Hacks;

public class ArcExtension implements LoadableExtension {
// this is called early enough
static {
Hacks.preventFileHandleLeaks();
}

@Override
public void register(ExtensionBuilder builder) {
builder.service(DeployableContainer.class, ArcDeployableContainer.class);
builder.service(Protocol.class, ArcProtocol.class);
}
}
Loading

0 comments on commit a2463b3

Please sign in to comment.