1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.testing.local; 6 7 import org.junit.runner.Description; 8 import org.junit.runner.manipulation.Filter; 9 10 import java.util.HashSet; 11 import java.util.Set; 12 import java.util.regex.Pattern; 13 14 /** 15 * Filters tests based on a googletest-style filter string. 16 */ 17 class GtestFilter extends Filter { 18 19 private final String mFilterString; 20 21 private final Set<Pattern> mPositiveRegexes; 22 private final Set<Pattern> mNegativeRegexes; 23 24 private static final Pattern ASTERISK = Pattern.compile("\\*"); 25 private static final Pattern COLON = Pattern.compile(":"); 26 private static final Pattern DASH = Pattern.compile("-"); 27 private static final Pattern PERIOD = Pattern.compile("\\."); 28 29 /** 30 * Creates the filter and converts the provided googletest-style filter 31 * string into positive and negative regexes. 32 */ 33 public GtestFilter(String filterString) { 34 mFilterString = filterString; 35 mPositiveRegexes = new HashSet<Pattern>(); 36 mNegativeRegexes = new HashSet<Pattern>(); 37 38 String[] filterStrings = COLON.split(filterString); 39 for (String f : filterStrings) { 40 if (f.isEmpty()) continue; 41 42 String sanitized = PERIOD.matcher(f).replaceAll("\\\\."); 43 sanitized = ASTERISK.matcher(sanitized).replaceAll(".*"); 44 int negIndex = sanitized.indexOf('-'); 45 if (negIndex == 0) { 46 mNegativeRegexes.add(Pattern.compile(sanitized.substring(1))); 47 } else if (negIndex != -1) { 48 String[] c = DASH.split(sanitized, 2); 49 mPositiveRegexes.add(Pattern.compile(c[0])); 50 mNegativeRegexes.add(Pattern.compile(c[1])); 51 } else { 52 mPositiveRegexes.add(Pattern.compile(sanitized)); 53 } 54 } 55 } 56 57 /** 58 * Determines whether or not a test with the provided description should 59 * run based on the configured positive and negative regexes. 60 * 61 * A test should run if: 62 * - it's just a class, OR 63 * - it doesn't match any of the negative regexes, AND 64 * - either: 65 * - there are no configured positive regexes, OR 66 * - it matches at least one of the positive regexes. 67 */ 68 @Override 69 public boolean shouldRun(Description description) { 70 if (description.getMethodName() == null) return true; 71 72 String gtestName = description.getClassName() + "." + description.getMethodName(); 73 for (Pattern p : mNegativeRegexes) { 74 if (p.matcher(gtestName).matches()) return false; 75 } 76 77 if (mPositiveRegexes.isEmpty()) return true; 78 79 for (Pattern p : mPositiveRegexes) { 80 if (p.matcher(gtestName).matches()) return true; 81 } 82 83 return false; 84 } 85 86 /** 87 * Returns a description of this filter. 88 */ 89 @Override 90 public String describe() { 91 return "gtest-filter: " + mFilterString; 92 } 93 94 } 95 96