Skip to content

Commit 51e63e7

Browse files
committed
Add testConvertMessagesFromJson
1 parent 13a51cb commit 51e63e7

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import analysis.GoblintAnalysis;
2+
import analysis.GoblintMessagesAnalysisResult;
3+
import api.GoblintService;
4+
import api.json.GoblintMessageJsonHandler;
5+
import api.messages.GoblintAnalysisResult;
6+
import api.messages.GoblintMessagesResult;
7+
import api.messages.GoblintPosition;
8+
import api.messages.params.AnalyzeParams;
9+
import com.google.gson.Gson;
10+
import com.google.gson.reflect.TypeToken;
11+
import com.ibm.wala.util.collections.Pair;
12+
import com.ibm.wala.classLoader.Module;
13+
import goblintserver.GoblintConfWatcher;
14+
import goblintserver.GoblintServer;
15+
import gobpie.GobPieConfiguration;
16+
import magpiebridge.core.AnalysisConsumer;
17+
import magpiebridge.core.AnalysisResult;
18+
import magpiebridge.core.MagpieServer;
19+
import org.junit.jupiter.api.BeforeEach;
20+
import org.junit.jupiter.api.Test;
21+
import org.mockito.Mock;
22+
import org.mockito.Spy;
23+
24+
import java.io.File;
25+
import java.io.IOException;
26+
import java.net.URL;
27+
import java.nio.file.Files;
28+
import java.nio.file.Path;
29+
import java.util.*;
30+
import java.util.concurrent.CompletableFuture;
31+
32+
import static org.mockito.Mockito.*;
33+
34+
public class GoblintMessagesTest {
35+
36+
private Gson gson;
37+
@Mock
38+
MagpieServer magpieServer = mock(MagpieServer.class);
39+
@Mock
40+
GoblintService goblintService = mock(GoblintService.class);
41+
@Mock
42+
GobPieConfiguration gobPieConfiguration = mock(GobPieConfiguration.class);
43+
@Spy
44+
GoblintServer goblintServer = spy(new GoblintServer(magpieServer, gobPieConfiguration));
45+
@Mock
46+
GoblintConfWatcher goblintConfWatcher = mock(GoblintConfWatcher.class);
47+
GoblintAnalysis goblintAnalysis = new GoblintAnalysis(magpieServer, goblintServer, goblintService, gobPieConfiguration, goblintConfWatcher);
48+
// Mock the arguments (files and analysisConsumer) for calling the GoblintAnalyze.analyze method
49+
Collection<? extends Module> files = new ArrayDeque<>();
50+
AnalysisConsumer analysisConsumer = mock(AnalysisConsumer.class);
51+
52+
/**
53+
* Method to initialize gson to parse Goblint warnings from JSON.
54+
*/
55+
private void createGsonBuilder() {
56+
GoblintMessageJsonHandler goblintMessageJsonHandler = new GoblintMessageJsonHandler(new HashMap<>());
57+
gson = goblintMessageJsonHandler.getDefaultGsonBuilder().create();
58+
}
59+
60+
/**
61+
* A function to mock that GoblintServer is alive
62+
* and Goblint's configuration file is ok.
63+
*/
64+
private void mockGoblintServerIsAlive(GoblintServer goblintServer) {
65+
doReturn(true).when(goblintServer).isAlive();
66+
when(goblintConfWatcher.refreshGoblintConfig()).thenReturn(true);
67+
}
68+
69+
@BeforeEach
70+
public void before() {
71+
createGsonBuilder();
72+
mockGoblintServerIsAlive(goblintServer);
73+
// Mock that the command to execute is empty
74+
when(gobPieConfiguration.getPreAnalyzeCommand()).thenReturn(new String[]{});
75+
// Mock that the analyses of Goblint have started and completed
76+
when(goblintService.analyze(new AnalyzeParams(false))).thenReturn(CompletableFuture.completedFuture(new GoblintAnalysisResult()));
77+
// Mock that the incremental analysis is turned off (TODO: not sure why this is checked in reanalyze?)
78+
when(gobPieConfiguration.useIncrementalAnalysis()).thenReturn(true);
79+
}
80+
81+
// TODO: this can be generalized later to pass the file name as an argument
82+
private List<GoblintMessagesResult> readGoblintResponseJson() throws IOException {
83+
String messages = Files.readString(
84+
Path.of(GoblintMessagesTest.class.getResource("messagesResponse.json").getPath())
85+
);
86+
return gson.fromJson(messages, new TypeToken<List<GoblintMessagesResult>>() {}.getType());
87+
}
88+
89+
90+
/**
91+
* Mock test to ensure that the Goblint warnings received from a response in JSON format
92+
* are correctly converted to {@link AnalysisResult} objects
93+
* and passed to {@link MagpieServer} via {@link AnalysisConsumer}.
94+
*
95+
* @throws IOException when reading messagesResponse.json from resources fails.
96+
*/
97+
@Test
98+
public void testConvertMessagesFromJson() throws IOException {
99+
List<GoblintMessagesResult> goblintMessagesResults = readGoblintResponseJson();
100+
101+
when(goblintService.messages()).thenReturn(CompletableFuture.completedFuture(goblintMessagesResults));
102+
when(gobPieConfiguration.showCfg()).thenReturn(false);
103+
104+
goblintAnalysis.analyze(files, analysisConsumer, true);
105+
106+
URL emptyUrl = new File("").toURI().toURL();
107+
GoblintPosition defaultPos = new GoblintPosition(1, 1, 1, 1, emptyUrl);
108+
109+
List<AnalysisResult> response = new ArrayList<>();
110+
response.add(
111+
new GoblintMessagesAnalysisResult(
112+
defaultPos,
113+
"[Deadcode] Logical lines of code (LLoC) summary",
114+
"Info",
115+
List.of(
116+
Pair.make(defaultPos, "live: 12"),
117+
Pair.make(defaultPos, "dead: 0"),
118+
Pair.make(defaultPos, "total lines: 12")
119+
)
120+
)
121+
);
122+
response.add(
123+
new GoblintMessagesAnalysisResult(
124+
new GoblintPosition(4, 4, 4, 12, emptyUrl),
125+
"[Race] Memory location myglobal (race with conf. 110)",
126+
"Warning",
127+
List.of(
128+
Pair.make(
129+
new GoblintPosition(10, 10, 2, 21, emptyUrl),
130+
"write with [mhp:{tid=[main, t_fun@src/example.c:17:3-17:40#top]}, lock:{mutex1}, thread:[main, t_fun@src/example.c:17:3-17:40#top]] (conf. 110) (exp: & myglobal)"
131+
),
132+
Pair.make(
133+
new GoblintPosition(19, 19, 2, 21, emptyUrl),
134+
"write with [mhp:{tid=[main]; created={[main, t_fun@src/example.c:17:3-17:40#top]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal)"
135+
),
136+
Pair.make(
137+
new GoblintPosition(10, 10, 2, 21, emptyUrl),
138+
"read with [mhp:{tid=[main, t_fun@src/example.c:17:3-17:40#top]}, lock:{mutex1}, thread:[main, t_fun@src/example.c:17:3-17:40#top]] (conf. 110) (exp: & myglobal)"
139+
),
140+
Pair.make(
141+
new GoblintPosition(19, 19, 2, 21, emptyUrl),
142+
"read with [mhp:{tid=[main]; created={[main, t_fun@src/example.c:17:3-17:40#top]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal)"
143+
)
144+
)
145+
)
146+
);
147+
response.add(
148+
new GoblintMessagesAnalysisResult(
149+
defaultPos,
150+
"[Race] Memory locations race summary",
151+
"Info",
152+
List.of(
153+
Pair.make(defaultPos, "safe: 0"),
154+
Pair.make(defaultPos, "vulnerable: 0"),
155+
Pair.make(defaultPos, "unsafe: 1"),
156+
Pair.make(defaultPos, "total memory locations: 1")
157+
)
158+
)
159+
);
160+
161+
verify(analysisConsumer).consume(response, "GobPie");
162+
}
163+
164+
165+
}
166+

0 commit comments

Comments
 (0)