Skip to content

Commit 300ba05

Browse files
committed
add tests
1 parent 83149d3 commit 300ba05

20 files changed

Lines changed: 1693 additions & 2 deletions

client-java/instrumentation/pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@
181181
<dependency>
182182
<groupId>com.google.guava</groupId>
183183
<artifactId>guava</artifactId>
184-
<scope>test</scope>
185184
</dependency>
186185
<dependency>
187186
<groupId>org.mongodb</groupId>

client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/dynamosa/graphs/GraphPool.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.evomaster.client.java.instrumentation.dynamosa.graphs;
66

77
import org.evomaster.client.java.instrumentation.ClassesToExclude;
8+
import com.google.common.annotations.VisibleForTesting;
89
import org.evomaster.client.java.instrumentation.dynamosa.DynamosaConfig;
910
import org.evomaster.client.java.instrumentation.dynamosa.graphs.cdg.ControlDependenceGraph;
1011
import org.evomaster.client.java.instrumentation.dynamosa.graphs.cfg.ActualControlFlowGraph;
@@ -66,6 +67,14 @@ public static GraphPool getInstance(ClassLoader classLoader) {
6667
return instanceMap.get(classLoader);
6768
}
6869

70+
@VisibleForTesting
71+
public static void resetForTesting(ClassLoader classLoader) {
72+
instanceMap.remove(classLoader);
73+
synchronized (exportLock) {
74+
exportedCdgs.clear();
75+
}
76+
}
77+
6978
/**
7079
* Complete control flow graph, contains each bytecode instruction, each
7180
* label and line number node Think of the direct Known Subclasses of

client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/dynamosa/graphs/cdg/ControlDependenceGraph.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,13 @@ public String getClassName() {
207207
public String getMethodName() {
208208
return methodName;
209209
}
210+
211+
/**
212+
* Exposes the underlying {@link ActualControlFlowGraph}
213+
*
214+
* @return the CFG used to build this CDG.
215+
*/
216+
public ActualControlFlowGraph getCFG() {
217+
return cfg;
218+
}
210219
}

client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/dynamosa/graphs/cdg/DominatorTree.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ private void createDominatorTree() {
104104
// check tree is connected
105105
if (!isConnected())
106106
throw new IllegalStateException("dominator tree expected to be connected");
107-
// TODO more sanity checks - no one likes to be insane ;)
108107
}
109108

