forked from spotbugs/spotbugs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixing spotbugs#3159 - Method call graph ignores constructors and non…
…-parametric void methods (spotbugs#3160) * Add failing test (spotbugs#3159) * Call graph must include also constuctors and other non-parametric void methods. All these methods are missing to be properly sorted by TopologicalSort (spotbugs#3159) * Fix test class to be package private (spotbugs#3159) * Simplify. The private static method cannot be called from other places anyway (spotbugs#3159) * Isolate test data into an inner class (spotbugs#3159) * Refactor test class to use @beforeeach and @AfterEach (spotbugs#3159) * Another test for testing a shortcut in the call graph (spotbugs#3159) * Update CHANGELOG.md (spotbugs#3159) --------- Co-authored-by: Jeremy Landis <jeremylandis@hotmail.com>
- Loading branch information
Showing
4 changed files
with
198 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
spotbugs-tests/src/test/java/edu/umd/cs/findbugs/classfile/MethodsCallOrderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package edu.umd.cs.findbugs.classfile; | ||
|
||
import edu.umd.cs.findbugs.*; | ||
import edu.umd.cs.findbugs.ba.AnalysisContext; | ||
import edu.umd.cs.findbugs.ba.ClassContext; | ||
import edu.umd.cs.findbugs.classfile.impl.ClassFactory; | ||
import org.apache.bcel.classfile.Method; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.fail; | ||
|
||
/** | ||
* @author Tomas Polesovsky | ||
*/ | ||
class MethodsCallOrderTest { | ||
|
||
private PrintingBugReporter bugReporter; | ||
private IClassFactory classFactory; | ||
private IClassPath classPath; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
bugReporter = new PrintingBugReporter(); | ||
classFactory = ClassFactory.instance(); | ||
classPath = classFactory.createClassPath(); | ||
|
||
IAnalysisCache analysisCache = classFactory.createAnalysisCache(classPath, bugReporter); | ||
Global.setAnalysisCacheForCurrentThread(analysisCache); | ||
FindBugs2.registerBuiltInAnalysisEngines(analysisCache); | ||
|
||
Project project = new Project(); | ||
AnalysisContext analysisContext = new AnalysisContext(project); | ||
AnalysisContext.setCurrentAnalysisContext(analysisContext); | ||
} | ||
|
||
@AfterEach | ||
void tearDown() { | ||
Global.setAnalysisCacheForCurrentThread(null); | ||
} | ||
|
||
void load(String codeBaseLocation) throws CheckedAnalysisException, IOException, InterruptedException { | ||
IClassPathBuilder builder = classFactory.createClassPathBuilder(bugReporter); | ||
builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(codeBaseLocation), true); | ||
builder.build(classPath, new NoOpFindBugsProgress()); | ||
} | ||
|
||
@Test | ||
void testSimpleTest() { | ||
try { | ||
load("../spotbugsTestCases/build/classes/java/main/MethodsCallOrder$SimpleTest.class"); | ||
} catch (CheckedAnalysisException | IOException | InterruptedException e) { | ||
fail("Unable to add MethodsCallOrder$SimpleTest.class to the build: " + e.getMessage(), e); | ||
} | ||
|
||
ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptor("MethodsCallOrder$SimpleTest"); | ||
|
||
List<String> actual = new ArrayList<>(); | ||
|
||
try { | ||
ClassContext classContext = Global.getAnalysisCache().getClassAnalysis(ClassContext.class, classDescriptor); | ||
for (Method method : classContext.getMethodsInCallOrder()) { | ||
actual.add(method.getName() + method.getSignature()); | ||
} | ||
} catch (CheckedAnalysisException e) { | ||
fail("Unable to get ClassContext analysis for MethodsCallOrder: " + e.getMessage(), e); | ||
} | ||
|
||
List<String> expected = Arrays.asList(new String[] { | ||
"method4()V", | ||
"method3()V", | ||
"method2()V", | ||
"method1()V", | ||
"<init>(Ljava/lang/Object;)V", | ||
"<init>()V", | ||
"staticMethod4()V", | ||
"staticMethod3()V", | ||
"staticMethod2()V", | ||
"staticMethod1()V", | ||
"<clinit>()V" }); | ||
|
||
assertEquals(expected, actual); | ||
} | ||
|
||
@Test | ||
void testShortcutPathTest() { | ||
try { | ||
load("../spotbugsTestCases/build/classes/java/main/MethodsCallOrder$ShortcutPathTest.class"); | ||
} catch (CheckedAnalysisException | IOException | InterruptedException e) { | ||
fail("Unable to add MethodsCallOrder$SimpleTest.class to the build: " + e.getMessage(), e); | ||
} | ||
|
||
ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptor("MethodsCallOrder$ShortcutPathTest"); | ||
|
||
List<String> actual = new ArrayList<>(); | ||
|
||
try { | ||
ClassContext classContext = Global.getAnalysisCache().getClassAnalysis(ClassContext.class, classDescriptor); | ||
for (Method method : classContext.getMethodsInCallOrder()) { | ||
actual.add(method.getName() + method.getSignature()); | ||
} | ||
} catch (CheckedAnalysisException e) { | ||
fail("Unable to get ClassContext analysis for MethodsCallOrder: " + e.getMessage(), e); | ||
} | ||
|
||
List<String> expected = Arrays.asList(new String[] { | ||
"methodC()V", | ||
"methodB()V", | ||
"methodA()V", | ||
"<init>()V" | ||
}); | ||
|
||
assertEquals(expected, actual); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* @author Tomas Polesovsky | ||
*/ | ||
public class MethodsCallOrder { | ||
|
||
static class SimpleTest { | ||
static { | ||
staticMethod1(); | ||
} | ||
|
||
public static void staticMethod1() { | ||
staticMethod2(); | ||
} | ||
|
||
public static void staticMethod2() { | ||
staticMethod3(); | ||
} | ||
|
||
public static void staticMethod3() { | ||
staticMethod4(); | ||
} | ||
|
||
public static void staticMethod4() { | ||
new MethodsCallOrder.SimpleTest(); | ||
} | ||
|
||
public SimpleTest() { | ||
this(null); | ||
} | ||
|
||
public SimpleTest(Object o) { | ||
method1(); | ||
} | ||
|
||
public void method1() { | ||
method2(); | ||
} | ||
|
||
public void method2() { | ||
method3(); | ||
} | ||
|
||
public void method3() { | ||
method4(); | ||
} | ||
|
||
public void method4() { | ||
System.out.println("HERE WE GO!"); | ||
} | ||
} | ||
|
||
static class ShortcutPathTest { | ||
public ShortcutPathTest() { | ||
methodA(); | ||
} | ||
|
||
public void methodA(){ | ||
if (System.currentTimeMillis() % 2 == 1) { | ||
methodB(); | ||
} else { | ||
methodC(); | ||
} | ||
} | ||
|
||
public void methodB(){ | ||
methodC(); | ||
} | ||
|
||
public void methodC(){ | ||
System.out.println("HERE WE GO!"); | ||
} | ||
} | ||
|
||
} |