Skip to content

Commit bd1d8f0

Browse files
authored
Add Jetty/Tomcat WAR integration tests for Maven (#1100)
1 parent dbaa762 commit bd1d8f0

File tree

13 files changed

+327
-73
lines changed

13 files changed

+327
-73
lines changed

jib-gradle-plugin/src/integration-test/java/com/google/cloud/tools/jib/gradle/WarProjectIntegrationTest.java

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818

1919
import com.google.cloud.tools.jib.Command;
2020
import com.google.cloud.tools.jib.IntegrationTestingConfiguration;
21-
import com.google.common.io.ByteStreams;
22-
import java.io.ByteArrayOutputStream;
21+
import com.google.cloud.tools.jib.blob.Blobs;
2322
import java.io.IOException;
23+
import java.io.InputStream;
2424
import java.net.HttpURLConnection;
2525
import java.net.URL;
26-
import java.nio.charset.StandardCharsets;
2726
import javax.annotation.Nullable;
2827
import org.junit.After;
2928
import org.junit.Assert;
@@ -41,48 +40,46 @@ private static String getContent(URL url) throws InterruptedException {
4140
Thread.sleep(500);
4241
try {
4342
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
44-
int code = connection.getResponseCode();
45-
if (code == HttpURLConnection.HTTP_OK) {
46-
ByteArrayOutputStream out = new ByteArrayOutputStream();
47-
ByteStreams.copy(connection.getInputStream(), out);
48-
return new String(out.toByteArray(), StandardCharsets.UTF_8);
43+
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
44+
try (InputStream in = connection.getInputStream()) {
45+
return Blobs.writeToString(Blobs.from(in));
46+
}
4947
}
5048
} catch (IOException ex) {
5149
}
5250
}
5351
return null;
5452
}
5553

56-
private String containerName;
54+
@Nullable private String containerName;
5755

5856
@After
5957
public void tearDown() throws IOException, InterruptedException {
6058
if (containerName != null) {
61-
new Command("docker", "stop", containerName.trim()).run();
59+
new Command("docker", "stop", containerName).run();
6260
}
6361
}
6462

6563
@Test
6664
public void testBuild_jettyServlet25Project() throws IOException, InterruptedException {
6765
buildAndRunDetached(servlet25Project, "war_jetty_servlet25:gradle", "build.gradle");
6866

69-
String content = getContent(new URL("http://localhost:8080/hello"));
70-
Assert.assertEquals("Hello world", content);
67+
Assert.assertEquals("Hello world", getContent(new URL("http://localhost:8080/hello")));
7168
}
7269

7370
@Test
7471
public void testBuild_tomcatServlet25Project() throws IOException, InterruptedException {
7572
buildAndRunDetached(servlet25Project, "war_tomcat_servlet25:gradle", "build-tomcat.gradle");
7673

77-
String content = getContent(new URL("http://localhost:8080/hello"));
78-
Assert.assertEquals("Hello world", content);
74+
Assert.assertEquals("Hello world", getContent(new URL("http://localhost:8080/hello")));
7975
}
8076

81-
private void buildAndRunDetached(TestProject project, String imageName, String gradleBuildFile)
77+
private void buildAndRunDetached(TestProject project, String label, String gradleBuildFile)
8278
throws IOException, InterruptedException {
83-
String repository = "gcr.io/" + IntegrationTestingConfiguration.getGCPProject() + '/';
84-
String targetImage = repository + imageName + System.nanoTime();
85-
containerName =
79+
String nameBase = "gcr.io/" + IntegrationTestingConfiguration.getGCPProject() + '/';
80+
String targetImage = nameBase + label + System.nanoTime();
81+
String output =
8682
JibRunHelper.buildAndRun(project, targetImage, gradleBuildFile, "--detach", "-p8080:8080");
83+
containerName = output.trim();
8784
}
8885
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Manifest-Version: 1.0
2-
Class-Path:
2+
Class-Path:

jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java

Lines changed: 82 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818

1919
import com.google.cloud.tools.jib.Command;
2020
import com.google.cloud.tools.jib.IntegrationTestingConfiguration;
21+
import com.google.cloud.tools.jib.blob.Blobs;
2122
import com.google.cloud.tools.jib.image.ImageReference;
2223
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
2324
import com.google.cloud.tools.jib.registry.LocalRegistry;
2425
import java.io.IOException;
26+
import java.io.InputStream;
27+
import java.net.HttpURLConnection;
28+
import java.net.URL;
2529
import java.nio.charset.StandardCharsets;
2630
import java.nio.file.Files;
2731
import java.nio.file.Path;
@@ -30,9 +34,11 @@
3034
import java.util.Arrays;
3135
import java.util.regex.Matcher;
3236
import java.util.regex.Pattern;
37+
import javax.annotation.Nullable;
3338
import org.apache.maven.it.VerificationException;
3439
import org.apache.maven.it.Verifier;
3540
import org.hamcrest.CoreMatchers;
41+
import org.junit.After;
3642
import org.junit.Assert;
3743
import org.junit.Before;
3844
import org.junit.ClassRule;
@@ -54,10 +60,6 @@ public class BuildImageMojoIntegrationTest {
5460
@ClassRule
5561
public static final TestProject simpleTestProject = new TestProject(testPlugin, "simple");
5662

57-
@ClassRule
58-
public static final TestProject complexTestProject =
59-
new TestProject(testPlugin, "simple", "pom-complex.xml");
60-
6163
@ClassRule
6264
public static final TestProject emptyTestProject = new TestProject(testPlugin, "empty");
6365

@@ -68,6 +70,31 @@ public class BuildImageMojoIntegrationTest {
6870
public static final TestProject defaultTargetTestProject =
6971
new TestProject(testPlugin, "default-target");
7072

73+
@ClassRule
74+
public static final TestProject servlet25Project = new TestProject(testPlugin, "war_servlet25");
75+
76+
private static String getGcrImageReference(String label) {
77+
String nameBase = "gcr.io/" + IntegrationTestingConfiguration.getGCPProject() + '/';
78+
return nameBase + label + System.nanoTime();
79+
}
80+
81+
@Nullable
82+
private static String getContent(URL url) throws InterruptedException {
83+
for (int i = 0; i < 40; i++) {
84+
Thread.sleep(500);
85+
try {
86+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
87+
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
88+
try (InputStream in = connection.getInputStream()) {
89+
return Blobs.writeToString(Blobs.from(in));
90+
}
91+
}
92+
} catch (IOException ex) {
93+
}
94+
}
95+
return null;
96+
}
97+
7198
/**
7299
* Builds and runs jib:build on a project at {@code projectRoot} pushing to {@code
73100
* imageReference}.
@@ -81,21 +108,16 @@ private static String buildAndRun(Path projectRoot, String imageReference, boole
81108
verifier.executeGoals(Arrays.asList("clean", "compile"));
82109

83110
// Builds twice, and checks if the second build took less time.
84-
verifier.executeGoal("jib:" + BuildImageMojo.GOAL_NAME);
111+
verifier.executeGoal("jib:build");
85112
float timeOne = getBuildTimeFromVerifierLog(verifier);
86113

87114
if (runTwice) {
88115
verifier.resetStreams();
89-
verifier.executeGoal("jib:" + BuildImageMojo.GOAL_NAME);
116+
verifier.executeGoal("jib:build");
90117
float timeTwo = getBuildTimeFromVerifierLog(verifier);
91118

92-
Assert.assertTrue(
93-
"First build time ("
94-
+ timeOne
95-
+ ") is not greater than second build time ("
96-
+ timeTwo
97-
+ ")",
98-
timeOne > timeTwo);
119+
String failMessage = "First build time (%s) is not greater than second build time (%s)";
120+
Assert.assertTrue(String.format(failMessage, timeOne, timeTwo), timeOne > timeTwo);
99121
}
100122

101123
verifier.verifyErrorFreeLog();
@@ -112,9 +134,7 @@ private static String buildAndRunAdditionalTag(
112134
verifier.setSystemProperty("_ADDITIONAL_TAG", additionalTag);
113135
verifier.setAutoclean(false);
114136
verifier.addCliOption("-X");
115-
verifier.executeGoals(Arrays.asList("clean", "compile"));
116-
117-
verifier.executeGoal("jib:" + BuildImageMojo.GOAL_NAME);
137+
verifier.executeGoals(Arrays.asList("clean", "compile", "jib:build"));
118138
verifier.verifyErrorFreeLog();
119139

120140
String additionalImageReference =
@@ -134,7 +154,7 @@ private static String buildAndRunComplex(
134154
String imageReference, String username, String password, LocalRegistry targetRegistry)
135155
throws VerificationException, IOException, InterruptedException {
136156
Instant before = Instant.now();
137-
Verifier verifier = new Verifier(complexTestProject.getProjectRoot().toString());
157+
Verifier verifier = new Verifier(simpleTestProject.getProjectRoot().toString());
138158
verifier.setSystemProperty("_TARGET_IMAGE", imageReference);
139159
verifier.setSystemProperty("_TARGET_USERNAME", username);
140160
verifier.setSystemProperty("_TARGET_PASSWORD", password);
@@ -217,26 +237,31 @@ private static void assertCreationTimeEpoch(String imageReference)
217237
new Command("docker", "inspect", "-f", "{{.Created}}", imageReference).run().trim());
218238
}
219239

240+
@Nullable private String detachedContainerName;
241+
220242
@Before
221-
public void setup() throws IOException, InterruptedException {
243+
public void setUp() throws IOException, InterruptedException {
222244
// Pull distroless to local registry so we can test 'from' credentials
223245
localRegistry1.pullAndPushToLocal("gcr.io/distroless/java:latest", "distroless/java");
224246
}
225247

248+
@After
249+
public void tearDown() throws IOException, InterruptedException {
250+
if (detachedContainerName != null) {
251+
new Command("docker", "stop", detachedContainerName).run();
252+
}
253+
}
254+
226255
@Test
227256
public void testExecute_simple() throws VerificationException, IOException, InterruptedException {
228-
String targetImage =
229-
"gcr.io/"
230-
+ IntegrationTestingConfiguration.getGCPProject()
231-
+ "/simpleimage:maven"
232-
+ System.nanoTime();
257+
String targetImage = getGcrImageReference("simpleimage:maven");
233258

234259
// Test empty output error
235260
try {
236261
Verifier verifier = new Verifier(simpleTestProject.getProjectRoot().toString());
237262
verifier.setSystemProperty("_TARGET_IMAGE", targetImage);
238263
verifier.setAutoclean(false);
239-
verifier.executeGoals(Arrays.asList("clean", "jib:" + BuildImageMojo.GOAL_NAME));
264+
verifier.executeGoals(Arrays.asList("clean", "jib:build"));
240265
Assert.fail();
241266

242267
} catch (VerificationException ex) {
@@ -275,12 +300,7 @@ public void testExecute_simple() throws VerificationException, IOException, Inte
275300

276301
@Test
277302
public void testExecute_empty() throws InterruptedException, IOException, VerificationException {
278-
String targetImage =
279-
"gcr.io/"
280-
+ IntegrationTestingConfiguration.getGCPProject()
281-
+ "/emptyimage:maven"
282-
+ System.nanoTime();
283-
303+
String targetImage = getGcrImageReference("emptyimage:maven");
284304
Assert.assertEquals("", buildAndRun(emptyTestProject.getProjectRoot(), targetImage, false));
285305
assertCreationTimeEpoch(targetImage);
286306
}
@@ -289,11 +309,7 @@ public void testExecute_empty() throws InterruptedException, IOException, Verifi
289309
public void testExecute_multipleTags()
290310
throws IOException, InterruptedException, InvalidImageReferenceException,
291311
VerificationException {
292-
String targetImage =
293-
"gcr.io/"
294-
+ IntegrationTestingConfiguration.getGCPProject()
295-
+ "/multitag-image:maven"
296-
+ System.nanoTime();
312+
String targetImage = getGcrImageReference("multitag-image:maven");
297313
Assert.assertEquals(
298314
"",
299315
buildAndRunAdditionalTag(
@@ -306,7 +322,7 @@ public void testExecute_defaultTarget() throws IOException {
306322
try {
307323
Verifier verifier = new Verifier(defaultTargetTestProject.getProjectRoot().toString());
308324
verifier.setAutoclean(false);
309-
verifier.executeGoals(Arrays.asList("clean", "jib:" + BuildImageMojo.GOAL_NAME));
325+
verifier.executeGoals(Arrays.asList("clean", "jib:build"));
310326
Assert.fail();
311327

312328
} catch (VerificationException ex) {
@@ -341,4 +357,34 @@ public void testExecute_complex_sameFromAndToRegistry()
341357
public void testExecute_skipJibGoal() throws VerificationException, IOException {
342358
SkippedGoalVerifier.verifyGoalIsSkipped(skippedTestProject, BuildImageMojo.GOAL_NAME);
343359
}
360+
361+
@Test
362+
public void testExecute_jettyServlet25()
363+
throws VerificationException, IOException, InterruptedException {
364+
buildAndRunWar("jetty-servlet25:maven", "pom.xml");
365+
Assert.assertEquals("Hello world", getContent(new URL("http://localhost:8080/hello")));
366+
}
367+
368+
@Test
369+
public void testExecute_tomcatServlet25()
370+
throws VerificationException, IOException, InterruptedException {
371+
buildAndRunWar("tomcat-servlet25:maven", "pom-tomcat.xml");
372+
Assert.assertEquals("Hello world", getContent(new URL("http://localhost:8080/hello")));
373+
}
374+
375+
private void buildAndRunWar(String label, String pomXml)
376+
throws VerificationException, IOException, InterruptedException {
377+
String targetImage = getGcrImageReference(label);
378+
379+
Verifier verifier = new Verifier(servlet25Project.getProjectRoot().toString());
380+
verifier.setSystemProperty("_TARGET_IMAGE", targetImage);
381+
verifier.setAutoclean(false);
382+
verifier.addCliOption("-X");
383+
verifier.addCliOption("--file=" + pomXml);
384+
verifier.executeGoals(Arrays.asList("clean", "package", "jib:build"));
385+
verifier.verifyErrorFreeLog();
386+
387+
detachedContainerName =
388+
new Command("docker", "run", "--rm", "--detach", "-p8080:8080", targetImage).run().trim();
389+
}
344390
}

jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/TestProject.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.nio.charset.StandardCharsets;
2222
import java.nio.file.Files;
2323
import java.nio.file.Path;
24+
import java.util.stream.Collectors;
25+
import java.util.stream.Stream;
2426
import org.apache.maven.it.util.ResourceExtractor;
2527
import org.junit.rules.TemporaryFolder;
2628

@@ -29,29 +31,32 @@ public class TestProject extends TemporaryFolder implements Closeable {
2931

3032
private static final String PROJECTS_PATH_IN_RESOURCES = "/projects/";
3133

34+
private static boolean isPomXml(Path path) {
35+
String filename = path.getFileName().toString();
36+
return filename.startsWith("pom") && filename.endsWith(".xml");
37+
}
38+
3239
private final TestPlugin testPlugin;
3340
private final String projectDir;
34-
private final String pomFilename;
3541

3642
private Path projectRoot;
3743

3844
/** Initialize to a specific project directory. */
3945
public TestProject(TestPlugin testPlugin, String projectDir) {
40-
this(testPlugin, projectDir, "pom.xml");
41-
}
42-
43-
/** Initialize to a specific project directory with a non-default pom.xml. */
44-
TestProject(TestPlugin testPlugin, String projectDir, String pomFilename) {
4546
this.testPlugin = testPlugin;
4647
this.projectDir = projectDir;
47-
this.pomFilename = pomFilename;
4848
}
4949

5050
/** Get the project root resolved as a real path */
5151
public Path getProjectRoot() throws IOException {
5252
return projectRoot.toRealPath();
5353
}
5454

55+
@Override
56+
public void close() {
57+
after();
58+
}
59+
5560
@Override
5661
protected void before() throws Throwable {
5762
super.before();
@@ -66,16 +71,14 @@ private void copyProject() throws IOException {
6671
.toPath();
6772

6873
// Puts the correct plugin version into the test project pom.xml.
69-
Path pomXml = projectRoot.resolve(pomFilename);
70-
Files.write(
71-
pomXml,
72-
new String(Files.readAllBytes(pomXml), StandardCharsets.UTF_8)
73-
.replace("@@PluginVersion@@", testPlugin.getVersion())
74-
.getBytes(StandardCharsets.UTF_8));
75-
}
76-
77-
@Override
78-
public void close() {
79-
after();
74+
try (Stream<Path> files = Files.list(projectRoot)) {
75+
for (Path pomXml : files.filter(TestProject::isPomXml).collect(Collectors.toList())) {
76+
Files.write(
77+
pomXml,
78+
new String(Files.readAllBytes(pomXml), StandardCharsets.UTF_8)
79+
.replace("@@PluginVersion@@", testPlugin.getVersion())
80+
.getBytes(StandardCharsets.UTF_8));
81+
}
82+
}
8083
}
8184
}

0 commit comments

Comments
 (0)