/* * JBoss, Home of Professional Open Source * Copyright 2010-2016, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.richfaces.tests.metamer.ftest.extension.configurator.skip; import static java.text.MessageFormat.format; import java.lang.reflect.Method; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.richfaces.tests.metamer.ftest.extension.configurator.ConfiguratorExtension; import org.richfaces.tests.metamer.ftest.extension.configurator.config.Config; import org.richfaces.tests.metamer.ftest.extension.configurator.config.EmptyConfig; import org.richfaces.tests.metamer.ftest.extension.configurator.skip.annotation.AndExpression; import org.richfaces.tests.metamer.ftest.extension.configurator.skip.annotation.Skip; /** * Configurator for not running test on specified circumstances. To use this extension, mark test method with @Skip annotation.<br/> * Configurator can be turned off by system property <code>configurator.skip.enabled=false</code>.<br/> * Configurator can run in reverse mode, activated by system property <code>configurator.skip.reverse</code>. In reverse mode, only those tests, which should be skipped by this configurator, will run.<br/> * Configurator can run only a specific skip case, specified by system property <code>configurator.skip.case=CASE</code>. Only those tests, which simple name of the first class specified in @Skip annotation matches expression <code>.*CASE.*</code>, will run. This specific configuration ignores reverse mode.<br/> * Some examples:<br/> * To always skip the test:<br/> * <code>@Skip</code><br/> * Some already predefined conditions can be found in {@link org.richfaces.tests.metamer.ftest.extension.configurator.skip.On On}.<br/> * To skip the test on Firefox browser:<br/> * <code>@Skip(On.Browser.Firefox.class)</code><br/> * To skip the test on Firefox browser on the Windows OS:<br/> * <code>@Skip({ On.Browser.Firefox.class, On.OS.Windows.class })</code> * To skip the test on Firefox or Chrome browser and on the Windows OS:<br/> * <code>@Skip(expressions = { @AndExpression({ On.Browser.Firefox.class, On.OS.Windows.class }), @AndExpression({ On.Browser.Chrome.class, On.OS.Windows.class }) })</code><br/> * To skip the test with custom condition implement an interface {@link org.richfaces.tests.metamer.ftest.extension.configurator.skip.SkipOn SkipOn} and add a no arguments constructor. * Other option is to extend predefined {@link org.richfaces.tests.metamer.ftest.extension.configurator.skip.BecauseOf.SkipOnIssue BecauseOf.SkipOnIssue} (and leave it in same class) to reuse already defined conditions from {@link org.richfaces.tests.metamer.ftest.extension.configurator.skip.On On}, like:<br/> * <code>@Skip(BecauseOf.Issue1234.class)</code><br/> * * @author <a href="mailto:jstefek@redhat.com">Jiri Stefek</a> */ public class SkipConfigurator implements ConfiguratorExtension { private static final List<Config> LIST_WITH_EMPTY_CONFIG = new LinkedList<Config>(); public static String PROPERTY_CASE = "configurator.skip.case"; public static String PROPERTY_ENABLED = "configurator.skip.enabled"; public static String PROPERTY_REVERSE = "configurator.skip.reverse"; private final SkipOnResultsCache cache = SkipOnResultsCache.getInstance(); static { LIST_WITH_EMPTY_CONFIG.add(EmptyConfig.getInstance()); } public List<Config> _createConfigurations(Method m, Object testInstance) { Skip annotationOnMethod = m.getAnnotation(Skip.class); if (annotationOnMethod == null) { return getNotSkippedConfiguration(); } // the expressions takes precedence over value (since it contains default value) if (annotationOnMethod.expressions() != null && annotationOnMethod.expressions().length > 0) { boolean willSkip = false; for (AndExpression expression : annotationOnMethod.expressions()) { willSkip = willSkip || handleAndExpressions(expression.value()); } return willSkip ? getSkippedConfiguration() : getNotSkippedConfiguration(); } else if (annotationOnMethod.value() != null && annotationOnMethod.value().length > 0) { if (handleAndExpressions(annotationOnMethod.value())) { return getSkippedConfiguration(); } } else { throw new RuntimeException("The Skip annotation cannot be empty. Either specify value or expressions!"); } return getNotSkippedConfiguration(); } private boolean applyCondition(Class<? extends SkipOn> skipOnClass) { return cache.getResultFor(skipOnClass); } @Override public List<Config> createConfigurations(Method m, Object testInstance) { if (isPropertyNotPresentOrTrue(PROPERTY_ENABLED)) {// is configurator enabled? String caseProperty = getCaseProperty(); if (caseProperty != null) { return getConfigurationForGivenCase(m, caseProperty); } List<Config> result = _createConfigurations(m, testInstance); return isPropertyPresentOrTrue(PROPERTY_REVERSE)// is reverse mode enabled? ? (result.isEmpty() ? getNotSkippedConfiguration() : getSkippedConfiguration()) : result; } return getNotSkippedConfiguration(); } private String getCaseProperty() { return System.getProperty(PROPERTY_CASE); } private List<Config> getConfigurationForGivenCase(Method m, String caseProperty) { Skip skipAnnotation = m.getAnnotation(Skip.class); if (skipAnnotation != null) { if (skipAnnotation.value() != null) { return skipAnnotation.value()[0].getSimpleName().matches(format(".*{0}.*", caseProperty)) ? getNotSkippedConfiguration() : getSkippedConfiguration(); } else { return getSkippedConfiguration(); } } else { return getSkippedConfiguration(); } } private List<Config> getNotSkippedConfiguration() { return LIST_WITH_EMPTY_CONFIG; } @SuppressWarnings("unchecked") private List<Config> getSkippedConfiguration() { return Collections.EMPTY_LIST; } private boolean handleAndExpressions(Class<? extends SkipOn>[] andValues) { if (andValues.length > 0) { boolean b = true; for (Class<? extends SkipOn> skipOnClass : andValues) { b = b && applyCondition(skipOnClass); } return b; } else { return Boolean.FALSE; } } @Override public boolean ignoreConfigurations() { return Boolean.TRUE; } private boolean isPropertyNotPresentOrTrue(String name) { return Boolean.parseBoolean(System.getProperty(name, "true")); } private boolean isPropertyPresentOrTrue(String name) { return Boolean.parseBoolean(System.getProperty(name, "false")); } @Override public boolean skipTestIfNoConfiguration() { return Boolean.TRUE; } }