/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.junit; import java.lang.reflect.Field; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.junit.runner.Runner; import org.junit.runners.Parameterized; public final class SelectedParameterizedRunner extends Parameterized { /** * <p>Parameterization override filter (works by name).</p> * * <p>If this property is set, then only parameterization names that match its value will be processed. These * names behave like @Failing names (in terms of regexes, etc). If this property is set and a test that matches * it is marked as @Failing, that test will still get run. For instance, if a parameterization named * <tt>myFooTest</tt> is marked as failing for a given test (either because the entire parameterization is marked * as failing, or because of a <tt>@Failing</tt> annotation on the method), and if you have a system property * <tt>{@value} == "/myFoo/"</tt>, then the test <em>will</em> be run. */ public final static String PARAMETERIZATION_OVERRIDE = "fdbsql.test.param.override"; private final String override; private final boolean overrideIsRegex; private final static Logger logger = LoggerFactory.getLogger(SelectedParameterizedRunner.class); public SelectedParameterizedRunner(Class<?> clazz) throws Throwable { super(clazz); override = System.getProperty(PARAMETERIZATION_OVERRIDE); overrideIsRegex = (override != null) && paramNameUsesRegex(override); if (override != null) { String msg = "Override is set to"; if (overrideIsRegex) { msg += " regex"; } msg += ":" + override; logger.debug(msg); } } static boolean paramNameUsesRegex(String paramName) { return paramName.length() > 2 && (paramName.charAt(0)=='/') && (paramName.charAt(paramName.length()-1)=='/'); } /** * Returns whether a given parameterization matches a given regex. The regex should be in "/regex/" format. * @param paramName the haystack, as it were * @param paramRegex a string that starts and ends with '/', and between them has a needle. * @return whether the paramRegex is found in paramName */ static boolean paramNameMatchesRegex(String paramName, String paramRegex) { assert paramRegex.charAt(0)=='/'; assert paramRegex.charAt(paramRegex.length()-1)=='/'; assert paramRegex.length() > 2; String regex = paramRegex.substring(1, paramRegex.length()-1); return Pattern.compile(regex).matcher(paramName).find(); } @Override protected List<Runner> getChildren() { List<Runner> children = super.getChildren(); if (override != null) { for (Iterator<Runner> iterator = children.iterator(); iterator.hasNext(); ) { Runner child = iterator.next(); String fName = child.getDescription().getDisplayName(); if (fName.startsWith("[") && fName.endsWith("]")) { fName = fName.substring(1, fName.length()-1); } if (overrideIsRegex && !paramNameMatchesRegex(fName, override)) { iterator.remove(); } else if (!overrideIsRegex && !fName.equals(override)) { iterator.remove(); } } } return children; } }