1 21 22 package edu.umd.cs.findbugs.detect; 23 24 25 import edu.umd.cs.findbugs.*; 26 import edu.umd.cs.findbugs.ba.ClassContext; 27 import org.apache.bcel.Repository; 28 import org.apache.bcel.classfile.*; 29 30 public class InvalidJUnitTest extends BytecodeScanningDetector { 31 32 private static final int SEEN_NOTHING = 0; 33 34 private static final int SEEN_ALOAD_0 = 1; 35 36 private BugReporter bugReporter; 37 private boolean checkedTestCaseClass; 38 private boolean haveTestCaseClass; 39 40 private int state; 41 42 public InvalidJUnitTest(BugReporter bugReporter) { 43 this.bugReporter = bugReporter; 44 } 45 46 47 48 boolean directChildOfTestCase; 49 50 @Override 51 public void visitClassContext(ClassContext classContext) { 52 if (!enabled()) 53 return; 54 55 JavaClass jClass = classContext.getJavaClass(); 56 57 try { 58 if (!Repository.instanceOf(jClass, "junit.framework.TestCase")) 59 return; 60 61 if ((jClass.getAccessFlags() & ACC_ABSTRACT) == 0) { 62 Method[] methods = jClass.getMethods(); 63 boolean foundTest = false; 64 for (Method m : methods) { 65 if (m.getName().startsWith("test")) { 66 foundTest = true; 67 break; 68 } 69 } 70 if (!foundTest && !hasSuite(methods)) { 71 bugReporter.reportBug( new BugInstance( this, "IJU_NO_TESTS", LOW_PRIORITY) 72 .addClass(jClass)); 73 } 74 } 75 76 JavaClass superClass = jClass.getSuperClass(); 77 directChildOfTestCase = superClass.getClassName().equals( 78 "junit.framework.TestCase"); 79 jClass.accept(this); 80 } catch (ClassNotFoundException cnfe) { 81 bugReporter.reportMissingClass(cnfe); 82 } 83 84 } 85 86 87 private boolean hasSuite(Method[] methods) { 88 for (Method m : methods) { 89 if (m.getName().equals("suite") 90 && m.isPublic() 91 && m.isStatic() 92 && m.getSignature().equals("()Ljunit/framework/Test;")) 95 return true; 96 } 97 return false; 98 } 99 100 107 private boolean enabled() { 108 if (!checkedTestCaseClass) { 109 checkedTestCaseClass = true; 110 try { 111 Repository.lookupClass("junit.framework.TestCase"); 112 haveTestCaseClass = true; 113 } catch (ClassNotFoundException e) { 114 } 117 } 118 119 return haveTestCaseClass; 120 } 121 122 @Override 123 public void visit(Method obj) { 124 if (getMethodName().equals("suite") && !obj.isStatic()) 125 bugReporter.reportBug(new BugInstance(this, "IJU_SUITE_NOT_STATIC", 126 NORMAL_PRIORITY).addClassAndMethod(this)); 127 128 } 129 130 private boolean sawSuperCall; 131 132 @Override 133 public void visit(Code obj) { 134 if (!directChildOfTestCase 135 && (getMethodName().equals("setUp") || getMethodName().equals( 136 "tearDown")) 137 && !getMethod().isPrivate()) { 138 sawSuperCall = false; 139 super.visit(obj); 140 if (sawSuperCall) 141 return; 142 JavaClass we = Lookup.findSuperImplementor(getThisClass(), 143 getMethodName(), "()V", bugReporter); 144 if (we != null && !we.getClassName().equals("junit.framework.TestCase")) { 145 bugReporter.reportBug(new BugInstance(this, getMethodName() 147 .equals("setUp") ? "IJU_SETUP_NO_SUPER" 148 : "IJU_TEARDOWN_NO_SUPER", NORMAL_PRIORITY) 149 .addClassAndMethod(this)); 150 } 151 } 152 } 153 154 @Override 155 public void sawOpcode(int seen) { 156 switch (state) { 157 case SEEN_NOTHING: 158 if (seen == ALOAD_0) 159 state = SEEN_ALOAD_0; 160 break; 161 162 case SEEN_ALOAD_0: 163 if ((seen == INVOKESPECIAL) 164 && (getNameConstantOperand().equals(getMethodName())) 165 && (getMethodSig().equals("()V"))) 166 sawSuperCall = true; 167 state = SEEN_NOTHING; 168 break; 169 default: 170 state = SEEN_NOTHING; 171 } 172 } 173 } 174 175 | Popular Tags |