Search in sources :

Example 1 with AugmentAction

use of io.quarkus.bootstrap.app.AugmentAction in project quarkus by quarkusio.

the class QuarkusDeployableContainer method deploy.

@SuppressWarnings("rawtypes")
@Override
public ProtocolMetaData deploy(Archive<?> archive) throws DeploymentException {
    old = Thread.currentThread().getContextClassLoader();
    if (testClass.get() == null) {
        throw new IllegalStateException("Test class not available");
    }
    Class testJavaClass = testClass.get().getJavaClass();
    // some TCK tests embed random libraries such as old versions of Jackson databind
    // this breaks quarkus, so we just skip them
    boolean skipLibraries = Boolean.getBoolean("io.quarkus.arquillian.skip-libraries");
    try {
        // Export the test archive
        Path tmpLocation = Files.createTempDirectory("quarkus-arquillian-test");
        deploymentLocation.set(tmpLocation);
        archive.as(ExplodedExporter.class).exportExplodedInto(tmpLocation.toFile());
        Path appLocation;
        Set<Path> libraries = new HashSet<>();
        if (archive instanceof WebArchive) {
            // Quarkus does not support the WAR layout and so adapt the layout (similarly to quarkus-war-launcher)
            appLocation = tmpLocation.resolve("app").toAbsolutePath();
            // WEB-INF/lib -> lib/
            if (!skipLibraries) {
                if (Files.exists(tmpLocation.resolve("WEB-INF/lib"))) {
                    Files.move(tmpLocation.resolve("WEB-INF/lib"), tmpLocation.resolve("lib"));
                }
            }
            // WEB-INF/classes -> archive/
            if (Files.exists(tmpLocation.resolve("WEB-INF/classes"))) {
                Files.move(tmpLocation.resolve("WEB-INF/classes"), appLocation);
            } else {
                Files.createDirectory(appLocation);
            }
            // META-INF -> archive/META-INF/
            if (Files.exists(tmpLocation.resolve("META-INF"))) {
                if (Files.exists(appLocation.resolve("META-INF"))) {
                    // Target directory not empty.
                    try (Stream<Path> fileTreeElements = Files.walk(tmpLocation.resolve("META-INF"), 2)) {
                        fileTreeElements.forEach(p -> {
                            try {
                                Files.createFile(p);
                            } catch (FileAlreadyExistsException faee) {
                            // Do Nothing
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        });
                    }
                } else {
                    Files.move(tmpLocation.resolve("META-INF"), appLocation.resolve("META-INF"));
                }
            }
            // WEB-INF -> archive/WEB-INF
            if (Files.exists(tmpLocation.resolve("WEB-INF"))) {
                Files.move(tmpLocation.resolve("WEB-INF"), appLocation.resolve("WEB-INF"));
            }
            // Collect all libraries
            if (Files.exists(tmpLocation.resolve("lib"))) {
                try (Stream<Path> libs = Files.walk(tmpLocation.resolve("lib"), 1)) {
                    libs.forEach((i) -> {
                        if (i.getFileName().toString().endsWith(".jar")) {
                            libraries.add(i);
                        }
                    });
                }
            }
        } else {
            appLocation = tmpLocation;
        }
        List<Consumer<BuildChainBuilder>> customizers = new ArrayList<>();
        // Test class is a bean
        customizers.add(new Consumer<BuildChainBuilder>() {

            @Override
            public void accept(BuildChainBuilder buildChainBuilder) {
                buildChainBuilder.addBuildStep(new BuildStep() {

                    @Override
                    public void execute(BuildContext context) {
                        context.produce(AdditionalBeanBuildItem.unremovableOf(testJavaClass));
                    }
                }).produces(AdditionalBeanBuildItem.class).build();
            }
        });
        QuarkusBootstrap.Builder bootstrapBuilder = QuarkusBootstrap.builder().setApplicationRoot(appLocation).setProjectRoot(appLocation).setIsolateDeployment(false).setFlatClassPath(true).setMode(QuarkusBootstrap.Mode.TEST);
        for (Path i : libraries) {
            bootstrapBuilder.addAdditionalApplicationArchive(new AdditionalDependency(i, false, true));
        }
        // Path testLocation = PathTestHelper.getTestClassesLocation(testJavaClass);
        // bootstrapBuilder.setProjectRoot(PathTestHelper.getTestClassesLocation(testJavaClass));
        CuratedApplication curatedApplication = bootstrapBuilder.build().bootstrap();
        AugmentAction augmentAction = new AugmentActionImpl(curatedApplication, customizers);
        StartupAction app = augmentAction.createInitialRuntimeApplication();
        RunningQuarkusApplication runningQuarkusApplication = app.run();
        appClassloader.set(runningQuarkusApplication.getClassLoader());
        runningApp.set(runningQuarkusApplication);
        Thread.currentThread().setContextClassLoader(runningQuarkusApplication.getClassLoader());
        // Instantiate the real test instance
        testInstance = TestInstantiator.instantiateTest(testJavaClass, runningQuarkusApplication.getClassLoader());
        // its pretty bogus
        if (Boolean.getBoolean("io.quarkus.arquillian.copy-fields")) {
            Class<?> dest = testInstance.getClass();
            Class<?> source = testClass.get().getJavaClass();
            while (source != Object.class) {
                for (Field f : source.getDeclaredFields()) {
                    try {
                        if (Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers())) {
                            Field df = dest.getDeclaredField(f.getName());
                            df.setAccessible(true);
                            f.setAccessible(true);
                            df.set(null, f.get(null));
                        }
                    } catch (Exception e) {
                        LOGGER.error("Failed to copy static field", e);
                    }
                }
                source = source.getSuperclass();
                dest = dest.getSuperclass();
            }
        }
    } catch (Throwable t) {
        // clone the exception into the correct class loader
        Throwable nt;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (ObjectOutputStream a = new ObjectOutputStream(out)) {
            a.writeObject(t);
            a.close();
            nt = (Throwable) new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())).readObject();
        } catch (Exception e) {
            throw new DeploymentException("Unable to start the runtime runner", t);
        }
        throw new DeploymentException("Unable to start the runtime runner", nt);
    } finally {
        Thread.currentThread().setContextClassLoader(old);
    }
    ProtocolMetaData metadata = new ProtocolMetaData();
    // TODO: fix this
    String testUri = TestHTTPResourceManager.getUri(runningApp.get());
    System.setProperty("test.url", testUri);
    URI uri = URI.create(testUri);
    HTTPContext httpContext = new HTTPContext(uri.getHost(), uri.getPort());
    // This is to work around https://github.com/arquillian/arquillian-core/issues/216
    httpContext.add(new Servlet("dummy", "/"));
    metadata.addContext(httpContext);
    return metadata;
}
Also used : FileAlreadyExistsException(java.nio.file.FileAlreadyExistsException) ArrayList(java.util.ArrayList) BuildStep(io.quarkus.builder.BuildStep) ObjectOutputStream(java.io.ObjectOutputStream) URI(java.net.URI) Field(java.lang.reflect.Field) Consumer(java.util.function.Consumer) Servlet(org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet) AdditionalDependency(io.quarkus.bootstrap.app.AdditionalDependency) ProtocolMetaData(org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData) ExplodedExporter(org.jboss.shrinkwrap.api.exporter.ExplodedExporter) HashSet(java.util.HashSet) AugmentActionImpl(io.quarkus.runner.bootstrap.AugmentActionImpl) Path(java.nio.file.Path) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) StartupAction(io.quarkus.bootstrap.app.StartupAction) RunningQuarkusApplication(io.quarkus.bootstrap.app.RunningQuarkusApplication) WebArchive(org.jboss.shrinkwrap.api.spec.WebArchive) HTTPContext(org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) LifecycleException(org.jboss.arquillian.container.spi.client.container.LifecycleException) IOException(java.io.IOException) FileAlreadyExistsException(java.nio.file.FileAlreadyExistsException) DeploymentException(org.jboss.arquillian.container.spi.client.container.DeploymentException) BuildContext(io.quarkus.builder.BuildContext) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) ByteArrayInputStream(java.io.ByteArrayInputStream) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) TestClass(org.jboss.arquillian.test.spi.TestClass) DeploymentException(org.jboss.arquillian.container.spi.client.container.DeploymentException) ObjectInputStream(java.io.ObjectInputStream)

Example 2 with AugmentAction

use of io.quarkus.bootstrap.app.AugmentAction in project quarkus by quarkusio.

the class QuarkusTestExtension method doJavaStart.

private ExtensionState doJavaStart(ExtensionContext context, Class<? extends QuarkusTestProfile> profile) throws Throwable {
    TracingHandler.quarkusStarting();
    hangDetectionExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "Quarkus hang detection timer thread");
        }
    });
    String time = "10m";
    // config is not established yet
    // we can only read from system properties
    String sysPropString = System.getProperty(QUARKUS_TEST_HANG_DETECTION_TIMEOUT);
    if (sysPropString != null) {
        time = sysPropString;
    }
    hangTimeout = new DurationConverter().convert(time);
    hangTaskKey = hangDetectionExecutor.schedule(hangDetectionTask, hangTimeout.toMillis(), TimeUnit.MILLISECONDS);
    quarkusTestProfile = profile;
    Class<?> requiredTestClass = context.getRequiredTestClass();
    Closeable testResourceManager = null;
    try {
        final LinkedBlockingDeque<Runnable> shutdownTasks = new LinkedBlockingDeque<>();
        PrepareResult result = createAugmentor(context, profile, shutdownTasks);
        AugmentAction augmentAction = result.augmentAction;
        QuarkusTestProfile profileInstance = result.profileInstance;
        testHttpEndpointProviders = TestHttpEndpointProvider.load();
        StartupAction startupAction = augmentAction.createInitialRuntimeApplication();
        Thread.currentThread().setContextClassLoader(startupAction.getClassLoader());
        populateDeepCloneField(startupAction);
        // must be done after the TCCL has been set
        testResourceManager = (Closeable) startupAction.getClassLoader().loadClass(TestResourceManager.class.getName()).getConstructor(Class.class, Class.class, List.class, boolean.class, Map.class, Optional.class).newInstance(requiredTestClass, profile != null ? profile : null, getAdditionalTestResources(profileInstance, startupAction.getClassLoader()), profileInstance != null && profileInstance.disableGlobalTestResources(), startupAction.getDevServicesProperties(), Optional.empty());
        testResourceManager.getClass().getMethod("init", String.class).invoke(testResourceManager, profile != null ? profile.getName() : null);
        Map<String, String> properties = (Map<String, String>) testResourceManager.getClass().getMethod("start").invoke(testResourceManager);
        startupAction.overrideConfig(properties);
        hasPerTestResources = (boolean) testResourceManager.getClass().getMethod("hasPerTestResources").invoke(testResourceManager);
        populateCallbacks(startupAction.getClassLoader());
        populateTestMethodInvokers(startupAction.getClassLoader());
        if (profileInstance == null || !profileInstance.runMainMethod()) {
            runningQuarkusApplication = startupAction.run(profileInstance == null ? new String[0] : profileInstance.commandLineParameters());
        } else {
            Class<?> lifecycleManager = Class.forName(ApplicationLifecycleManager.class.getName(), true, startupAction.getClassLoader());
            lifecycleManager.getDeclaredMethod("setDefaultExitCodeHandler", Consumer.class).invoke(null, (Consumer<Integer>) integer -> {
            });
            runningQuarkusApplication = startupAction.runMainClass(profileInstance.commandLineParameters());
        }
        String patternString = runningQuarkusApplication.getConfigValue("quarkus.test.class-clone-pattern", String.class).orElse("java\\..*");
        clonePattern = Pattern.compile(patternString);
        TracingHandler.quarkusStarted();
        if (hangTaskKey != null) {
            hangTaskKey.cancel(false);
            hangTimeout = runningQuarkusApplication.getConfigValue(QUARKUS_TEST_HANG_DETECTION_TIMEOUT, Duration.class).orElse(Duration.of(10, ChronoUnit.MINUTES));
            hangTaskKey = hangDetectionExecutor.schedule(hangDetectionTask, hangTimeout.toMillis(), TimeUnit.MILLISECONDS);
        }
        ConfigProviderResolver.setInstance(new RunningAppConfigResolver(runningQuarkusApplication));
        RestorableSystemProperties restorableSystemProperties = RestorableSystemProperties.setProperties(Collections.singletonMap("test.url", TestHTTPResourceManager.getUri(runningQuarkusApplication)));
        Closeable tm = testResourceManager;
        Closeable shutdownTask = new Closeable() {

            @Override
            public void close() throws IOException {
                TracingHandler.quarkusStopping();
                try {
                    runningQuarkusApplication.close();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    TracingHandler.quarkusStopped();
                    try {
                        while (!shutdownTasks.isEmpty()) {
                            shutdownTasks.pop().run();
                        }
                    } finally {
                        try {
                            tm.close();
                        } finally {
                            restorableSystemProperties.close();
                            GroovyCacheCleaner.clearGroovyCache();
                            shutdownHangDetection();
                        }
                    }
                    try {
                        TestClassIndexer.removeIndex(requiredTestClass);
                    } catch (Exception ignored) {
                    }
                }
            }
        };
        ExtensionState state = new ExtensionState(testResourceManager, shutdownTask);
        return state;
    } catch (Throwable e) {
        if (!InitialConfigurator.DELAYED_HANDLER.isActivated()) {
            activateLogging();
        }
        try {
            if (testResourceManager != null) {
                testResourceManager.close();
            }
        } catch (Exception ex) {
            e.addSuppressed(ex);
        }
        throw e;
    } finally {
        if (originalCl != null) {
            Thread.currentThread().setContextClassLoader(originalCl);
        }
    }
}
Also used : ApplicationLifecycleManager(io.quarkus.runtime.ApplicationLifecycleManager) RestAssuredURLManager(io.quarkus.test.common.RestAssuredURLManager) FieldInfo(org.jboss.jandex.FieldInfo) ApplicationLifecycleManager(io.quarkus.runtime.ApplicationLifecycleManager) ThreadInfo(java.lang.management.ThreadInfo) TestClassPredicateBuildItem(io.quarkus.deployment.builditem.TestClassPredicateBuildItem) Duration(java.time.Duration) Map(java.util.Map) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) QuarkusTestAfterEachCallback(io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback) InitialConfigurator(io.quarkus.bootstrap.logging.InitialConfigurator) Path(java.nio.file.Path) DurationConverter(io.quarkus.runtime.configuration.DurationConverter) TestAbortedException(org.opentest4j.TestAbortedException) TestHttpEndpointProvider(io.quarkus.runtime.test.TestHttpEndpointProvider) Set(java.util.Set) QuarkusClassLoader(io.quarkus.bootstrap.classloading.QuarkusClassLoader) Executors(java.util.concurrent.Executors) StartupAction(io.quarkus.bootstrap.app.StartupAction) InvocationTargetException(java.lang.reflect.InvocationTargetException) ReflectiveInvocationContext(org.junit.jupiter.api.extension.ReflectiveInvocationContext) BuildStep(io.quarkus.builder.BuildStep) TestClassBeanBuildItem(io.quarkus.deployment.builditem.TestClassBeanBuildItem) AnnotationInstance(org.jboss.jandex.AnnotationInstance) QuarkusTestMethodContext(io.quarkus.test.junit.callback.QuarkusTestMethodContext) PropertyTestUtil(io.quarkus.test.common.PropertyTestUtil) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ExtensionContext(org.junit.jupiter.api.extension.ExtensionContext) Constructor(java.lang.reflect.Constructor) Supplier(java.util.function.Supplier) Nested(org.junit.jupiter.api.Nested) RestorableSystemProperties(io.quarkus.test.common.RestorableSystemProperties) ArrayList(java.util.ArrayList) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) Parameter(java.lang.reflect.Parameter) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ManagementFactory(java.lang.management.ManagementFactory) IntegrationTestUtil.getAdditionalTestResources(io.quarkus.test.junit.IntegrationTestUtil.getAdditionalTestResources) ParameterResolutionException(org.junit.jupiter.api.extension.ParameterResolutionException) IOException(java.io.IOException) ParameterContext(org.junit.jupiter.api.extension.ParameterContext) ChronoUnit(java.time.temporal.ChronoUnit) BeforeAllCallback(org.junit.jupiter.api.extension.BeforeAllCallback) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) BeforeEachCallback(org.junit.jupiter.api.extension.BeforeEachCallback) TestResourceManager(io.quarkus.test.common.TestResourceManager) TestHTTPResourceManager(io.quarkus.test.common.http.TestHTTPResourceManager) QuarkusTestContext(io.quarkus.test.junit.callback.QuarkusTestContext) TestHTTPEndpoint(io.quarkus.test.common.http.TestHTTPEndpoint) ScheduledFuture(java.util.concurrent.ScheduledFuture) QuarkusTestBeforeEachCallback(io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback) QuarkusTestBeforeClassCallback(io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback) ClassInfo(org.jboss.jandex.ClassInfo) DeepClone(io.quarkus.test.junit.internal.DeepClone) ConfigProviderResolver(org.eclipse.microprofile.config.spi.ConfigProviderResolver) AfterEachCallback(org.junit.jupiter.api.extension.AfterEachCallback) Locale(java.util.Locale) AnnotationTarget(org.jboss.jandex.AnnotationTarget) ThreadFactory(java.util.concurrent.ThreadFactory) Method(java.lang.reflect.Method) GroovyCacheCleaner(io.quarkus.test.common.GroovyCacheCleaner) Predicate(java.util.function.Predicate) ServiceLoader(java.util.ServiceLoader) TestInfo(org.junit.jupiter.api.TestInfo) Objects(java.util.Objects) List(java.util.List) TestBuildChainCustomizerProducer(io.quarkus.test.junit.buildchain.TestBuildChainCustomizerProducer) BuildContext(io.quarkus.builder.BuildContext) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) TestScopeManager(io.quarkus.test.common.TestScopeManager) PathTestHelper(io.quarkus.test.common.PathTestHelper) TestClassIndexer(io.quarkus.test.common.TestClassIndexer) RunningQuarkusApplication(io.quarkus.bootstrap.app.RunningQuarkusApplication) TestAnnotationBuildItem(io.quarkus.deployment.builditem.TestAnnotationBuildItem) Logger(org.jboss.logging.Logger) Type(org.jboss.jandex.Type) TracingHandler(io.quarkus.dev.testing.TracingHandler) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) LaunchMode(io.quarkus.runtime.LaunchMode) HashMap(java.util.HashMap) IntegrationTestUtil.activateLogging(io.quarkus.test.junit.IntegrationTestUtil.activateLogging) Function(java.util.function.Function) QuarkusTestAfterAllCallback(io.quarkus.test.junit.callback.QuarkusTestAfterAllCallback) QuarkusTestAfterConstructCallback(io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) TestMethodInvoker(io.quarkus.test.TestMethodInvoker) ApplicationClassPredicateBuildItem(io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem) Index(org.jboss.jandex.Index) ClassPathElement(io.quarkus.bootstrap.classloading.ClassPathElement) InvocationInterceptor(org.junit.jupiter.api.extension.InvocationInterceptor) TestInstantiationException(org.junit.jupiter.api.extension.TestInstantiationException) SerializationWithXStreamFallbackDeepClone(io.quarkus.test.junit.internal.SerializationWithXStreamFallbackDeepClone) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) AbstractMap(java.util.AbstractMap) ConditionEvaluationResult(org.junit.jupiter.api.extension.ConditionEvaluationResult) ExecutionCondition(org.junit.jupiter.api.extension.ExecutionCondition) AfterAllCallback(org.junit.jupiter.api.extension.AfterAllCallback) ExceptionReporting(io.quarkus.dev.testing.ExceptionReporting) Closeable(java.io.Closeable) ProfileManager(io.quarkus.runtime.configuration.ProfileManager) Collections(java.util.Collections) ParameterResolver(org.junit.jupiter.api.extension.ParameterResolver) ThreadFactory(java.util.concurrent.ThreadFactory) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Closeable(java.io.Closeable) Consumer(java.util.function.Consumer) DurationConverter(io.quarkus.runtime.configuration.DurationConverter) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) List(java.util.List) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) StartupAction(io.quarkus.bootstrap.app.StartupAction) Optional(java.util.Optional) TestAbortedException(org.opentest4j.TestAbortedException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ParameterResolutionException(org.junit.jupiter.api.extension.ParameterResolutionException) IOException(java.io.IOException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) TestInstantiationException(org.junit.jupiter.api.extension.TestInstantiationException) RestorableSystemProperties(io.quarkus.test.common.RestorableSystemProperties) Map(java.util.Map) HashMap(java.util.HashMap) AbstractMap(java.util.AbstractMap) TestResourceManager(io.quarkus.test.common.TestResourceManager)

Example 3 with AugmentAction

use of io.quarkus.bootstrap.app.AugmentAction in project quarkus by quarkusio.

the class IntegrationTestUtil method handleDevServices.

static ArtifactLauncher.InitContext.DevServicesLaunchResult handleDevServices(ExtensionContext context, boolean isDockerAppLaunch) throws Exception {
    Class<?> requiredTestClass = context.getRequiredTestClass();
    Path testClassLocation = getTestClassesLocation(requiredTestClass);
    final Path appClassLocation = getAppClassLocationForTestLocation(testClassLocation.toString());
    final PathList.Builder rootBuilder = PathList.builder();
    if (!appClassLocation.equals(testClassLocation)) {
        rootBuilder.add(testClassLocation);
        // if test classes is a dir, we should also check whether test resources dir exists as a separate dir (gradle)
        // TODO: this whole app/test path resolution logic is pretty dumb, it needs be re-worked using proper workspace discovery
        final Path testResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(testClassLocation, "test");
        if (testResourcesLocation != null) {
            rootBuilder.add(testResourcesLocation);
        }
    }
    final QuarkusBootstrap.Builder runnerBuilder = QuarkusBootstrap.builder().setIsolateDeployment(true).setMode(QuarkusBootstrap.Mode.TEST);
    final Path projectRoot = Paths.get("").normalize().toAbsolutePath();
    runnerBuilder.setProjectRoot(projectRoot);
    runnerBuilder.setTargetDirectory(PathTestHelper.getProjectBuildDir(projectRoot, testClassLocation));
    rootBuilder.add(appClassLocation);
    final Path appResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(appClassLocation, "main");
    if (appResourcesLocation != null) {
        rootBuilder.add(appResourcesLocation);
    }
    // If gradle project running directly with IDE
    if (System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL) == null) {
        ApplicationModel model = BuildToolHelper.enableGradleAppModelForTest(projectRoot);
        if (model != null && model.getApplicationModule() != null) {
            final ArtifactSources testSources = model.getApplicationModule().getTestSources();
            if (testSources != null) {
                for (SourceDir src : testSources.getSourceDirs()) {
                    if (!Files.exists(src.getOutputDir())) {
                        final Path classes = src.getOutputDir();
                        if (!rootBuilder.contains(classes)) {
                            rootBuilder.add(classes);
                        }
                    }
                }
            }
            for (SourceDir src : model.getApplicationModule().getMainSources().getSourceDirs()) {
                if (!Files.exists(src.getOutputDir())) {
                    final Path classes = src.getOutputDir();
                    if (!rootBuilder.contains(classes)) {
                        rootBuilder.add(classes);
                    }
                }
            }
        }
    } else if (System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR) != null) {
        final String[] sourceDirectories = System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR).split(",");
        for (String sourceDirectory : sourceDirectories) {
            final Path directory = Paths.get(sourceDirectory);
            if (Files.exists(directory) && !rootBuilder.contains(directory)) {
                rootBuilder.add(directory);
            }
        }
    }
    runnerBuilder.setApplicationRoot(rootBuilder.build());
    CuratedApplication curatedApplication = runnerBuilder.setTest(true).build().bootstrap();
    Index testClassesIndex = TestClassIndexer.indexTestClasses(requiredTestClass);
    // we need to write the Index to make it reusable from other parts of the testing infrastructure that run in different ClassLoaders
    TestClassIndexer.writeIndex(testClassesIndex, requiredTestClass);
    Map<String, String> propertyMap = new HashMap<>();
    AugmentAction augmentAction;
    String networkId = null;
    if (isDockerAppLaunch) {
        // when the application is going to be launched as a docker container, we need to make containers started by DevServices
        // use a shared network that the application container can then use as well
        augmentAction = curatedApplication.createAugmentor("io.quarkus.deployment.builditem.DevServicesSharedNetworkBuildItem$Factory", Collections.emptyMap());
    } else {
        augmentAction = curatedApplication.createAugmentor();
    }
    augmentAction.performCustomBuild(NativeDevServicesHandler.class.getName(), new BiConsumer<String, String>() {

        @Override
        public void accept(String s, String s2) {
            propertyMap.put(s, s2);
        }
    }, DevServicesLauncherConfigResultBuildItem.class.getName());
    boolean manageNetwork = false;
    if (isDockerAppLaunch) {
        // or else we run into various ClassLoader problems
        try {
            Class<?> networkClass = curatedApplication.getAugmentClassLoader().loadClass("org.testcontainers.containers.Network");
            Object sharedNetwork = networkClass.getField("SHARED").get(null);
            networkId = (String) networkClass.getMethod("getId").invoke(sharedNetwork);
        } catch (Exception e) {
            // use the network the use has specified or else just generate one if none is configured
            Config config = LauncherUtil.installAndGetSomeConfig();
            Optional<String> networkIdOpt = config.getOptionalValue("quarkus.test.container.network", String.class);
            if (networkIdOpt.isPresent()) {
                networkId = networkIdOpt.get();
            } else {
                networkId = "quarkus-integration-test-" + RandomStringUtils.random(5, true, false);
                manageNetwork = true;
            }
        }
    }
    DefaultDevServicesLaunchResult result = new DefaultDevServicesLaunchResult(propertyMap, networkId, manageNetwork, curatedApplication);
    createNetworkIfNecessary(result);
    return result;
}
Also used : DevServicesLauncherConfigResultBuildItem(io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem) HashMap(java.util.HashMap) Config(org.eclipse.microprofile.config.Config) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) Index(org.jboss.jandex.Index) Path(java.nio.file.Path) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) SourceDir(io.quarkus.bootstrap.workspace.SourceDir) Optional(java.util.Optional) PathList(io.quarkus.paths.PathList) URISyntaxException(java.net.URISyntaxException) JUnitException(org.junit.platform.commons.JUnitException) InvocationTargetException(java.lang.reflect.InvocationTargetException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) ArtifactSources(io.quarkus.bootstrap.workspace.ArtifactSources)

