package org.jboss.windup.exec.test;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.forge.arquillian.AddonDependencies;
import org.jboss.forge.arquillian.AddonDependency;
import org.jboss.forge.arquillian.archive.AddonArchive;
import org.jboss.forge.furnace.proxy.Proxies;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.windup.config.AbstractRuleLifecycleListener;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.RuleProvider;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.RuleMetadata;
import org.jboss.windup.config.metadata.RuleMetadataType;
import org.jboss.windup.config.operation.Log;
import org.jboss.windup.exec.WindupProcessor;
import org.jboss.windup.exec.configuration.WindupConfiguration;
import org.jboss.windup.exec.configuration.options.ExcludeTagsOption;
import org.jboss.windup.exec.configuration.options.IncludeTagsOption;
import org.jboss.windup.graph.GraphContext;
import org.jboss.windup.graph.GraphContextFactory;
import org.jboss.windup.util.exception.WindupException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ocpsoft.logging.Logger;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.config.Rule;
import org.ocpsoft.rewrite.context.Context;
import org.ocpsoft.rewrite.context.EvaluationContext;
/**
* Test for the tags include/exclude - RuleProvider execution filtering based on tags.
*
* How this tests works:
*
* The 3 RuleProviders have different tags. There are 4 executions, each time with different include/exclude tags.
* Through the RuleExecutionListener, execution of rules is observed, and the same listener, at the end of execution,
* checks whether the right set of rules was executed.
*
* @author <a href="mailto:ozizka@redhat.com">Ondrej Zizka</a>
*/
@RunWith(Arquillian.class)
public class TagsIncludeExcludeTest
{
public static final String TEST_RULES_THAT_SHOULD_RUN = "test:rulesThatShouldRun";
@Deployment
@AddonDependencies({
@AddonDependency(name = "org.jboss.forge.furnace.container:cdi"),
@AddonDependency(name = "org.jboss.windup.utils:windup-utils"),
@AddonDependency(name = "org.jboss.windup.graph:windup-graph"),
@AddonDependency(name = "org.jboss.windup.config:windup-config"),
@AddonDependency(name = "org.jboss.windup.exec:windup-exec"),
})
public static AddonArchive getDeployment()
{
final AddonArchive archive = ShrinkWrap.create(AddonArchive.class)
.addBeansXML();
return archive;
}
@Inject
private WindupProcessor processor;
@Inject
private GraphContextFactory contextFactory;
public static class TestTagsRuleExecutionListener extends AbstractRuleLifecycleListener
{
Map<String, Boolean> executedRules = new HashMap<>();
@Override
public void beforeExecution(GraphRewrite event)
{
event.getRewriteContext().put("testData", new HashMap<>());
}
@Override
public boolean beforeRuleEvaluation(GraphRewrite event, Rule rule, EvaluationContext context)
{
RuleProvider provider = (RuleProvider) ((Context) rule).get(RuleMetadataType.RULE_PROVIDER);
String realName = Proxies.unwrapProxyClassName(provider.getClass());
executedRules.put(realName, Boolean.FALSE);
return false;
}
@Override
public boolean ruleEvaluationProgress(GraphRewrite event, String name, int currentPosition, int total, int timeRemainingInSeconds)
{
return false;
}
@Override
public void afterRuleConditionEvaluation(GraphRewrite event, EvaluationContext context, Rule rule, boolean result)
{
RuleProvider provider = (RuleProvider) ((Context) rule).get(RuleMetadataType.RULE_PROVIDER);
String realName = Proxies.unwrapProxyClassName(provider.getClass());
executedRules.put(realName, Boolean.TRUE);
}
@Override
public void afterExecution(GraphRewrite event)
{
@SuppressWarnings("unchecked")
Set<Class<? extends RuleProvider>> shouldHaveRun =
(Set<Class<? extends RuleProvider>>) event.getGraphContext().getOptionMap().get(TEST_RULES_THAT_SHOULD_RUN);
assertRule(TestTagsA1B1Rules.class, shouldHaveRun);
assertRule(TestTagsARules.class, shouldHaveRun);
assertRule(TestTagsBRules.class, shouldHaveRun);
}
private void assertRule(Class<? extends RuleProvider> cls, Set<Class<? extends RuleProvider>> shouldHaveRun)
{
final Boolean didItRun = BooleanUtils.isTrue(executedRules.get(cls.getName()));
Assert.assertEquals(cls.getSimpleName(), shouldHaveRun.contains(cls), didItRun);
}
}
@Test
public void testIncludeA1Tags()
{
executeTest("tagA1", null, new HashSet<Class<? extends RuleProvider>>(Arrays.asList(TestTagsARules.class, TestTagsA1B1Rules.class)));
}
@Test
public void testExcludeA1Tags()
{
executeTest(null, "tagA1", new HashSet<Class<? extends RuleProvider>>(Arrays.asList(TestTagsBRules.class)));
}
@Test
public void testCombinedA1B1Tags()
{
executeTest("tagA1", "tagB1", new HashSet<Class<? extends RuleProvider>>(Arrays.asList(TestTagsARules.class)));
}
@Test
public void testNoTags()
{
/*
* All rules should be executed (tags should create no limitation).
*/
executeTest(null, null,
new HashSet<Class<? extends RuleProvider>>(Arrays.asList(TestTagsA1B1Rules.class, TestTagsARules.class, TestTagsBRules.class)));
}
private void executeTest(String includeTags, String excludeTags, Set<Class<? extends RuleProvider>> rules)
{
Set<String> included = null;
if (includeTags != null)
included = new HashSet<>(Arrays.asList(StringUtils.split(includeTags)));
Set<String> excluded = null;
if (excludeTags != null)
excluded = new HashSet<>(Arrays.asList(StringUtils.split(excludeTags)));
try (GraphContext context = contextFactory.create())
{
runRules(context, included, excluded, rules);
}
catch (Exception ex)
{
throw new WindupException(ex.getMessage(), ex);
}
}
/**
* Configure the WindupConfiguration according to the params and run the RuleProviders.
*/
private void runRules(GraphContext grCtx, Set<String> inTags, Set<String> exTags,
Set<Class<? extends RuleProvider>> rules)
{
WindupConfiguration wc = new WindupConfiguration();
wc.setGraphContext(grCtx);
wc.addInputPath(Paths.get("."));
wc.setOutputDirectory(Paths.get("target/WindupReport"));
wc.setOptionValue(IncludeTagsOption.NAME, inTags);
wc.setOptionValue(ExcludeTagsOption.NAME, exTags);
wc.setOptionValue(TEST_RULES_THAT_SHOULD_RUN, rules);
processor.execute(wc);
}
@RuleMetadata(tags = { "tagA1", "tagA2", "tagA3" })
public static class TestTagsARules extends NoopRuleProvider
{
}
@RuleMetadata(tags = { "tagB1", "tagB2", "tagB3" })
public static class TestTagsBRules extends NoopRuleProvider
{
}
@RuleMetadata(tags = { "tagA1", "tagB1" })
public static class TestTagsA1B1Rules extends NoopRuleProvider
{
}
public abstract static class NoopRuleProvider extends AbstractRuleProvider
{
@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
return ConfigurationBuilder.begin().addRule()
.perform(Log.message(Logger.Level.TRACE, "Performing Rule: " + this.getClass().getSimpleName()));
}
}
}