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

io.paradoxical.common.test.web.runner.BaseServiceTestRunner Maven / Gradle / Ivy

There is a newer version: 2.0
Show newest version
package io.paradoxical.common.test.web.runner;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.logging.ConsoleAppenderFactory;
import io.dropwizard.logging.DefaultLoggingFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.dropwizard.testing.ConfigOverride;
import io.paradoxical.common.test.guice.ModuleOverrider;
import io.paradoxical.common.test.guice.OverridableModule;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import net.sourceforge.argparse4j.inf.Namespace;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import java.util.List;

public class BaseServiceTestRunner> implements AutoCloseable {

    @Getter(AccessLevel.PROTECTED)
    private final TestApplicationFactory applicationFactory;

    @Getter(AccessLevel.PROTECTED)
    private final String configPath;

    @Getter(AccessLevel.PROTECTED)
    private final TConfiguration configuration;


    @Getter(AccessLevel.PROTECTED)
    @Setter(AccessLevel.PROTECTED)
    private ServiceTestRunnerConfig testHostConfiguration;

    @Getter
    @Setter(AccessLevel.PROTECTED)
    private TApplication application;

    @Getter
    private boolean started = false;

    @Getter(AccessLevel.PROTECTED)
    private Bootstrap currentBootstrap;

    public BaseServiceTestRunner(
            @NonNull @Nonnull @NotNull TestApplicationFactory applicationFactory,
            @NonNull @Nonnull @NotNull TConfiguration configuration) {
        this(applicationFactory, configuration, null, ImmutableList.of());
    }

    protected BaseServiceTestRunner(
            @NonNull @Nonnull @NotNull TestApplicationFactory applicationFactory,
            @Nullable TConfiguration configuration,
            @Nullable String configPath,
            @NonNull @Nonnull @NotNull ImmutableList configOverrides) {

        this.applicationFactory = applicationFactory;
        this.configPath = configPath;
        this.configuration = configuration;

        configOverrides.forEach(ConfigOverride::addToSystemProperties);
    }

    public BaseServiceTestRunner(
            @NonNull @Nonnull @NotNull TestApplicationFactory applicationFactory,
            @Nullable String configPath,
            ConfigOverride... configOverrides) {
        this(applicationFactory, null, configPath, ImmutableList.copyOf(configOverrides));
    }

    public BaseServiceTestRunner run() throws Exception {
        return run(ImmutableList.of());
    }

    public BaseServiceTestRunner run(List overridableModules) throws Exception {
        return run(ServiceTestRunnerConfig.Default, overridableModules);
    }

    public BaseServiceTestRunner run(ServiceTestRunnerConfig config, List overridableModules) throws Exception {
        this.testHostConfiguration = config;

        startIfRequired(ImmutableList.copyOf(overridableModules));

        return this;
    }

    protected void startIfRequired(final ImmutableList overridableModules) throws Exception {
        if (started) {
            return;
        }

        currentBootstrap = internalInit(overridableModules);

        final EnvironmentCommand command = createStartupCommand(application);

        ImmutableMap.Builder file = ImmutableMap.builder();

        if (!Strings.isNullOrEmpty(configPath)) {
            file.put("file", configPath);
        }

        final Namespace namespace = new Namespace(file.build());

        command.run(currentBootstrap, namespace);

        started = true;
    }

    /**
     * Customize the dropwizard bootstrapping code to provide a custom logger, and return the provided config
     * This way we aren't bound to files to pass in configs and can override things in code
     *
     * @param overridableModules The list of modules to use
     * @return a bootstrap system for self-hosting
     */
    protected Bootstrap internalInit(final ImmutableList overridableModules) {

        application = applicationFactory.createService(overridableModules);

        final Bootstrap bootstrap = createBootstrapSystem(application);

        if (configuration != null) {
            final StaticConfigurationFactory staticConfigurationFactory = new StaticConfigurationFactory() {
                @Override
                public TConfiguration provideConfig() {

                    initializeLogging();

                    return configuration;
                }

                private void initializeLogging() {
                    final DefaultLoggingFactory loggingFactory = ((DefaultLoggingFactory) configuration.getLoggingFactory());

                    final ConsoleAppenderFactory testAppender = new ConsoleAppenderFactory();

                    testAppender.setLogFormat(testHostConfiguration.getLogFormat());

                    loggingFactory.setAppenders(ImmutableList.of(testAppender));
                }
            };

            bootstrap.setConfigurationFactoryFactory((klass, validator, objectMapper, propertyPrefix) -> staticConfigurationFactory);
        }

        application.initialize(bootstrap);

        return bootstrap;
    }

    protected EnvironmentCommand createStartupCommand(final TApplication application) {
        return new EnvironmentCommand(application, "non-running", "test") {
            @Override
            protected void run(final Environment environment, final Namespace namespace, final TConfiguration configuration) throws Exception {
            }
        };
    }

    protected Bootstrap createBootstrapSystem(TApplication application) {
        return new Bootstrap<>(application);
    }

    public BaseServiceTestRunner run(ServiceTestRunnerConfig config) throws Exception {
        return run(config, ImmutableList.of());
    }

    @Override
    public void close() throws Exception {
        if (!isStarted()) {
            return;
        }

        TApplication application = getApplication();

        if (application != null &&
            application instanceof ModuleOverrider &&
            ((ModuleOverrider) (application)).getOverrideModules() != null) {

            (((ModuleOverrider) application)).getOverrideModules()
                                             .stream()
                                             .forEach(OverridableModule::close);
        }

        started = false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy