[Fb-contrib-commit] SF.net SVN: fb-contrib:[1781] trunk/fb-contrib
Brought to you by:
dbrosius
From: <dbr...@us...> - 2015-08-16 23:24:00
|
Revision: 1781 http://sourceforge.net/p/fb-contrib/code/1781 Author: dbrosius Date: 2015-08-16 23:23:57 +0000 (Sun, 16 Aug 2015) Log Message: ----------- sync from githuh Added Paths: ----------- trunk/fb-contrib/samples/UTAO_Sample.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnitTestAssertionOddities.java Removed Paths: ------------- trunk/fb-contrib/samples/JAO_Sample.java trunk/fb-contrib/samples/samples.fb trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/JUnitAssertionOddities.java Deleted: trunk/fb-contrib/samples/JAO_Sample.java =================================================================== --- trunk/fb-contrib/samples/JAO_Sample.java 2015-08-16 23:20:38 UTC (rev 1780) +++ trunk/fb-contrib/samples/JAO_Sample.java 2015-08-16 23:23:57 UTC (rev 1781) @@ -1,58 +0,0 @@ -import junit.framework.TestCase; - -import org.junit.Assert; -import org.junit.Test; - -public class JAO_Sample extends TestCase { - - public void testExactDoubles(double d1, double d2) { - Assert.assertEquals(d1, d2); - } - - public void testTrue(boolean b) { - Assert.assertEquals(true, b); - } - - public void testFalse(boolean b) { - Assert.assertEquals("Wow this is bad", false, b); - } - - public void testWrongOrder(int i) { - Assert.assertEquals(i, 10); - } - - public void testAutoBoxNotNull(int i) { - Assert.assertNotNull(i); - Assert.assertNotNull(i == 3); - } - - public void testAssertUsed(String s) { - assert s != null; - } - - public void testUseAssertEquals(String s, String s2) { - Assert.assertTrue(s.equals(s2)); - Assert.assertTrue(s.length() == s.length()); - } - - public void test3ArgNP(float foo, int boo) { - Assert.assertEquals(1.0f, foo, 0.1); - Assert.assertEquals(20, boo, 0); - - } -} - -class New { - @Test - public void nada() { - } - - @Test - public void aha() { - check("hello", "world"); - } - - private void check(String a, String b) { - Assert.assertEquals(a, b); - } -} Added: trunk/fb-contrib/samples/UTAO_Sample.java =================================================================== --- trunk/fb-contrib/samples/UTAO_Sample.java (rev 0) +++ trunk/fb-contrib/samples/UTAO_Sample.java 2015-08-16 23:23:57 UTC (rev 1781) @@ -0,0 +1,102 @@ +import org.junit.Assert; +import org.junit.Test; + +import junit.framework.TestCase; + +public class UTAO_Sample extends TestCase { + + public void testExactDoubles(double d1, double d2) { + Assert.assertEquals(d1, d2); + } + + public void testTrue(boolean b) { + Assert.assertEquals(true, b); + } + + public void testFalse(boolean b) { + Assert.assertEquals("Wow this is bad", false, b); + } + + public void testWrongOrder(int i) { + Assert.assertEquals(i, 10); + } + + public void testAutoBoxNotNull(int i) { + Assert.assertNotNull(i); + Assert.assertNotNull(i == 3); + } + + public void testAssertUsed(String s) { + assert s != null; + } + + public void testUseAssertEquals(String s, String s2) { + Assert.assertTrue(s.equals(s2)); + Assert.assertTrue(s.length() == s.length()); + } + + public void test3ArgNP(float foo, int boo) { + Assert.assertEquals(1.0f, foo, 0.1); + Assert.assertEquals(20, boo, 0); + + } +} + +class New { + @Test + public void nada() { + } + + @Test + public void aha() { + check("hello", "world"); + } + + private void check(String a, String b) { + Assert.assertEquals(a, b); + } +} + +class TestNG { + @org.testng.annotations.Test + public void nada() { + } + + @org.testng.annotations.Test + public void testTrue(boolean b) { + org.testng.Assert.assertEquals(b, true); + } + + @org.testng.annotations.Test + public void testFalse(boolean b) { + org.testng.Assert.assertEquals(b, false, "Wow this is bad"); + } + + @org.testng.annotations.Test + public void testWrongOrder(int i) { + org.testng.Assert.assertEquals(10, i); + } + + @org.testng.annotations.Test + public void testAutoBoxNotNull(int i) { + org.testng.Assert.assertNotNull(i); + org.testng.Assert.assertNotNull(i == 3); + } + + @org.testng.annotations.Test + public void testAssertUsed(String s) { + assert s != null; + } + + @org.testng.annotations.Test + public void testUseAssertEquals(String s, String s2) { + org.testng.Assert.assertTrue(s.equals(s2)); + org.testng.Assert.assertTrue(s.length() == s.length()); + } + + @org.testng.annotations.Test + public void test3ArgNP(float foo, int boo) { + Assert.assertEquals(foo, 1.0f, 0.1); + Assert.assertEquals(boo, 20, 0); + } +} Property changes on: trunk/fb-contrib/samples/UTAO_Sample.java ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Deleted: trunk/fb-contrib/samples/samples.fb =================================================================== --- trunk/fb-contrib/samples/samples.fb 2015-08-16 23:20:38 UTC (rev 1780) +++ trunk/fb-contrib/samples/samples.fb 2015-08-16 23:23:57 UTC (rev 1781) @@ -1,10 +0,0 @@ -[Jar files] -. -[Source dirs] -. -[Aux classpath entries] -./lib/jsp-api.jar -./lib/junit.jar -./lib/servlet-api.jar -[Options] -relative_paths=true Deleted: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/JUnitAssertionOddities.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/JUnitAssertionOddities.java 2015-08-16 23:20:38 UTC (rev 1780) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/JUnitAssertionOddities.java 2015-08-16 23:23:57 UTC (rev 1781) @@ -1,287 +0,0 @@ -/* - * fb-contrib - Auxiliary detectors for Java programs - * Copyright (C) 2005-2015 Dave Brosius - * - * This library 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 library 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package com.mebigfatguy.fbcontrib.detect; - -import org.apache.bcel.Repository; -import org.apache.bcel.classfile.AnnotationEntry; -import org.apache.bcel.classfile.Code; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.Type; - -import com.mebigfatguy.fbcontrib.utils.BugType; -import com.mebigfatguy.fbcontrib.utils.TernaryPatcher; - -import edu.umd.cs.findbugs.BugInstance; -import edu.umd.cs.findbugs.BugReporter; -import edu.umd.cs.findbugs.BytecodeScanningDetector; -import edu.umd.cs.findbugs.OpcodeStack; -import edu.umd.cs.findbugs.OpcodeStack.CustomUserValue; -import edu.umd.cs.findbugs.ba.ClassContext; - -/** looks for odd uses of the Assert class of the JUnit framework */ -@CustomUserValue -public class JUnitAssertionOddities extends BytecodeScanningDetector -{ - private enum State {SAW_NOTHING, SAW_IF_ICMPNE, SAW_ICONST_1, SAW_GOTO, SAW_ICONST_0, SAW_EQUALS}; - - private static final String TESTCASE_CLASS = "junit.framework.TestCase"; - private static final String TEST_CLASS = "org.junit.Test"; - private static final String TEST_ANNOTATION_SIGNATURE = "Lorg/junit/Test;"; - private static final String OLD_ASSERT_CLASS = "junit/framework/Assert"; - private static final String NEW_ASSERT_CLASS = "org/junit/Assert"; - - private BugReporter bugReporter; - private JavaClass testCaseClass; - private JavaClass testAnnotationClass; - private JavaClass cls; - private OpcodeStack stack; - private boolean isTestCaseDerived; - private boolean isAnnotationCapable; - private String clsName; - private boolean sawAssert; - private State state; - - /** - * constructs a JOA detector given the reporter to report bugs on - * @param bugReporter the sync of bug reports - */ - public JUnitAssertionOddities(BugReporter bugReporter) { - this.bugReporter = bugReporter; - - try { - testCaseClass = Repository.lookupClass(TESTCASE_CLASS); - } catch (ClassNotFoundException cnfe) { - testCaseClass = null; - } - try { - testAnnotationClass = Repository.lookupClass(TEST_CLASS); - } catch (ClassNotFoundException cnfe) { - testAnnotationClass = null; - } - } - - /** - * override the visitor to see if this class could be a test class - * - * @param classContext the context object of the currently parsed class - */ - @Override - public void visitClassContext(ClassContext classContext) { - try { - cls = classContext.getJavaClass(); - clsName = cls.getClassName().replace('.', '/'); - isTestCaseDerived = ((testCaseClass != null) && cls.instanceOf(testCaseClass)); - isAnnotationCapable = (cls.getMajor() >= 5) && (testAnnotationClass != null); - if (isTestCaseDerived || isAnnotationCapable) { - stack = new OpcodeStack(); - super.visitClassContext(classContext); - } - } catch (ClassNotFoundException cnfe) { - bugReporter.reportMissingClass(cnfe); - } finally { - stack = null; - } - } - - @Override - public void visitCode(Code obj) { - Method m = getMethod(); - boolean isTestMethod = isTestCaseDerived && m.getName().startsWith("test"); - - if (!isTestMethod && isAnnotationCapable) { - AnnotationEntry[] annotations = m.getAnnotationEntries(); - if (annotations != null) { - for (AnnotationEntry annotation : annotations) { - if (annotation.isRuntimeVisible() && TEST_ANNOTATION_SIGNATURE.equals(annotation.getAnnotationType())) { - isTestMethod = true; - break; - } - } - } - } - - if (isTestMethod) { - stack.resetForMethodEntry(this); - state = State.SAW_NOTHING; - sawAssert = false; - super.visitCode(obj); - -// if (!sawAssert) { -// bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_NO_ASSERT.name(), LOW_PRIORITY) -// .addClass(this) -// .addMethod(this)); -// } - } - } - - @Override - public void sawOpcode(int seen) { - String userValue = null; - - try { - stack.precomputation(this); - - if (seen == INVOKESTATIC) { - String clsName = getClassConstantOperand(); - if (OLD_ASSERT_CLASS.equals(clsName) || NEW_ASSERT_CLASS.equals(clsName)) { - sawAssert = true; - String methodName = getNameConstantOperand(); - if ("assertEquals".equals(methodName)) { - String signature = getSigConstantOperand(); - Type[] argTypes = Type.getArgumentTypes(signature); - if ((argTypes.length == 2) || (argTypes.length ==3)) { - - if (stack.getStackDepth() >= 2) { - OpcodeStack.Item item1 = stack.getStackItem(1); - Object cons1 = item1.getConstant(); - if ((cons1 != null) && (argTypes[argTypes.length-1].equals(Type.BOOLEAN)) && (argTypes[argTypes.length-2].equals(Type.BOOLEAN))) { - bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_BOOLEAN_ASSERT.name(), NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); - return; - } - OpcodeStack.Item item0 = stack.getStackItem(0); - if ((item0.getConstant() != null) && (item1.getConstant() == null) && ((argTypes.length == 2) || !isFloatingPtPrimitive(item0.getSignature()))) { - bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_ACTUAL_CONSTANT.name(), NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); - return; - } - if (argTypes[argTypes.length-1].equals(Type.OBJECT) && argTypes[argTypes.length-2].equals(Type.OBJECT)) { - if ("Ljava/lang/Double;".equals(item0.getSignature()) && "Ljava/lang/Double;".equals(item1.getSignature())) { - bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_INEXACT_DOUBLE.name(), NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); - return; - } - } - } - } - } else if ("assertNotNull".equals(methodName)) { - if (stack.getStackDepth() > 0) { - if ("valueOf".equals(stack.getStackItem(0).getUserValue())) { - bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_IMPOSSIBLE_NULL.name(), NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); - } - } - } else if ("assertTrue".equals(methodName)) { - if ((state == State.SAW_ICONST_0) || (state == State.SAW_EQUALS)) { - bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_USE_ASSERT_EQUALS.name(), NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); - } - } - } else { - String methodName = getNameConstantOperand(); - String sig = getSigConstantOperand(); - if (clsName.startsWith("java/lang/") - && "valueOf".equals(methodName) - && (sig.indexOf(")Ljava/lang/") >= 0)) { - userValue = "valueOf"; - } - } - } else if (seen == ATHROW) { - if (stack.getStackDepth() > 0) { - OpcodeStack.Item item = stack.getStackItem(0); - String throwClass = item.getSignature(); - if ("Ljava/lang/AssertionError;".equals(throwClass)) { - bugReporter.reportBug(new BugInstance(this, BugType.JAO_JUNIT_ASSERTION_ODDITIES_ASSERT_USED.name(), NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); - sawAssert = true; - } - } - } - - switch (state) { - case SAW_NOTHING: - case SAW_EQUALS: - if (seen == IF_ICMPNE) - state = State.SAW_IF_ICMPNE; - else - state = State.SAW_NOTHING; - break; - - case SAW_IF_ICMPNE: - if (seen == ICONST_1) - state = State.SAW_ICONST_1; - else - state = State.SAW_NOTHING; - break; - - case SAW_ICONST_1: - if (seen == GOTO) - state = State.SAW_GOTO; - else - state = State.SAW_NOTHING; - break; - - case SAW_GOTO: - if (seen == ICONST_0) - state = State.SAW_ICONST_0; - else - state = State.SAW_NOTHING; - break; - - default: - state = State.SAW_NOTHING; - break; - } - - if ((seen == INVOKEVIRTUAL) || (seen == INVOKESTATIC) || (seen == INVOKESPECIAL)) { - String lcName = getNameConstantOperand().toLowerCase(); - if (seen == INVOKEVIRTUAL) { - String sig = getSigConstantOperand(); - if ("equals".equals(lcName) && "(Ljava/lang/Object;)Z".equals(sig)) { - state = State.SAW_EQUALS; - } - } - - //assume that if you call a method in the unit test class, or call a method with assert of verify in them - //it's possibly doing asserts for you. Yes this is a hack - - if (clsName.equals(getClassConstantOperand()) || lcName.contains("assert") || lcName.contains("verify")) { - sawAssert = true; - } - } - - - } finally { - TernaryPatcher.pre(stack, seen); - stack.sawOpcode(this, seen); - TernaryPatcher.post(stack, seen); - if ((userValue != null) && (stack.getStackDepth() > 0)) { - OpcodeStack.Item item = stack.getStackItem(0); - item.setUserValue(userValue); - } - } - } - - public boolean isFloatingPtPrimitive(String signature) { - return "D".equals(signature) || "F".equals(signature); - } -} Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnitTestAssertionOddities.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnitTestAssertionOddities.java (rev 0) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnitTestAssertionOddities.java 2015-08-16 23:23:57 UTC (rev 1781) @@ -0,0 +1,359 @@ +/* + * fb-contrib - Auxiliary detectors for Java programs + * Copyright (C) 2005-2015 Dave Brosius + * + * This library 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 library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package com.mebigfatguy.fbcontrib.detect; + +import org.apache.bcel.Repository; +import org.apache.bcel.classfile.AnnotationEntry; +import org.apache.bcel.classfile.Code; +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.Type; + +import com.mebigfatguy.fbcontrib.utils.BugType; +import com.mebigfatguy.fbcontrib.utils.TernaryPatcher; + +import edu.umd.cs.findbugs.BugInstance; +import edu.umd.cs.findbugs.BugReporter; +import edu.umd.cs.findbugs.BytecodeScanningDetector; +import edu.umd.cs.findbugs.OpcodeStack; +import edu.umd.cs.findbugs.OpcodeStack.CustomUserValue; +import edu.umd.cs.findbugs.ba.ClassContext; + +/** looks for odd uses of the Assert class of the JUnit and TestNG framework */ +@CustomUserValue +public class UnitTestAssertionOddities extends BytecodeScanningDetector { + private enum State { + SAW_NOTHING, SAW_IF_ICMPNE, SAW_ICONST_1, SAW_GOTO, SAW_ICONST_0, SAW_EQUALS + }; + + private enum TestFrameworkType { + UNKNOWN, JUNIT, TESTNG; + } + + private static final String TESTCASE_CLASS = "junit.framework.TestCase"; + private static final String TEST_CLASS = "org.junit.Test"; + private static final String TEST_ANNOTATION_SIGNATURE = "Lorg/junit/Test;"; + private static final String OLD_ASSERT_CLASS = "junit/framework/Assert"; + private static final String NEW_ASSERT_CLASS = "org/junit/Assert"; + + private static final String TESTNG_CLASS = "org.testng.annotations.Test"; + private static final String TESTNG_ANNOTATION_SIGNATURE = "Lorg/testng/annotations/Test;"; + private static final String NG_ASSERT_CLASS = "org/testng/Assert"; + private static final String NG_JUNIT_ASSERT_CLASS = "org/testng/AssertJUnit"; + + private BugReporter bugReporter; + private JavaClass testCaseClass; + private JavaClass testAnnotationClass; + private JavaClass testNGAnnotationClass; + private OpcodeStack stack; + private boolean isTestCaseDerived; + private boolean isAnnotationCapable; + private String clsName; + private boolean sawAssert; + private State state; + private TestFrameworkType frameworkType; + + /** + * constructs a JOA detector given the reporter to report bugs on + * + * @param bugReporter + * the sync of bug reports + */ + public UnitTestAssertionOddities(BugReporter bugReporter) { + this.bugReporter = bugReporter; + + try { + testCaseClass = Repository.lookupClass(TESTCASE_CLASS); + } catch (ClassNotFoundException cnfe) { + testCaseClass = null; + } + try { + testAnnotationClass = Repository.lookupClass(TEST_CLASS); + } catch (ClassNotFoundException cnfe) { + testAnnotationClass = null; + } + + try { + testNGAnnotationClass = Repository.lookupClass(TESTNG_CLASS); + } catch (ClassNotFoundException cnfe) { + testNGAnnotationClass = null; + } + } + + /** + * override the visitor to see if this class could be a test class + * + * @param classContext + * the context object of the currently parsed class + */ + @Override + public void visitClassContext(ClassContext classContext) { + try { + JavaClass cls = classContext.getJavaClass(); + clsName = cls.getClassName().replace('.', '/'); + isTestCaseDerived = (testCaseClass != null) && cls.instanceOf(testCaseClass); + isAnnotationCapable = (cls.getMajor() >= 5) && ((testAnnotationClass != null) || (testNGAnnotationClass != null)); + if (isTestCaseDerived || isAnnotationCapable) { + stack = new OpcodeStack(); + super.visitClassContext(classContext); + } + } catch (ClassNotFoundException cnfe) { + bugReporter.reportMissingClass(cnfe); + } finally { + stack = null; + } + } + + @Override + public void visitCode(Code obj) { + Method m = getMethod(); + frameworkType = isTestCaseDerived && m.getName().startsWith("test") ? TestFrameworkType.JUNIT : TestFrameworkType.UNKNOWN; + + if ((frameworkType == TestFrameworkType.UNKNOWN) && isAnnotationCapable) { + AnnotationEntry[] annotations = m.getAnnotationEntries(); + if (annotations != null) { + for (AnnotationEntry annotation : annotations) { + String annotationType = annotation.getAnnotationType(); + if (annotation.isRuntimeVisible()) { + if (TEST_ANNOTATION_SIGNATURE.equals(annotationType)) { + frameworkType = TestFrameworkType.JUNIT; + break; + } else if (TESTNG_ANNOTATION_SIGNATURE.equals(annotationType)) { + frameworkType = TestFrameworkType.TESTNG; + break; + } + } + } + } + } + + if (frameworkType != TestFrameworkType.UNKNOWN) { + stack.resetForMethodEntry(this); + state = State.SAW_NOTHING; + sawAssert = false; + super.visitCode(obj); + + if (!sawAssert) { + bugReporter.reportBug(new BugInstance(this, frameworkType == TestFrameworkType.JUNIT ? BugType.UTAO_JUNIT_ASSERTION_ODDITIES_NO_ASSERT.name() + : BugType.UTAO_TESTNG_ASSERTION_ODDITIES_NO_ASSERT.name(), LOW_PRIORITY).addClass(this).addMethod(this)); + } + } + } + + @Override + public void sawOpcode(int seen) { + String userValue = null; + + try { + stack.precomputation(this); + + if (seen == INVOKESTATIC) { + String clsName = getClassConstantOperand(); + if (OLD_ASSERT_CLASS.equals(clsName) || NEW_ASSERT_CLASS.equals(clsName) || NG_JUNIT_ASSERT_CLASS.equals(clsName)) { + sawAssert = true; + String methodName = getNameConstantOperand(); + if ("assertEquals".equals(methodName)) { + String signature = getSigConstantOperand(); + Type[] argTypes = Type.getArgumentTypes(signature); + if ((argTypes.length == 2) || (argTypes.length == 3)) { + + if (stack.getStackDepth() >= 2) { + OpcodeStack.Item expectedItem = stack.getStackItem(1); + Object cons1 = expectedItem.getConstant(); + if ((cons1 != null) && argTypes[argTypes.length - 1].equals(Type.BOOLEAN) + && argTypes[argTypes.length - 2].equals(Type.BOOLEAN)) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_JUNIT_ASSERTION_ODDITIES_BOOLEAN_ASSERT.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + return; + } + OpcodeStack.Item item0 = stack.getStackItem(0); + if ((item0.getConstant() != null) && (expectedItem.getConstant() == null) + && ((argTypes.length == 2) || !isFloatingPtPrimitive(item0.getSignature()))) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_JUNIT_ASSERTION_ODDITIES_ACTUAL_CONSTANT.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + return; + } + if (argTypes[argTypes.length - 1].equals(Type.OBJECT) && argTypes[argTypes.length - 2].equals(Type.OBJECT)) { + if ("Ljava/lang/Double;".equals(item0.getSignature()) && "Ljava/lang/Double;".equals(expectedItem.getSignature())) { + bugReporter + .reportBug(new BugInstance(this, BugType.UTAO_JUNIT_ASSERTION_ODDITIES_INEXACT_DOUBLE.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + return; + } + } + } + } + } else if ("assertNotNull".equals(methodName)) { + if (stack.getStackDepth() > 0) { + if ("valueOf".equals(stack.getStackItem(0).getUserValue())) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_JUNIT_ASSERTION_ODDITIES_IMPOSSIBLE_NULL.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + } + } + } else if ("assertTrue".equals(methodName)) { + if ((state == State.SAW_ICONST_0) || (state == State.SAW_EQUALS)) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_JUNIT_ASSERTION_ODDITIES_USE_ASSERT_EQUALS.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + } + } + } else if (NG_ASSERT_CLASS.equals(clsName)) { + sawAssert = true; + String methodName = getNameConstantOperand(); + if ("assertEquals".equals(methodName)) { + String signature = getSigConstantOperand(); + Type[] argTypes = Type.getArgumentTypes(signature); + if ((argTypes.length == 2) || (argTypes.length == 3)) { + + OpcodeStack.Item actualItem, expectedItem; + if ((argTypes.length == 2) && (stack.getStackDepth() >= 2)) { + expectedItem = stack.getStackItem(0); + actualItem = stack.getStackItem(1); + } else if ((argTypes.length == 3) && (stack.getStackDepth() >= 3)) { + expectedItem = stack.getStackItem(1); + actualItem = stack.getStackItem(2); + } else { + return; + } + + Object cons1 = expectedItem.getConstant(); + if ((cons1 != null) && argTypes[argTypes.length - 1].equals(Type.BOOLEAN) && argTypes[argTypes.length - 2].equals(Type.BOOLEAN)) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_TESTNG_ASSERTION_ODDITIES_BOOLEAN_ASSERT.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + return; + } + if ((actualItem.getConstant() != null) && (expectedItem.getConstant() == null) + && ((argTypes.length == 2) || !isFloatingPtPrimitive(actualItem.getSignature()))) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_TESTNG_ASSERTION_ODDITIES_ACTUAL_CONSTANT.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + return; + } + if (argTypes[argTypes.length - 1].equals(Type.OBJECT) && argTypes[argTypes.length - 2].equals(Type.OBJECT)) { + if ("Ljava/lang/Double;".equals(actualItem.getSignature()) && "Ljava/lang/Double;".equals(expectedItem.getSignature())) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_TESTNG_ASSERTION_ODDITIES_INEXACT_DOUBLE.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + return; + } + } + } + } else if ("assertNotNull".equals(methodName)) { + if (stack.getStackDepth() > 0) { + if ("valueOf".equals(stack.getStackItem(0).getUserValue())) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_TESTNG_ASSERTION_ODDITIES_IMPOSSIBLE_NULL.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + } + } + } else if ("assertTrue".equals(methodName)) { + if ((state == State.SAW_ICONST_0) || (state == State.SAW_EQUALS)) { + bugReporter.reportBug(new BugInstance(this, BugType.UTAO_TESTNG_ASSERTION_ODDITIES_USE_ASSERT_EQUALS.name(), NORMAL_PRIORITY) + .addClass(this).addMethod(this).addSourceLine(this)); + } + } + } else { + String methodName = getNameConstantOperand(); + String sig = getSigConstantOperand(); + if (clsName.startsWith("java/lang/") && "valueOf".equals(methodName) && (sig.indexOf(")Ljava/lang/") >= 0)) { + userValue = "valueOf"; + } + } + } else if (seen == ATHROW) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item item = stack.getStackItem(0); + String throwClass = item.getSignature(); + if ("Ljava/lang/AssertionError;".equals(throwClass)) { + bugReporter.reportBug(new BugInstance(this, + frameworkType == TestFrameworkType.JUNIT ? BugType.UTAO_JUNIT_ASSERTION_ODDITIES_ASSERT_USED.name() + : BugType.UTAO_TESTNG_ASSERTION_ODDITIES_ASSERT_USED.name(), + NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this)); + sawAssert = true; + } + } + } + + switch (state) { + case SAW_NOTHING: + case SAW_EQUALS: + if (seen == IF_ICMPNE) { + state = State.SAW_IF_ICMPNE; + } else { + state = State.SAW_NOTHING; + } + break; + + case SAW_IF_ICMPNE: + if (seen == ICONST_1) { + state = State.SAW_ICONST_1; + } else { + state = State.SAW_NOTHING; + } + break; + + case SAW_ICONST_1: + if (seen == GOTO) { + state = State.SAW_GOTO; + } else { + state = State.SAW_NOTHING; + } + break; + + case SAW_GOTO: + if (seen == ICONST_0) { + state = State.SAW_ICONST_0; + } else { + state = State.SAW_NOTHING; + } + break; + + default: + state = State.SAW_NOTHING; + break; + } + + if ((seen == INVOKEVIRTUAL) || (seen == INVOKESTATIC) || (seen == INVOKESPECIAL)) { + String lcName = getNameConstantOperand().toLowerCase(); + if (seen == INVOKEVIRTUAL) { + String sig = getSigConstantOperand(); + if ("equals".equals(lcName) && "(Ljava/lang/Object;)Z".equals(sig)) { + state = State.SAW_EQUALS; + } + } + + // assume that if you call a method in the unit test class, or + // call a method with assert of verify in them + // it's possibly doing asserts for you. Yes this is a hack + + if (clsName.equals(getClassConstantOperand()) || lcName.contains("assert") || lcName.contains("verify")) { + sawAssert = true; + } + } + + } finally { + TernaryPatcher.pre(stack, seen); + stack.sawOpcode(this, seen); + TernaryPatcher.post(stack, seen); + if ((userValue != null) && (stack.getStackDepth() > 0)) { + OpcodeStack.Item item = stack.getStackItem(0); + item.setUserValue(userValue); + } + } + } + + public boolean isFloatingPtPrimitive(String signature) { + return "D".equals(signature) || "F".equals(signature); + } +} Property changes on: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnitTestAssertionOddities.java ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |