001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase; 020 021import java.lang.reflect.Method; 022import java.lang.reflect.Modifier; 023import java.util.regex.Pattern; 024 025import org.junit.Test; 026import org.junit.experimental.categories.Category; 027import org.junit.runners.Suite; 028 029/** 030 * ClassFinder that is pre-configured with filters that will only allow test classes. 031 * The name is strange because a logical name would start with "Test" and be confusing. 032 */ 033public class ClassTestFinder extends ClassFinder { 034 035 public ClassTestFinder() { 036 super(new TestFileNameFilter(), new TestFileNameFilter(), new TestClassFilter()); 037 } 038 039 public ClassTestFinder(Class<?> category) { 040 super(new TestFileNameFilter(), new TestFileNameFilter(), new TestClassFilter(category)); 041 } 042 043 public static Class<?>[] getCategoryAnnotations(Class<?> c) { 044 Category category = c.getAnnotation(Category.class); 045 if (category != null) { 046 return category.value(); 047 } 048 return new Class<?>[0]; 049 } 050 051 /** Filters both test classes and anything in the hadoop-compat modules */ 052 public static class TestFileNameFilter implements FileNameFilter, ResourcePathFilter { 053 private static final Pattern hadoopCompactRe = 054 Pattern.compile("hbase-hadoop\\d?-compat"); 055 056 @Override 057 public boolean isCandidateFile(String fileName, String absFilePath) { 058 boolean isTestFile = fileName.startsWith("Test") 059 || fileName.startsWith("IntegrationTest"); 060 return isTestFile && !hadoopCompactRe.matcher(absFilePath).find(); 061 } 062 063 @Override 064 public boolean isCandidatePath(String resourcePath, boolean isJar) { 065 return !hadoopCompactRe.matcher(resourcePath).find(); 066 } 067 } 068 069 /* 070 * A class is considered as a test class if: 071 * - it's not Abstract AND 072 * - one or more of its methods is annotated with org.junit.Test OR 073 * - the class is annotated with Suite.SuiteClasses 074 * */ 075 public static class TestClassFilter implements ClassFilter { 076 private Class<?> categoryAnnotation = null; 077 public TestClassFilter(Class<?> categoryAnnotation) { 078 this.categoryAnnotation = categoryAnnotation; 079 } 080 081 public TestClassFilter() { 082 this(null); 083 } 084 085 @Override 086 public boolean isCandidateClass(Class<?> c) { 087 return isTestClass(c) && isCategorizedClass(c); 088 } 089 090 private boolean isTestClass(Class<?> c) { 091 if (Modifier.isAbstract(c.getModifiers())) { 092 return false; 093 } 094 095 if (c.getAnnotation(Suite.SuiteClasses.class) != null) { 096 return true; 097 } 098 099 for (Method met : c.getMethods()) { 100 if (met.getAnnotation(Test.class) != null) { 101 return true; 102 } 103 } 104 105 return false; 106 } 107 108 private boolean isCategorizedClass(Class<?> c) { 109 if (this.categoryAnnotation == null) { 110 return true; 111 } 112 for (Class<?> cc : getCategoryAnnotations(c)) { 113 if (cc.equals(this.categoryAnnotation)) { 114 return true; 115 } 116 } 117 return false; 118 } 119 } 120}