Example 4 with AugmentAction

use of io.quarkus.bootstrap.app.AugmentAction in project quarkus by quarkusio.

the class IsolatedDevModeMain method accept.

// the main entry point, but loaded inside the augmentation class loader
@Override
public void accept(CuratedApplication o, Map<String, Object> params) {
    // setup the dev mode thread pool for NIO
    System.setProperty("java.nio.channels.DefaultThreadPool.threadFactory", "io.quarkus.dev.io.NioThreadPoolThreadFactory");
    Timing.staticInitStarted(o.getBaseRuntimeClassLoader(), false);
    // https://github.com/quarkusio/quarkus/issues/9748
    // if you have an app with all daemon threads then the app thread
    // may be the only thread keeping the JVM alive
    // during the restart process when this thread is stopped then
    // the JVM will die
    // we start this thread to keep the JVM alive until the shutdown hook is run
    // even for command mode we still want the JVM to live until it receives
    // a signal to make the 'press enter to restart' function to work
    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                shutdownLatch.await();
            } catch (InterruptedException ignore) {
            }
        }
    }, "Quarkus Devmode keep alive thread").start();
    try {
        curatedApplication = o;
        Object potentialContext = params.get(DevModeContext.class.getName());
        if (potentialContext instanceof DevModeContext) {
            context = (DevModeContext) potentialContext;
        } else {
            // this was from the external class loader
            // we need to copy it into this one
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream oo = new ObjectOutputStream(out);
            oo.writeObject(potentialContext);
            context = (DevModeContext) new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())).readObject();
        }
        augmentAction = new AugmentActionImpl(curatedApplication, Collections.singletonList(new Consumer<BuildChainBuilder>() {

            @Override
            public void accept(BuildChainBuilder buildChainBuilder) {
                buildChainBuilder.addBuildStep(new BuildStep() {

                    @Override
                    public void execute(BuildContext context) {
                        // we need to make sure all hot reloadable classes are application classes
                        context.produce(new ApplicationClassPredicateBuildItem(new Predicate<String>() {

                            @Override
                            public boolean test(String s) {
                                QuarkusClassLoader cl = (QuarkusClassLoader) Thread.currentThread().getContextClassLoader();
                                // if the class file is present in this (and not the parent) CL then it is an application class
                                List<ClassPathElement> res = cl.getElementsWithResource(s.replace('.', '/') + ".class", true);
                                return !res.isEmpty();
                            }
                        }));
                    }
                }).produces(ApplicationClassPredicateBuildItem.class).build();
            }
        }), Collections.emptyList());
        List<CodeGenData> codeGens = new ArrayList<>();
        QuarkusClassLoader deploymentClassLoader = curatedApplication.createDeploymentClassLoader();
        for (DevModeContext.ModuleInfo module : context.getAllModules()) {
            if (!module.getSourceParents().isEmpty() && module.getPreBuildOutputDir() != null) {
                // it's null for remote dev
                codeGens.addAll(CodeGenerator.init(deploymentClassLoader, module.getSourceParents(), Paths.get(module.getPreBuildOutputDir()), Paths.get(module.getTargetDir()), sourcePath -> module.addSourcePathFirst(sourcePath.toAbsolutePath().toString())));
            }
        }
        RuntimeUpdatesProcessor.INSTANCE = setupRuntimeCompilation(context, (Path) params.get(APP_ROOT), (DevModeType) params.get(DevModeType.class.getName()));
        if (RuntimeUpdatesProcessor.INSTANCE != null) {
            RuntimeUpdatesProcessor.INSTANCE.checkForFileChange();
            RuntimeUpdatesProcessor.INSTANCE.checkForChangedClasses(true);
        }
        firstStart(deploymentClassLoader, codeGens);
        // doStart(false, Collections.emptySet());
        if (deploymentProblem != null || RuntimeUpdatesProcessor.INSTANCE.getCompileProblem() != null) {
            if (context.isAbortOnFailedStart()) {
                throw new RuntimeException(deploymentProblem == null ? RuntimeUpdatesProcessor.INSTANCE.getCompileProblem() : deploymentProblem);
            }
        }
        shutdownThread = new Thread(new Runnable() {

            @Override
            public void run() {
                shutdownLatch.countDown();
                synchronized (DevModeMain.class) {
                    if (runner != null) {
                        try {
                            close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, "Quarkus Shutdown Thread");
        Runtime.getRuntime().addShutdownHook(shutdownThread);
    } catch (Exception e) {
        close();
        throw new RuntimeException(e);
    }
}
Also used : BiFunction(java.util.function.BiFunction) ObjectInputStream(java.io.ObjectInputStream) ClassTransformingBuildStep(io.quarkus.deployment.steps.ClassTransformingBuildStep) CommandLineUtils(org.apache.maven.shared.utils.cli.CommandLineUtils) ConfigProviderResolver(org.eclipse.microprofile.config.spi.ConfigProviderResolver) ApplicationLifecycleManager(io.quarkus.runtime.ApplicationLifecycleManager) ByteArrayInputStream(java.io.ByteArrayInputStream) Map(java.util.Map) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) ConsoleStateManager(io.quarkus.deployment.console.ConsoleStateManager) DevConsoleManager(io.quarkus.dev.console.DevConsoleManager) InitialConfigurator(io.quarkus.bootstrap.logging.InitialConfigurator) Path(java.nio.file.Path) ConsoleHandler(org.jboss.logmanager.handlers.ConsoleHandler) LoggingSetupRecorder(io.quarkus.runtime.logging.LoggingSetupRecorder) Predicate(java.util.function.Predicate) Collection(java.util.Collection) AugmentActionImpl(io.quarkus.runner.bootstrap.AugmentActionImpl) Set(java.util.Set) BLUE(io.quarkus.deployment.dev.testing.MessageFormat.BLUE) ServiceLoader(java.util.ServiceLoader) QuarkusClassLoader(io.quarkus.bootstrap.classloading.QuarkusClassLoader) StartupAction(io.quarkus.bootstrap.app.StartupAction) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) MessageFormat(io.quarkus.deployment.dev.testing.MessageFormat) BuildStep(io.quarkus.builder.BuildStep) ColorPatternFormatter(org.jboss.logmanager.formatters.ColorPatternFormatter) BuildContext(io.quarkus.builder.BuildContext) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) ByteArrayOutputStream(java.io.ByteArrayOutputStream) RunningQuarkusApplication(io.quarkus.bootstrap.app.RunningQuarkusApplication) DevModeType(io.quarkus.dev.spi.DevModeType) Logger(org.jboss.logging.Logger) DeploymentFailedStartHandler(io.quarkus.dev.spi.DeploymentFailedStartHandler) LaunchMode(io.quarkus.runtime.LaunchMode) ClassChangeInformation(io.quarkus.bootstrap.app.ClassChangeInformation) Timing(io.quarkus.bootstrap.runner.Timing) BindException(java.net.BindException) TestSupport(io.quarkus.deployment.dev.testing.TestSupport) CodeGenData(io.quarkus.deployment.codegen.CodeGenData) ArrayList(java.util.ArrayList) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) ApplicationClassPredicateBuildItem(io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem) BiConsumer(java.util.function.BiConsumer) ObjectOutputStream(java.io.ObjectOutputStream) ApplicationStartException(io.quarkus.dev.appstate.ApplicationStartException) QuarkusConfigFactory(io.quarkus.runtime.configuration.QuarkusConfigFactory) HotReplacementSetup(io.quarkus.dev.spi.HotReplacementSetup) Properties(java.util.Properties) ClassPathElement(io.quarkus.bootstrap.classloading.ClassPathElement) CommandLineException(org.apache.maven.shared.utils.cli.CommandLineException) IOException(java.io.IOException) ConsoleCommand(io.quarkus.deployment.console.ConsoleCommand) Consumer(java.util.function.Consumer) Paths(java.nio.file.Paths) Closeable(java.io.Closeable) CodeGenerator(io.quarkus.deployment.CodeGenerator) Comparator(java.util.Comparator) FSWatchUtil(io.quarkus.deployment.util.FSWatchUtil) Collections(java.util.Collections) ArrayList(java.util.ArrayList) ClassTransformingBuildStep(io.quarkus.deployment.steps.ClassTransformingBuildStep) BuildStep(io.quarkus.builder.BuildStep) ApplicationClassPredicateBuildItem(io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem) ClassPathElement(io.quarkus.bootstrap.classloading.ClassPathElement) ObjectOutputStream(java.io.ObjectOutputStream) Predicate(java.util.function.Predicate) AugmentActionImpl(io.quarkus.runner.bootstrap.AugmentActionImpl) Path(java.nio.file.Path) CodeGenData(io.quarkus.deployment.codegen.CodeGenData) ByteArrayOutputStream(java.io.ByteArrayOutputStream) QuarkusClassLoader(io.quarkus.bootstrap.classloading.QuarkusClassLoader) BindException(java.net.BindException) ApplicationStartException(io.quarkus.dev.appstate.ApplicationStartException) CommandLineException(org.apache.maven.shared.utils.cli.CommandLineException) IOException(java.io.IOException) BuildContext(io.quarkus.builder.BuildContext) ByteArrayInputStream(java.io.ByteArrayInputStream) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) DevModeType(io.quarkus.dev.spi.DevModeType) ObjectInputStream(java.io.ObjectInputStream)