110109
private void computeDominatorFrontiers(DominatorNode<V> currentNode) {

client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/dynamosa/graphs/cfg/branch/BranchPool.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package org.evomaster.client.java.instrumentation.dynamosa.graphs.cfg.branch;
66

7+
import com.google.common.annotations.VisibleForTesting;
78
import org.evomaster.client.java.instrumentation.dynamosa.graphs.cfg.BytecodeInstruction;
89
import org.evomaster.client.java.instrumentation.shared.ObjectiveNaming;
910
import org.evomaster.client.java.utils.SimpleLogger;
@@ -43,6 +44,16 @@ public static BranchPool getInstance(ClassLoader classLoader) {
4344

4445
return instanceMap.get(classLoader);
4546
}
47+
48+
@VisibleForTesting
49+
public static void resetForTesting(ClassLoader classLoader) {
50+
BranchPool pool = instanceMap.remove(classLoader);
51+
if (pool != null) {
52+
pool.registeredNormalBranches.clear();
53+
pool.branchOrdinalCounters.clear();
54+
pool.branchCounter = 0;
55+
}
56+
}
4657
// fill the pool
4758

4859

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package org.evomaster.client.java.instrumentation.dynamosa.graphs;
2+
3+
import org.evomaster.client.java.instrumentation.dynamosa.graphs.cfg.ActualControlFlowGraph;
4+
import org.evomaster.client.java.instrumentation.dynamosa.graphs.cfg.BytecodeInstruction;
5+
import org.evomaster.client.java.instrumentation.dynamosa.graphs.cfg.RawControlFlowGraph;
6+
import org.junit.jupiter.api.AfterEach;
7+
import org.junit.jupiter.api.Test;
8+
import org.objectweb.asm.Opcodes;
9+
import org.objectweb.asm.tree.InsnNode;
10+
11+
import static org.junit.jupiter.api.Assertions.*;
12+
13+
class GraphPoolTest {
14+
15+
private static final ClassLoader TEST_LOADER = GraphPoolTest.class.getClassLoader();
16+
private static final String CLASS_NAME = "com.example.GraphPoolFixture";
17+
private static final String METHOD_NAME = "sample()V";
18+
19+
// Custom class loader that intentionally throws an exception when the ExecutionTracer class is loaded.
20+
private ClassLoader blockingLoader;
21+
22+
@AfterEach
23+
void resetPools() {
24+
GraphPool.resetForTesting(TEST_LOADER);
25+
if (blockingLoader != null) {
26+
GraphPool.resetForTesting(blockingLoader);
27+
blockingLoader = null;
28+
}
29+
}
30+
31+
@Test
32+
void getInstanceReturnsSingletonPerLoader() {
33+
GraphPool first = GraphPool.getInstance(TEST_LOADER);
34+
GraphPool second = GraphPool.getInstance(TEST_LOADER);
35+
assertSame(first, second);
36+
37+
ClassLoader otherLoader = new SimpleDelegatingClassLoader(TEST_LOADER);
38+
GraphPool third = GraphPool.getInstance(otherLoader);
39+
assertNotSame(first, third);
40+
GraphPool.resetForTesting(otherLoader);
41+
}
42+
43+
@Test
44+
void getRawCFGReturnsNullWhenClassIsUnknown() {
45+
GraphPool pool = GraphPool.getInstance(TEST_LOADER);
46+
assertNull(pool.getRawCFG("unknown.class", METHOD_NAME));
47+
}
48+
49+
@Test
50+
void registerRawCFGStoresGraphUntilCleared() {
51+
GraphPool pool = GraphPool.getInstance(TEST_LOADER);
52+
RawControlFlowGraph raw = simpleRawGraph(TEST_LOADER, CLASS_NAME, METHOD_NAME);
53+
54+
// Test that registerRawCFG and GetRawCFG works correctly
55+
pool.registerRawCFG(raw);
56+
assertSame(raw, pool.getRawCFG(CLASS_NAME, METHOD_NAME));
57+
58+
// Test that clear works correctly
59+
pool.clear(CLASS_NAME, METHOD_NAME);
60+
assertNull(pool.getRawCFG(CLASS_NAME, METHOD_NAME));
61+
}
62+
63+
@Test
64+
void registerActualCFGSkipsCdgWhenInstrumentationDisabled() {
65+
blockingLoader = new NoExecutionTracerClassLoader(GraphPoolTest.class.getClassLoader());
66+
GraphPool pool = GraphPool.getInstance(blockingLoader);
67+
RawControlFlowGraph raw = simpleRawGraph(blockingLoader, CLASS_NAME, METHOD_NAME);
68+
ActualControlFlowGraph cfg = new ActualControlFlowGraph(raw);
69+
70+
pool.registerActualCFG(cfg);
71+
72+
assertSame(cfg, pool.getActualCFG(CLASS_NAME, METHOD_NAME));
73+
assertNull(pool.getCDG(CLASS_NAME, METHOD_NAME));
74+
}
75+
76+
@Test
77+
void resetForTestingDropsCachedInstancesAndGraphs() {
78+
GraphPool pool = GraphPool.getInstance(TEST_LOADER);
79+
RawControlFlowGraph raw = simpleRawGraph(TEST_LOADER, CLASS_NAME, METHOD_NAME);
80+
pool.registerRawCFG(raw);
81+
82+
GraphPool.resetForTesting(TEST_LOADER);
83+
84+
GraphPool fresh = GraphPool.getInstance(TEST_LOADER);
85+
assertNotSame(pool, fresh);
86+
assertNull(fresh.getRawCFG(CLASS_NAME, METHOD_NAME));
87+
}
88+
89+
private static RawControlFlowGraph simpleRawGraph(ClassLoader loader,
90+
String className,
91+
String methodName) {
92+
TestRawControlFlowGraph raw = new TestRawControlFlowGraph(loader, className, methodName);
93+
94+
BytecodeInstruction entry = instruction(loader, className, methodName, 0, Opcodes.NOP);
95+
BytecodeInstruction body = instruction(loader, className, methodName, 1, Opcodes.NOP);
96+
BytecodeInstruction exit = instruction(loader, className, methodName, 2, Opcodes.RETURN);
97+
98+
raw.addVertex(entry);
99+
raw.addVertex(body);
100+
raw.addVertex(exit);
101+
102+
raw.connect(entry, body);
103+
raw.connect(body, exit);
104+
105+
return raw;
106+
}
107+
108+
private static BytecodeInstruction instruction(ClassLoader loader,
109+
String className,
110+
String methodName,
111+
int instructionId,
112+
int opcode) {
113+
BytecodeInstruction instruction = new BytecodeInstruction(
114+
loader,
115+
className,
116+
methodName,
117+
instructionId,
118+
instructionId,
119+
new InsnNode(opcode)
120+
);
121+
instruction.setLineNumber(100 + instructionId);
122+
return instruction;
123+
}
124+
125+
private static final class TestRawControlFlowGraph extends RawControlFlowGraph {
126+
private TestRawControlFlowGraph(ClassLoader loader, String className, String methodName) {
127+
super(loader, className, methodName, Opcodes.ACC_PUBLIC);
128+
}
129+
130+
private void connect(BytecodeInstruction src, BytecodeInstruction dst) {
131+
super.addEdge(src, dst, false);
132+
}
133+
}
134+
135+
private static class SimpleDelegatingClassLoader extends ClassLoader {
136+
private SimpleDelegatingClassLoader(ClassLoader parent) {
137+
super(parent);
138+
}
139+
}
140+
141+
private static class NoExecutionTracerClassLoader extends ClassLoader {
142+
private NoExecutionTracerClassLoader(ClassLoader parent) {
143+
super(parent);
144+
}
145+
146+
@Override
147+
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
148+
if ("org.evomaster.client.java.instrumentation.staticstate.ExecutionTracer".equals(name)) {
149+
throw new ClassNotFoundException(name);
150+
}
151+
return super.loadClass(name, resolve);
152+
}
153+
}
154+
}
155+

0 commit comments

Comments
 (0)