diff --git a/recaf-api/src/main/java/software/coley/recaf/services/callgraph/CallGraph.java b/recaf-api/src/main/java/software/coley/recaf/services/callgraph/CallGraph.java index 41e978ae7..1bbe7bd50 100644 --- a/recaf-api/src/main/java/software/coley/recaf/services/callgraph/CallGraph.java +++ b/recaf-api/src/main/java/software/coley/recaf/services/callgraph/CallGraph.java @@ -85,6 +85,14 @@ private void setActive(boolean active) { } } + /** + * @return Observable boolean tracking the state of the call-graph's parsing of the current workspace. + */ + @Nonnull + public ObservableBoolean isReady() { + return isReady; + } + /** * @param classInfo * Class to wrap. diff --git a/recaf-core/src/test/java/software/coley/recaf/services/callgraph/CallGraphTest.java b/recaf-core/src/test/java/software/coley/recaf/services/callgraph/CallGraphTest.java index c5d4404c0..6c2e5537a 100644 --- a/recaf-core/src/test/java/software/coley/recaf/services/callgraph/CallGraphTest.java +++ b/recaf-core/src/test/java/software/coley/recaf/services/callgraph/CallGraphTest.java @@ -1,6 +1,8 @@ package software.coley.recaf.services.callgraph; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import software.coley.observables.ObservableBoolean; import software.coley.recaf.info.JvmClassInfo; import software.coley.recaf.path.ClassPathNode; import software.coley.recaf.test.TestClassUtils; @@ -9,6 +11,7 @@ import software.coley.recaf.workspace.model.Workspace; import java.io.IOException; +import java.util.concurrent.TimeUnit; import static org.junit.jupiter.api.Assertions.*; @@ -17,6 +20,7 @@ */ class CallGraphTest { @Test + @Timeout(10) void testCalleeCallerRelation() throws IOException { Workspace workspace = TestClassUtils.fromBundle(TestClassUtils.fromClasses( StringConsumer.class, @@ -31,6 +35,15 @@ void testCalleeCallerRelation() throws IOException { JvmClassInfo functionClass = pathFunc.getValue().asJvmClass(); CallGraph graph = new CallGraph(new CallGraphConfig(), workspace); + + // Need to wait until async population of graph contents is done. + ObservableBoolean ready = graph.isReady(); + assertDoesNotThrow(() ->{ + while (!ready.getValue()) { + Thread.sleep(100); + } + }); + ClassMethodsContainer containerMain = graph.getClassMethodsContainer(mainClass); ClassMethodsContainer containerFunction = graph.getClassMethodsContainer(functionClass);