diff --git a/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java b/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java index a9e8b2b6..a4d8c509 100644 --- a/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java +++ b/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java @@ -2598,7 +2598,7 @@ private void printDevModeMessages(boolean inputUnavailable, boolean startup) thr } } - private void printPortInfo(boolean pKeyPressed) throws PluginExecutionException { + void printPortInfo(boolean pKeyPressed) throws PluginExecutionException { if (container) { boolean nonDefaultHttpPortUsed = !skipDefaultPorts && !String.valueOf(LIBERTY_DEFAULT_HTTP_PORT).equals(httpPort); boolean nonDefaultHttpsPortUsed = !skipDefaultPorts && !String.valueOf(LIBERTY_DEFAULT_HTTPS_PORT).equals(httpsPort); @@ -2622,6 +2622,7 @@ private void printPortInfo(boolean pKeyPressed) throws PluginExecutionException } else { info(formatAttentionMessage("Internal container HTTP port [ " + containerHttpPort + " ] is mapped to container host port [ " + httpPort + " ] <")); } + info(formatAttentionMessage("Liberty welcome page: http://localhost:" + httpPort + "/")); } else { info(formatAttentionMessage("Internal container HTTP port: [ " + containerHttpPort + " ]")); } @@ -2633,6 +2634,7 @@ private void printPortInfo(boolean pKeyPressed) throws PluginExecutionException } else { info(formatAttentionMessage("Internal container HTTPS port [ " + containerHttpsPort + " ] is mapped to container host port [ " + httpsPort + " ] <")); } + info(formatAttentionMessage("Liberty welcome page: https://localhost:" + httpsPort + "/")); } else { info(formatAttentionMessage("Internal container HTTPS port: [ " + containerHttpsPort + " ]")); } @@ -2666,9 +2668,11 @@ private void printPortInfo(boolean pKeyPressed) throws PluginExecutionException } if (httpPort != null) { info(formatAttentionMessage("Liberty server HTTP port: [ " + httpPort + " ]")); + info(formatAttentionMessage("Liberty welcome page: http://" + hostName + ":" + httpPort + "/")); } if (httpsPort != null) { info(formatAttentionMessage("Liberty server HTTPS port: [ " + httpsPort + " ]")); + info(formatAttentionMessage("Liberty welcome page: https://" + hostName + ":" + httpsPort + "/")); } if (libertyDebug) { int debugPort = (alternativeDebugPort == -1 ? libertyDebugPort : alternativeDebugPort); @@ -2797,6 +2801,22 @@ private void infoSrcDirModified() { info("The source configuration directory will be modified. Features will automatically be generated in a new file: " + generatedFileCanonicalPath); } + protected void setContainerHttpPort(String containerHttpPort) { + this.containerHttpPort = containerHttpPort; + } + + protected void setContainerHttpsPort(String containerHttpsPort) { + this.containerHttpsPort = containerHttpsPort; + } + + protected void setHttpPort(String httpPort) { + this.httpPort = httpPort; + } + + protected void setHttpsPort(String httpsPort) { + this.httpsPort = httpsPort; + } + // called by Liberty plugins protected void setFeatureGeneration(boolean generateFeatures) { this.generateFeatures = generateFeatures; diff --git a/src/test/java/io/openliberty/tools/common/plugins/util/BaseDevUtilTest.java b/src/test/java/io/openliberty/tools/common/plugins/util/BaseDevUtilTest.java index 3a546b9c..e619d165 100644 --- a/src/test/java/io/openliberty/tools/common/plugins/util/BaseDevUtilTest.java +++ b/src/test/java/io/openliberty/tools/common/plugins/util/BaseDevUtilTest.java @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; import java.nio.file.Path; import java.util.Collections; @@ -50,6 +51,24 @@ public DevTestUtil(File serverDirectory, File buildDir) { false, null, null, null, 0, false, null, false, null, null, false, null, null, null, false, false, null, null, null, Collections.emptyMap()); } + public DevTestUtil(File serverDirectory, File buildDir, boolean container) { + super(buildDir, serverDirectory, null, null, null, null, null, + null, false, false, false, false, false, false, null, 30, 30, 5, 500, true, false, false, false, + container, null, null, null, 0, false, null, false, null, null, false, null, null, null, false, false, null, null, null, Collections.emptyMap()); + } + + /** + * Sets the container port fields without going through findLocalPort (which calls Docker). + * Only meaningful when container=true. + */ + public void setContainerPorts(String containerHttpPort, String mappedHttpPort, + String containerHttpsPort, String mappedHttpsPort) { + setContainerHttpPort(containerHttpPort); + setHttpPort(mappedHttpPort); + setContainerHttpsPort(containerHttpsPort); + setHttpsPort(mappedHttpsPort); + } + @Override public void debug(String msg) { // not needed for tests @@ -74,10 +93,20 @@ public void warn(String msg) { } + public final List infoMessages = new ArrayList<>(); + @Override public void info(String msg) { - // not needed for tests - + infoMessages.add(msg); + } + + public boolean hasMessage(String substring) { + for (String msg : infoMessages) { + if (msg.contains(substring)) { + return true; + } + } + return false; } @Override @@ -266,4 +295,8 @@ public DevUtil getNewDevUtil(File serverDirectory) throws IOException { public DevUtil getNewDevUtil(File serverDirectory, File buildDir) { return new DevTestUtil(serverDirectory, buildDir); } + + public DevTestUtil getNewContainerUtil() { + return new DevTestUtil(null, null, true); + } } diff --git a/src/test/java/io/openliberty/tools/common/plugins/util/DevUtilPrintPortInfoTest.java b/src/test/java/io/openliberty/tools/common/plugins/util/DevUtilPrintPortInfoTest.java new file mode 100644 index 00000000..51a5d4bd --- /dev/null +++ b/src/test/java/io/openliberty/tools/common/plugins/util/DevUtilPrintPortInfoTest.java @@ -0,0 +1,187 @@ +/** + * (C) Copyright IBM Corporation 2025, 2026. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.openliberty.tools.common.plugins.util; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +/** + * Tests that printPortInfo outputs a Liberty welcome page URL alongside each port line, + * for both non-container (server) and container modes. + */ +public class DevUtilPrintPortInfoTest extends BaseDevUtilTest { + + private DevTestUtil newUtil() throws Exception { + return (DevTestUtil) getNewDevUtil(null); + } + + // ----------------------------------------------------------------------- + // Non-container: HTTP port + // ----------------------------------------------------------------------- + + @Test + public void testServerHttpPortUrlPrinted() throws Exception { + DevTestUtil util = newUtil(); + int portPrefixIndex = util.parseHostName( + "Web application available (default_host): http://myhostname:9080/myapp/"); + util.parseHttpPort( + "Web application available (default_host): http://myhostname:9080/myapp/", portPrefixIndex); + + util.printPortInfo(true); + + assertTrue("Expected HTTP port line to be printed", + util.hasMessage("Liberty server HTTP port: [ 9080 ]")); + assertTrue("Expected HTTP URL to be printed", + util.hasMessage("Liberty welcome page: http://myhostname:9080/")); + } + + @Test + public void testServerHttpPortUrlUsesActualHostname() throws Exception { + DevTestUtil util = newUtil(); + // Simulate Liberty bound to a real IP address (not localhost) + int portPrefixIndex = util.parseHostName( + "Web application available (default_host): http://192.168.1.26:9080/myapp/"); + util.parseHttpPort( + "Web application available (default_host): http://192.168.1.26:9080/myapp/", portPrefixIndex); + + util.printPortInfo(true); + + assertTrue("Expected URL with actual IP address", + util.hasMessage("Liberty welcome page: http://192.168.1.26:9080/")); + assertFalse("localhost should not appear in URL when server bound to IP", + util.hasMessage("Liberty welcome page: http://localhost:9080/")); + } + + // ----------------------------------------------------------------------- + // Non-container: HTTPS port + // ----------------------------------------------------------------------- + + @Test + public void testServerHttpsPortUrlPrinted() throws Exception { + DevTestUtil util = newUtil(); + int portPrefixIndex = util.parseHostName( + "Web application available (default_host): http://myhostname:9080/myapp/"); + util.parseHttpPort( + "Web application available (default_host): http://myhostname:9080/myapp/", portPrefixIndex); + + List tcpMessages = new ArrayList<>(); + tcpMessages.add("CWWKO0219I: TCP Channel defaultHttpEndpoint-ssl has been started and is now listening for requests on host myhostname port 9443."); + util.parseHttpsPort(tcpMessages); + + util.printPortInfo(true); + + assertTrue("Expected HTTPS port line to be printed", + util.hasMessage("Liberty server HTTPS port: [ 9443 ]")); + assertTrue("Expected HTTPS URL to be printed", + util.hasMessage("Liberty welcome page: https://myhostname:9443/")); + } + + // ----------------------------------------------------------------------- + // Non-container: no port — no URL printed + // ----------------------------------------------------------------------- + + @Test + public void testNoUrlPrintedWhenNoPortAvailable() throws Exception { + DevTestUtil util = newUtil(); + // Do not parse any port — httpPort and httpsPort remain null + + util.printPortInfo(true); + + assertFalse("No URL should be printed when no port is available", + util.hasMessage("Liberty welcome page: http://")); + assertFalse("No URL should be printed when no port is available", + util.hasMessage("Liberty welcome page: https://")); + } + + // ----------------------------------------------------------------------- + // Non-container: non-default port + // ----------------------------------------------------------------------- + + @Test + public void testServerNonDefaultHttpPortUrl() throws Exception { + DevTestUtil util = newUtil(); + int portPrefixIndex = util.parseHostName( + "Web application available (default_host): http://myhostname:9085/myapp/"); + util.parseHttpPort( + "Web application available (default_host): http://myhostname:9085/myapp/", portPrefixIndex); + + util.printPortInfo(true); + + assertTrue("Expected HTTP port line with non-default port", + util.hasMessage("Liberty server HTTP port: [ 9085 ]")); + assertTrue("Expected HTTP URL with non-default port", + util.hasMessage("Liberty welcome page: http://myhostname:9085/")); + } + + // ----------------------------------------------------------------------- + // Non-container: localhost + // ----------------------------------------------------------------------- + + @Test + public void testServerLocalhostHttpPortUrl() throws Exception { + DevTestUtil util = newUtil(); + int portPrefixIndex = util.parseHostName( + "Web application available (default_host): http://localhost:9080/myapp/"); + util.parseHttpPort( + "Web application available (default_host): http://localhost:9080/myapp/", portPrefixIndex); + + util.printPortInfo(true); + + assertTrue("Expected HTTP URL with localhost", + util.hasMessage("Liberty welcome page: http://localhost:9080/")); + } + + // ----------------------------------------------------------------------- + // Container: HTTP port + // ----------------------------------------------------------------------- + + @Test + public void testContainerHttpPortUrlPrinted() throws Exception { + DevTestUtil util = getNewContainerUtil(); + // Internal container port 9080 mapped to host port 9080 + util.setContainerPorts("9080", "9080", null, null); + + util.printPortInfo(true); + + assertTrue("Expected container HTTP port line to be printed", + util.hasMessage("Internal container HTTP port [ 9080 ] is mapped to container host port [ 9080 ]")); + assertTrue("Expected container HTTP welcome page URL to be printed", + util.hasMessage("Liberty welcome page: http://localhost:9080/")); + } + + // ----------------------------------------------------------------------- + // Container: HTTPS port + // ----------------------------------------------------------------------- + + @Test + public void testContainerHttpsPortUrlPrinted() throws Exception { + DevTestUtil util = getNewContainerUtil(); + // Internal container port 9443 mapped to host port 9443 + util.setContainerPorts(null, null, "9443", "9443"); + + util.printPortInfo(true); + + assertTrue("Expected container HTTPS port line to be printed", + util.hasMessage("Internal container HTTPS port [ 9443 ] is mapped to container host port [ 9443 ]")); + assertTrue("Expected container HTTPS welcome page URL to be printed", + util.hasMessage("Liberty welcome page: https://localhost:9443/")); + } +}