Skip to content

Commit 01a5699

Browse files
committed
Merge remote-tracking branch 'origin/refactor-for-testing'
2 parents 69e208e + b7d55d5 commit 01a5699

File tree

8 files changed

+182
-55
lines changed

8 files changed

+182
-55
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: build
33
on:
44
push:
55
pull_request:
6+
workflow_dispatch:
67

78
jobs:
89
build:

pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@
117117
<scope>compile</scope>
118118
</dependency>
119119

120+
<dependency>
121+
<groupId>org.junit.jupiter</groupId>
122+
<artifactId>junit-jupiter-engine</artifactId>
123+
<version>5.9.2</version>
124+
<scope>test</scope>
125+
</dependency>
126+
127+
<dependency>
128+
<groupId>org.mockito</groupId>
129+
<artifactId>mockito-core</artifactId>
130+
<version>5.8.0</version>
131+
<scope>test</scope>
132+
</dependency>
133+
120134
</dependencies>
121135
<properties>
122136
<maven.compiler.source>17</maven.compiler.source>
@@ -160,6 +174,12 @@
160174
</execution>
161175
</executions>
162176
</plugin>
177+
178+
<plugin>
179+
<groupId>org.apache.maven.plugins</groupId>
180+
<artifactId>maven-surefire-plugin</artifactId>
181+
<version>3.2.5</version>
182+
</plugin>
163183
</plugins>
164184
</build>
165185
</project>

src/main/java/Main.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import api.GoblintService;
77
import api.GoblintServiceLauncher;
88
import api.messages.params.Params;
9+
import goblintserver.GoblintConfWatcher;
910
import goblintserver.GoblintServer;
1011
import gobpie.GobPieConfReader;
1112
import gobpie.GobPieConfiguration;
@@ -17,7 +18,10 @@
1718
import org.eclipse.lsp4j.MessageParams;
1819
import org.eclipse.lsp4j.MessageType;
1920
import org.eclipse.lsp4j.jsonrpc.messages.Either;
21+
import util.FileWatcher;
22+
2023
import java.io.File;
24+
import java.nio.file.Path;
2125

2226
public class Main {
2327

@@ -40,8 +44,11 @@ public static void main(String... args) {
4044
// Connect GoblintService and read configuration
4145
GoblintService goblintService = connectGoblintService(magpieServer, gobpieConfiguration, goblintServer);
4246

47+
// Create file watcher for Goblint configuration
48+
GoblintConfWatcher goblintConfWatcher = getGoblintConfWatcher(magpieServer, goblintService, gobpieConfiguration);
49+
4350
// Add analysis
44-
addAnalysis(magpieServer, gobpieConfiguration, goblintServer, goblintService);
51+
addAnalysis(magpieServer, gobpieConfiguration, goblintServer, goblintService, goblintConfWatcher);
4552

4653
// Launch magpieServer
4754
magpieServer.configurationDone();
@@ -123,19 +130,24 @@ private static GoblintService connectGoblintService(MagpieServer magpieServer, G
123130
return goblintService;
124131
}
125132

133+
private static GoblintConfWatcher getGoblintConfWatcher(GoblintMagpieServer magpieServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration) {
134+
FileWatcher fileWatcher = new FileWatcher(Path.of(gobpieConfiguration.getGoblintConf()));
135+
return new GoblintConfWatcher(magpieServer, goblintService, gobpieConfiguration, fileWatcher);
136+
}
137+
126138

127139
/**
128140
* Method for creating and adding Goblint analysis to MagpieBridge server.
129141
* <p>
130142
* Creates the GoblintAnalysis classes.
131143
*/
132144
private static void addAnalysis(MagpieServer magpieServer, GobPieConfiguration gobpieConfiguration,
133-
GoblintServer goblintServer, GoblintService goblintService) {
145+
GoblintServer goblintServer, GoblintService goblintService, GoblintConfWatcher goblintConfWatcher) {
134146
// define language
135147
String language = "c";
136148

137149
// add analysis to the MagpieServer
138-
ServerAnalysis serverAnalysis = new GoblintAnalysis(magpieServer, goblintServer, goblintService, gobpieConfiguration);
150+
ServerAnalysis serverAnalysis = new GoblintAnalysis(magpieServer, goblintServer, goblintService, gobpieConfiguration, goblintConfWatcher);
139151
magpieServer.addAnalysis(Either.forLeft(serverAnalysis), language);
140152

141153
// add HTTP server for showing CFGs, only if the option is specified in the configuration

src/main/java/analysis/GoblintAnalysis.java

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import api.messages.params.AnalyzeParams;
66
import api.messages.params.Params;
77
import com.ibm.wala.classLoader.Module;
8+
import goblintserver.GoblintConfWatcher;
89
import goblintserver.GoblintServer;
910
import gobpie.GobPieConfiguration;
1011
import gobpie.GobPieException;
@@ -20,12 +21,9 @@
2021
import org.zeroturnaround.exec.InvalidExitValueException;
2122
import org.zeroturnaround.exec.ProcessExecutor;
2223
import org.zeroturnaround.exec.ProcessResult;
23-
import org.zeroturnaround.process.UnixProcess;
24-
import util.FileWatcher;
2524

2625
import java.io.File;
2726
import java.io.IOException;
28-
import java.nio.file.Path;
2927
import java.util.ArrayList;
3028
import java.util.Arrays;
3129
import java.util.Collection;
@@ -51,26 +49,22 @@
5149

5250
public class GoblintAnalysis implements ServerAnalysis {
5351

54-
private final static int SIGINT = 2;
55-
5652
private final MagpieServer magpieServer;
5753
private final GoblintServer goblintServer;
5854
private final GoblintService goblintService;
5955
private final GobPieConfiguration gobpieConfiguration;
60-
private final FileWatcher goblintConfWatcher;
61-
62-
private static boolean configValid = false;
56+
private final GoblintConfWatcher goblintConfWatcher;
6357
private static Future<?> lastAnalysisTask = null;
6458

6559
private final Logger log = LogManager.getLogger(GoblintAnalysis.class);
6660

6761

68-
public GoblintAnalysis(MagpieServer magpieServer, GoblintServer goblintServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration) {
62+
public GoblintAnalysis(MagpieServer magpieServer, GoblintServer goblintServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration, GoblintConfWatcher goblintConfWatcher) {
6963
this.magpieServer = magpieServer;
7064
this.goblintServer = goblintServer;
7165
this.goblintService = goblintService;
7266
this.gobpieConfiguration = gobpieConfiguration;
73-
this.goblintConfWatcher = new FileWatcher(Path.of(gobpieConfiguration.getGoblintConf()));
67+
this.goblintConfWatcher = goblintConfWatcher;
7468
}
7569

7670

@@ -100,7 +94,7 @@ public void analyze(Collection<? extends Module> files, AnalysisConsumer consume
10094
return;
10195
}
10296

103-
if (!goblintServer.getGoblintRunProcess().getProcess().isAlive()) {
97+
if (!goblintServer.isAlive()) {
10498
// Goblint server has crashed. Exit GobPie because without the server no analysis is possible.
10599
magpieServer.exit();
106100
return;
@@ -109,16 +103,14 @@ public void analyze(Collection<? extends Module> files, AnalysisConsumer consume
109103
if (lastAnalysisTask != null && !lastAnalysisTask.isDone()) {
110104
lastAnalysisTask.cancel(true);
111105
try {
112-
abortAnalysis();
106+
goblintServer.abortAnalysis();
113107
log.info("--------------- This analysis has been aborted -------------");
114108
} catch (IOException e) {
115109
log.error("Aborting analysis failed.");
116110
}
117111
}
118112

119-
refreshGoblintConfig();
120-
121-
if (!configValid) {
113+
if (!goblintConfWatcher.refreshGoblintConfig()) {
122114
return;
123115
}
124116

@@ -144,40 +136,6 @@ public void analyze(Collection<? extends Module> files, AnalysisConsumer consume
144136
}
145137

146138

147-
/**
148-
* Aborts the previous running analysis by sending a SIGINT signal to Goblint.
149-
*/
150-
private void abortAnalysis() throws IOException {
151-
Process goblintProcess = goblintServer.getGoblintRunProcess().getProcess();
152-
int pid = Math.toIntExact(goblintProcess.pid());
153-
UnixProcess unixProcess = new UnixProcess(pid);
154-
unixProcess.kill(SIGINT);
155-
}
156-
157-
158-
/**
159-
* Reloads Goblint config if it has been changed or is currently invalid.
160-
*/
161-
private void refreshGoblintConfig() {
162-
if (goblintConfWatcher.checkModified() || !configValid) {
163-
configValid = goblintService.reset_config()
164-
.thenCompose(_res ->
165-
goblintService.read_config(new Params(new File(gobpieConfiguration.getGoblintConf()).getAbsolutePath())))
166-
.handle((_res, ex) -> {
167-
if (ex != null) {
168-
Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
169-
String msg = "Goblint was unable to successfully read the new configuration: " + cause.getMessage();
170-
magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, msg));
171-
log.error(msg);
172-
return false;
173-
}
174-
return true;
175-
})
176-
.join();
177-
}
178-
}
179-
180-
181139
/**
182140
* The method that is triggered before each analysis.
183141
* <p>

src/main/java/api/messages/params/AnalyzeParams.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package api.messages.params;
22

3+
import java.util.Objects;
4+
35
public class AnalyzeParams {
46

57
boolean reset;
@@ -8,4 +10,16 @@ public AnalyzeParams(boolean reset) {
810
this.reset = reset;
911
}
1012

13+
@Override
14+
public boolean equals(Object o) {
15+
if (this == o) return true;
16+
if (o == null || getClass() != o.getClass()) return false;
17+
AnalyzeParams that = (AnalyzeParams) o;
18+
return reset == that.reset;
19+
}
20+
21+
@Override
22+
public int hashCode() {
23+
return Objects.hash(reset);
24+
}
1125
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package goblintserver;
2+
3+
import api.GoblintService;
4+
import api.messages.params.Params;
5+
import gobpie.GobPieConfiguration;
6+
import magpiebridge.core.MagpieServer;
7+
import org.apache.logging.log4j.LogManager;
8+
import org.apache.logging.log4j.Logger;
9+
import org.eclipse.lsp4j.MessageParams;
10+
import org.eclipse.lsp4j.MessageType;
11+
import util.FileWatcher;
12+
13+
import java.io.File;
14+
import java.nio.file.Path;
15+
import java.util.concurrent.CompletionException;
16+
17+
public class GoblintConfWatcher {
18+
19+
private final FileWatcher fileWatcher;
20+
private final MagpieServer magpieServer;
21+
private final GoblintService goblintService;
22+
private final GobPieConfiguration gobpieConfiguration;
23+
24+
public boolean configValid = false;
25+
26+
private final Logger log = LogManager.getLogger(GoblintConfWatcher.class);
27+
28+
public GoblintConfWatcher(MagpieServer magpieServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration, FileWatcher fileWatcher) {
29+
this.magpieServer = magpieServer;
30+
this.goblintService = goblintService;
31+
this.gobpieConfiguration = gobpieConfiguration;
32+
this.fileWatcher = fileWatcher;
33+
}
34+
35+
/**
36+
* Reloads Goblint config if it has been changed or is currently invalid.
37+
*/
38+
public boolean refreshGoblintConfig() {
39+
if (fileWatcher.checkModified() || !configValid) {
40+
configValid = goblintService.reset_config()
41+
.thenCompose(_res ->
42+
goblintService.read_config(new Params(new File(gobpieConfiguration.getGoblintConf()).getAbsolutePath())))
43+
.handle((_res, ex) -> {
44+
if (ex != null) {
45+
Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
46+
String msg = "Goblint was unable to successfully read the new configuration: " + cause.getMessage();
47+
magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, msg));
48+
log.error(msg);
49+
return false;
50+
}
51+
return true;
52+
})
53+
.join();
54+
}
55+
return configValid;
56+
}
57+
}

src/main/java/goblintserver/GoblintServer.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.zeroturnaround.exec.ProcessExecutor;
1313
import org.zeroturnaround.exec.StartedProcess;
1414
import org.zeroturnaround.exec.listener.ProcessListener;
15+
import org.zeroturnaround.process.UnixProcess;
1516

1617
import java.io.ByteArrayOutputStream;
1718
import java.io.File;
@@ -35,7 +36,7 @@
3536
public class GoblintServer {
3637

3738
private static final String GOBLINT_SOCKET = "goblint.sock";
38-
39+
private static final int SIGINT = 2;
3940
private final MagpieServer magpieServer;
4041
private final GobPieConfiguration configuration;
4142
private final String[] goblintRunCommand;
@@ -51,8 +52,14 @@ public GoblintServer(MagpieServer magpieServer, GobPieConfiguration configuratio
5152
this.goblintRunCommand = constructGoblintRunCommand();
5253
}
5354

54-
public StartedProcess getGoblintRunProcess() {
55-
return goblintRunProcess;
55+
/**
56+
* Aborts the previous running analysis by sending a SIGINT signal to Goblint.
57+
*/
58+
public void abortAnalysis() throws IOException {
59+
Process goblintProcess = goblintRunProcess.getProcess();
60+
int pid = Math.toIntExact(goblintProcess.pid());
61+
UnixProcess unixProcess = new UnixProcess(pid);
62+
unixProcess.kill(SIGINT);
5663
}
5764

5865
public String getGoblintSocket() {
@@ -102,6 +109,10 @@ public void startGoblintServer() {
102109
}
103110
}
104111

112+
public boolean isAlive() {
113+
return goblintRunProcess.getProcess().isAlive();
114+
}
115+
105116

106117
/**
107118
* Checks Goblint command reported version.

0 commit comments

Comments
 (0)