Example 5 with AugmentAction

use of io.quarkus.bootstrap.app.AugmentAction in project quarkus by quarkusio.

the class PackageAppTestBase method testBootstrap.

@Override
protected void testBootstrap(QuarkusBootstrap creator) throws Exception {
    System.setProperty("quarkus.package.type", "legacy-jar");
    try {
        CuratedApplication curated = creator.bootstrap();
        assertAppModel(curated.getApplicationModel());
        final String[] expectedExtensions = expectedExtensionDependencies();
        if (expectedExtensions != null) {
            assertExtensionDependencies(curated.getApplicationModel(), expectedExtensions);
        }
        assertDeploymentDeps(curated.getApplicationModel().getDependencies().stream().filter(d -> d.isDeploymentCp() && !d.isRuntimeCp()).map(d -> new ArtifactDependency(d)).collect(Collectors.toSet()));
        AugmentAction action = curated.createAugmentor();
        AugmentResult outcome = action.createProductionApplication();
        final Path libDir = outcome.getJar().getLibraryDir();
        assertTrue(Files.isDirectory(libDir));
        final Set<String> actualLib = new HashSet<>();
        try (Stream<Path> stream = Files.list(libDir)) {
            final Iterator<Path> i = stream.iterator();
            while (i.hasNext()) {
                actualLib.add(i.next().getFileName().toString());
            }
        }
        final Path runnerJar = outcome.getJar().getPath();
        assertTrue(Files.exists(runnerJar));
        try (JarFile jar = new JarFile(runnerJar.toFile())) {
            final Attributes mainAttrs = jar.getManifest().getMainAttributes();
            // assert the main class
            assertEquals(MAIN_CLS, mainAttrs.getValue("Main-Class"));
            // assert the Class-Path contains all the entries in the lib dir
            final String cp = mainAttrs.getValue("Class-Path");
            assertNotNull(cp);
            String[] cpEntries = Arrays.stream(cp.trim().split("\\s+")).filter(s -> !s.trim().isEmpty()).toArray(String[]::new);
            assertEquals(actualLib.size(), cpEntries.length);
            for (String entry : cpEntries) {
                assertTrue(entry.startsWith(LIB_PREFIX));
                assertTrue(actualLib.contains(entry.substring(LIB_PREFIX.length())));
            }
        }
        List<String> missingEntries = Collections.emptyList();
        for (String entry : expectedLib) {
            if (!actualLib.remove(entry)) {
                if (missingEntries.isEmpty()) {
                    missingEntries = new ArrayList<>();
                }
                missingEntries.add(entry);
            }
        }
        StringBuilder buf = null;
        if (!missingEntries.isEmpty()) {
            buf = new StringBuilder();
            buf.append("Missing entries: ").append(missingEntries.get(0));
            for (int i = 1; i < missingEntries.size(); ++i) {
                buf.append(", ").append(missingEntries.get(i));
            }
        }
        if (!actualLib.isEmpty()) {
            if (buf == null) {
                buf = new StringBuilder();
            } else {
                buf.append("; ");
            }
            final Iterator<String> i = actualLib.iterator();
            buf.append("Extra entries: ").append(i.next());
            while (i.hasNext()) {
                buf.append(", ").append(i.next());
            }
        }
        if (buf != null) {
            fail(buf.toString());
        }
    } finally {
        System.clearProperty("quarkus.package.type");
    }
}
Also used : Assertions.fail(org.junit.jupiter.api.Assertions.fail) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) Arrays(java.util.Arrays) TsDependency(io.quarkus.bootstrap.resolver.TsDependency) JarFile(java.util.jar.JarFile) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ArtifactDependency(io.quarkus.maven.dependency.ArtifactDependency) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) Dependency(io.quarkus.maven.dependency.Dependency) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Path(java.nio.file.Path) OutputStream(java.io.OutputStream) AugmentResult(io.quarkus.bootstrap.app.AugmentResult) Properties(java.util.Properties) Iterator(java.util.Iterator) Files(java.nio.file.Files) BufferedWriter(java.io.BufferedWriter) Collection(java.util.Collection) Set(java.util.Set) BootstrapConstants(io.quarkus.bootstrap.BootstrapConstants) IOException(java.io.IOException) ContentProvider(io.quarkus.bootstrap.resolver.TsArtifact.ContentProvider) TsArtifact(io.quarkus.bootstrap.resolver.TsArtifact) BootstrapTestBase(io.quarkus.bootstrap.resolver.BootstrapTestBase) Attributes(java.util.jar.Attributes) Collectors(java.util.stream.Collectors) List(java.util.List) Stream(java.util.stream.Stream) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) ResolvedDependency(io.quarkus.maven.dependency.ResolvedDependency) Collections(java.util.Collections) Path(java.nio.file.Path) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) ArtifactDependency(io.quarkus.maven.dependency.ArtifactDependency) Attributes(java.util.jar.Attributes) AugmentResult(io.quarkus.bootstrap.app.AugmentResult) JarFile(java.util.jar.JarFile) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) HashSet(java.util.HashSet)

Aggregations

AugmentAction (io.quarkus.bootstrap.app.AugmentAction)9 Path (java.nio.file.Path)9 IOException (java.io.IOException)8 CuratedApplication (io.quarkus.bootstrap.app.CuratedApplication)7 QuarkusBootstrap (io.quarkus.bootstrap.app.QuarkusBootstrap)5 AugmentResult (io.quarkus.bootstrap.app.AugmentResult)4 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)4 Map (java.util.Map)4 RunningQuarkusApplication (io.quarkus.bootstrap.app.RunningQuarkusApplication)3 StartupAction (io.quarkus.bootstrap.app.StartupAction)3 BuildChainBuilder (io.quarkus.builder.BuildChainBuilder)3 BuildContext (io.quarkus.builder.BuildContext)3 BuildStep (io.quarkus.builder.BuildStep)3 UncheckedIOException (java.io.UncheckedIOException)3 Collections (java.util.Collections)3 HashMap (java.util.HashMap)3 List (java.util.List)3 Set (java.util.Set)3 Consumer (java.util.function.Consumer)3