All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.arquillian.testcontainers.TestContainersObserver Maven / Gradle / Ivy

/*
 * Copyright The Arquillian Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package org.jboss.arquillian.testcontainers;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.jboss.arquillian.container.spi.ContainerRegistry;
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.core.api.annotation.Observes;
import org.jboss.arquillian.test.spi.TestClass;
import org.jboss.arquillian.test.spi.annotation.ClassScoped;
import org.jboss.arquillian.test.spi.event.enrichment.AfterEnrichment;
import org.jboss.arquillian.test.spi.event.suite.AfterClass;
import org.jboss.arquillian.test.spi.event.suite.BeforeClass;
import org.jboss.arquillian.testcontainers.api.DockerRequired;
import org.testcontainers.DockerClientFactory;

@SuppressWarnings("unused")
class TestContainersObserver {
    @Inject
    @ClassScoped
    private InstanceProducer containerRegistry;

    @Inject
    private Instance registry;

    /**
     * This first checks if the {@link DockerRequired} annotation is present on the test class failing if necessary. It
     * then creates the {@link TestcontainerRegistry} and stores it in a {@link ClassScoped} instance.
     *
     * @param beforeClass the before class event
     *
     * @throws Throwable if an error occurs
     */
    public void createContainer(@Observes(precedence = 500) BeforeClass beforeClass) throws Throwable {
        final TestClass javaClass = beforeClass.getTestClass();
        final DockerRequired dockerRequired = javaClass.getAnnotation(DockerRequired.class);
        if (dockerRequired != null) {
            if (!isDockerAvailable()) {
                throw createException(dockerRequired.value());
            }
        }
        final TestcontainerRegistry instances = new TestcontainerRegistry();
        containerRegistry.set(instances);
    }

    /**
     * Stops all containers, even ones not managed via Arquillian, after the test is complete
     *
     * @param afterClass the after class event
     */
    public void stopContainer(@Observes AfterClass afterClass) {
        TestcontainerRegistry registry = containerRegistry.get();
        if (registry != null) {
            for (TestcontainerDescription container : registry) {
                container.instance.stop();
            }
        }
    }

    /**
     * Starts all containers after enrichment is done. This happens after the {@link ContainerInjectionTestEnricher} is
     * invoked.
     *
     * @param event the after enrichment event
     */
    public void startContainer(@Observes(precedence = 500) final AfterEnrichment event) {
        TestcontainerRegistry registry = containerRegistry.get();
        if (registry != null) {
            // Look for the servers to start on fields only
            for (TestcontainerDescription description : registry) {
                if (description.testcontainer.value()) {
                    description.instance.start();
                }
            }
        }
    }

    @SuppressWarnings({ "resource", "BooleanMethodIsAlwaysInverted" })
    private boolean isDockerAvailable() {
        try {
            DockerClientFactory.instance().client();
            return true;
        } catch (Throwable ex) {
            return false;
        }
    }

    private static Throwable createException(final Class value) {
        // First try the String.class constructor
        try {
            final Constructor constructor = value.getConstructor(String.class);
            return constructor.newInstance("No Docker environment is available.");
        } catch (NoSuchMethodException ignore) {
            try {
                final Constructor constructor = value.getConstructor();
                return constructor.newInstance();
            } catch (NoSuchMethodException unused) {
                throw new AssertionError(String.format("No String or no-arg constructor found for %s", value));
            } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
                throw new AssertionError(String.format("Failed to create exception for type %s", value), e);
            }
        } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
            throw new AssertionError(String.format("Failed to create exception for type %s", value), e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy