1
1
package com .ibm .cldk ;
2
2
3
+ import com .google .gson .Gson ;
4
+ import com .google .gson .JsonArray ;
5
+ import com .google .gson .JsonElement ;
6
+ import com .google .gson .JsonObject ;
7
+ import org .json .JSONArray ;
3
8
import org .junit .jupiter .api .BeforeAll ;
4
9
import org .junit .jupiter .api .Test ;
5
10
import org .junit .jupiter .api .Assertions ;
6
11
import org .testcontainers .containers .BindMode ;
7
12
import org .testcontainers .containers .GenericContainer ;
13
+ import org .testcontainers .containers .startupcheck .OneShotStartupCheckStrategy ;
8
14
import org .testcontainers .junit .jupiter .Container ;
9
15
import org .testcontainers .junit .jupiter .Testcontainers ;
10
16
import org .testcontainers .utility .MountableFile ;
13
19
import java .io .FileInputStream ;
14
20
import java .io .IOException ;
15
21
import java .nio .file .Paths ;
22
+ import java .time .Duration ;
16
23
import java .util .Properties ;
24
+ import java .util .stream .StreamSupport ;
17
25
18
26
19
27
@ Testcontainers
@@ -25,7 +33,7 @@ public class CodeAnalyzerIntegrationTest {
25
33
*/
26
34
static String codeanalyzerVersion ;
27
35
static final String javaVersion = "17" ;
28
-
36
+ static String javaHomePath ;
29
37
static {
30
38
// Build project first
31
39
try {
@@ -41,16 +49,14 @@ public class CodeAnalyzerIntegrationTest {
41
49
}
42
50
43
51
@ Container
44
- static final GenericContainer <?> container = new GenericContainer <>("openjdk:17-jdk " )
52
+ static final GenericContainer <?> container = new GenericContainer <>("ubuntu:latest " )
45
53
.withCreateContainerCmdModifier (cmd -> cmd .withEntrypoint ("sh" ))
46
54
.withCommand ("-c" , "while true; do sleep 1; done" )
47
- .withFileSystemBind (
48
- String .valueOf (Paths .get (System .getProperty ("user.dir" )).resolve ("build/libs" )),
49
- "/opt/jars" ,
50
- BindMode .READ_WRITE )
55
+ .withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("build/libs" )), "/opt/jars" )
51
56
.withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("build/libs" )), "/opt/jars" )
52
57
.withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("src/test/resources/test-applications/mvnw-corrupt-test" )), "/test-applications/mvnw-corrupt-test" )
53
58
.withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("src/test/resources/test-applications/plantsbywebsphere" )), "/test-applications/plantsbywebsphere" )
59
+ .withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("src/test/resources/test-applications/call-graph-test" )), "/test-applications/call-graph-test" )
54
60
.withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("src/test/resources/test-applications/mvnw-working-test" )), "/test-applications/mvnw-working-test" );
55
61
56
62
@ Container
@@ -62,8 +68,29 @@ public class CodeAnalyzerIntegrationTest {
62
68
.withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("src/test/resources/test-applications/mvnw-working-test" )), "/test-applications/mvnw-working-test" )
63
69
.withCopyFileToContainer (MountableFile .forHostPath (Paths .get (System .getProperty ("user.dir" )).resolve ("src/test/resources/test-applications/daytrader8" )), "/test-applications/daytrader8" );
64
70
71
+ public CodeAnalyzerIntegrationTest () throws IOException , InterruptedException {
72
+ }
73
+
65
74
@ BeforeAll
66
75
static void setUp () {
76
+ // Install Java 17 in the base container
77
+ try {
78
+ container .execInContainer ("apt-get" , "update" );
79
+ container .execInContainer ("apt-get" , "install" , "-y" , "openjdk-17-jdk" );
80
+
81
+ // Get JAVA_HOME dynamically
82
+ var javaHomeResult = container .execInContainer ("bash" , "-c" ,
83
+ "dirname $(dirname $(readlink -f $(which java)))"
84
+ );
85
+ javaHomePath = javaHomeResult .getStdout ().trim ();
86
+ Assertions .assertFalse (javaHomePath .isEmpty (), "Failed to determine JAVA_HOME" );
87
+
88
+ } catch (IOException | InterruptedException e ) {
89
+ throw new RuntimeException (e );
90
+ }
91
+
92
+
93
+ // Get the version of the codeanalyzer jar
67
94
Properties properties = new Properties ();
68
95
try (FileInputStream fis = new FileInputStream (
69
96
Paths .get (System .getProperty ("user.dir" ), "gradle.properties" ).toFile ())) {
@@ -92,18 +119,42 @@ void shouldHaveCodeAnalyzerJar() throws Exception {
92
119
@ Test
93
120
void shouldBeAbleToRunCodeAnalyzer () throws Exception {
94
121
var runCodeAnalyzerJar = container .execInContainer (
95
- "java" ,
96
- "-jar" ,
97
- String .format ("/opt/jars/codeanalyzer-%s.jar" , codeanalyzerVersion ),
98
- "--help"
99
- );
122
+ "bash" , "-c" ,
123
+ String .format ("export JAVA_HOME=%s && java -jar /opt/jars/codeanalyzer-%s.jar --help" ,
124
+ javaHomePath , codeanalyzerVersion
125
+ ));
100
126
101
127
Assertions .assertEquals (0 , runCodeAnalyzerJar .getExitCode (),
102
128
"Command should execute successfully" );
103
129
Assertions .assertTrue (runCodeAnalyzerJar .getStdout ().length () > 0 ,
104
130
"Should have some output" );
105
131
}
106
132
133
+ @ Test
134
+ void callGraphShouldHaveKnownEdges () throws Exception {
135
+ var runCodeAnalyzerOnCallGraphTest = container .execInContainer (
136
+ "bash" , "-c" ,
137
+ String .format (
138
+ "export JAVA_HOME=%s && java -jar /opt/jars/codeanalyzer-%s.jar --input=/test-applications/call-graph-test --analysis-level=2" ,
139
+ javaHomePath , codeanalyzerVersion
140
+ )
141
+ );
142
+
143
+
144
+ // Read the output JSON
145
+ Gson gson = new Gson ();
146
+ JsonObject jsonObject = gson .fromJson (runCodeAnalyzerOnCallGraphTest .getStdout (), JsonObject .class );
147
+ JsonArray systemDepGraph = jsonObject .getAsJsonArray ("system_dependency_graph" );
148
+ Assertions .assertTrue (StreamSupport .stream (systemDepGraph .spliterator (), false )
149
+ .map (JsonElement ::getAsJsonObject )
150
+ .anyMatch (entry ->
151
+ "CALL_DEP" .equals (entry .get ("type" ).getAsString ()) &&
152
+ "1" .equals (entry .get ("weight" ).getAsString ()) &&
153
+ entry .getAsJsonObject ("source" ).get ("signature" ).getAsString ().equals ("helloString()" ) &&
154
+ entry .getAsJsonObject ("target" ).get ("signature" ).getAsString ().equals ("log()" )
155
+ ), "Expected edge not found in the system dependency graph" );
156
+ }
157
+
107
158
@ Test
108
159
void corruptMavenShouldNotBuildWithWrapper () throws IOException , InterruptedException {
109
160
// Make executable
@@ -131,42 +182,44 @@ void corruptMavenShouldProduceAnalysisArtifactsWhenMVNCommandIsInPath() throws I
131
182
132
183
@ Test
133
184
void corruptMavenShouldNotTerminateWithErrorWhenMavenIsNotPresentUnlessAnalysisLevel2 () throws IOException , InterruptedException {
134
- // When javaee level 2, we should get a Runtime Exception
185
+ // When analysis level 2, we should get a Runtime Exception
135
186
var runCodeAnalyzer = container .execInContainer (
136
- "java" ,
137
- "-jar" ,
138
- String .format ("/opt/jars/codeanalyzer-%s.jar" , codeanalyzerVersion ),
139
- "--input=/test-applications/mvnw-corrupt-test" ,
140
- "--output=/tmp/" ,
141
- "--analysis-level=2"
187
+ "bash" , "-c" ,
188
+ String .format (
189
+ "export JAVA_HOME=%s && java -jar /opt/jars/codeanalyzer-%s.jar --input=/test-applications/mvnw-corrupt-test --output=/tmp/ --analysis-level=2" ,
190
+ javaHomePath , codeanalyzerVersion
191
+ )
142
192
);
193
+
143
194
Assertions .assertEquals (1 , runCodeAnalyzer .getExitCode ());
144
195
Assertions .assertTrue (runCodeAnalyzer .getStderr ().contains ("java.lang.RuntimeException" ));
145
196
}
146
197
147
198
@ Test
148
199
void shouldBeAbleToGenerateAnalysisArtifactForDaytrader8 () throws Exception {
149
200
var runCodeAnalyzerOnDaytrader8 = mavenContainer .execInContainer (
150
- "java " ,
151
- "-jar" ,
152
- String . format ( " /opt/jars/codeanalyzer-%s.jar" , codeanalyzerVersion ) ,
153
- "--input=/test-applications/daytrader8" ,
154
- "--analysis-level=1"
201
+ "bash" , "-c " ,
202
+ String . format (
203
+ "export JAVA_HOME=%s && java -jar /opt/jars/codeanalyzer-%s.jar --input=/test-applications/daytrader8 --analysis-level=1" ,
204
+ javaHomePath , codeanalyzerVersion
205
+ )
155
206
);
207
+
156
208
Assertions .assertTrue (runCodeAnalyzerOnDaytrader8 .getStdout ().contains ("\" is_entrypoint_class\" : true" ), "No entry point classes found" );
157
209
Assertions .assertTrue (runCodeAnalyzerOnDaytrader8 .getStdout ().contains ("\" is_entrypoint\" : true" ), "No entry point methods found" );
158
210
}
159
211
160
212
@ Test
161
213
void shouldBeAbleToDetectCRUDOperationsAndQueriesForPlantByWebsphere () throws Exception {
162
214
var runCodeAnalyzerOnPlantsByWebsphere = container .execInContainer (
163
- "java " ,
164
- "-jar" ,
165
- String . format ( " /opt/jars/codeanalyzer-%s.jar" , codeanalyzerVersion ) ,
166
- "--input=/test-applications/plantsbywebsphere" ,
167
- "--analysis-level=1" , "--verbose"
215
+ "bash" , "-c " ,
216
+ String . format (
217
+ "export JAVA_HOME=%s && java -jar /opt/jars/codeanalyzer-%s.jar --input=/test-applications/plantsbywebsphere --analysis-level=1 --verbose" ,
218
+ javaHomePath , codeanalyzerVersion
219
+ )
168
220
);
169
221
222
+
170
223
String output = runCodeAnalyzerOnPlantsByWebsphere .getStdout ();
171
224
172
225
Assertions .assertTrue (output .contains ("\" query_type\" : \" NAMED\" " ), "No entry point classes found" );
0 commit comments