001/**
002 * Copyright (C) 2006-2019 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.junit5.environment;
017
018import static java.util.Collections.singletonList;
019import static java.util.Optional.ofNullable;
020
021import java.util.List;
022
023import org.junit.jupiter.api.extension.AfterEachCallback;
024import org.junit.jupiter.api.extension.BeforeEachCallback;
025import org.junit.jupiter.api.extension.ConditionEvaluationResult;
026import org.junit.jupiter.api.extension.ExecutionCondition;
027import org.junit.jupiter.api.extension.Extension;
028import org.junit.jupiter.api.extension.ExtensionContext;
029import org.junit.jupiter.api.extension.ParameterContext;
030import org.junit.jupiter.api.extension.ParameterResolutionException;
031import org.junit.jupiter.api.extension.ParameterResolver;
032import org.junit.jupiter.api.extension.TestInstancePostProcessor;
033import org.junit.jupiter.api.extension.TestTemplateInvocationContext;
034import org.talend.sdk.component.junit.environment.DecoratingEnvironmentProvider;
035import org.talend.sdk.component.junit.environment.EnvironmentProvider;
036import org.talend.sdk.component.junit5.ComponentExtension;
037
038import lombok.AllArgsConstructor;
039
040@AllArgsConstructor
041public class EnvironmentalContext implements TestTemplateInvocationContext {
042
043    private final EnvironmentProvider provider;
044
045    private final String displayName;
046
047    private final ComponentExtension componentExtension;
048
049    @Override
050    public String getDisplayName(final int invocationIndex) {
051        return displayName;
052    }
053
054    @Override
055    public List<Extension> getAdditionalExtensions() {
056        return singletonList(new EnvironmentalLifecycle(provider, componentExtension, null));
057    }
058
059    @AllArgsConstructor
060    public static class EnvironmentalLifecycle implements BeforeEachCallback, AfterEachCallback, ExecutionCondition,
061            ParameterResolver, TestInstancePostProcessor {
062
063        private final EnvironmentProvider provider;
064
065        private final ComponentExtension componentExtension;
066
067        private AutoCloseable closeable;
068
069        @Override
070        public void beforeEach(final ExtensionContext context) {
071            closeable = provider.start(context.getRequiredTestClass(), context.getRequiredTestClass().getAnnotations());
072            ofNullable(componentExtension).ifPresent(c -> {
073                c.doStart(context);
074                c.doInject(context);
075            });
076        }
077
078        @Override
079        public void afterEach(final ExtensionContext context) {
080            ofNullable(componentExtension).ifPresent(c -> {
081                c.resetState();
082                c.doStop(context);
083            });
084            ofNullable(closeable).ifPresent(c -> {
085                try {
086                    c.close();
087                } catch (final Exception e) {
088                    throw new IllegalStateException(e);
089                }
090            });
091        }
092
093        @Override
094        public ConditionEvaluationResult evaluateExecutionCondition(final ExtensionContext context) {
095            return isActive() ? ConditionEvaluationResult.enabled("provider is active")
096                    : ConditionEvaluationResult.disabled("provider is disabled");
097        }
098
099        private boolean isActive() {
100            return DecoratingEnvironmentProvider.class.isInstance(provider)
101                    && DecoratingEnvironmentProvider.class.cast(provider).isActive();
102        }
103
104        @Override
105        public boolean supportsParameter(final ParameterContext parameterContext,
106                final ExtensionContext extensionContext) throws ParameterResolutionException {
107            return componentExtension != null
108                    && componentExtension.supportsParameter(parameterContext, extensionContext);
109        }
110
111        @Override
112        public Object resolveParameter(final ParameterContext parameterContext, final ExtensionContext extensionContext)
113                throws ParameterResolutionException {
114            return componentExtension == null ? null
115                    : componentExtension.resolveParameter(parameterContext, extensionContext);
116        }
117
118        @Override
119        public void postProcessTestInstance(final Object o, final ExtensionContext extensionContext) {
120            if (componentExtension != null) {
121                componentExtension.postProcessTestInstance(o, extensionContext);
122            }
123        }
124    }
125}