You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ds...@apache.org on 2025/09/09 15:55:43 UTC

(tomcat) branch main updated (f487a90199 -> 604efd338e)

This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


    from f487a90199 Add certificate selection code specific to TLS 1.3
     new bcf169fa9b Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=57700
     new c9490bfe3c Remove specific exception UnknownHostException as it's covered by general IOException and remove redundant initializer.
     new f9b917245a Create a helper in TomcatBaseTest to injects a LifecycleListener to a Context of a Container that sends code ADD_CHILD_EVENT and utilize this helper in TestManagerWebapp.
     new 9a53274683 Make ContainerInjector generic to set other fields in the context as well like Valve, xmlValidation etc
     new 3f0e084995 Tweak LogCapture logic
     new f660d8da56 Replace deployment of /examples with a new custom webapp to avoid Windows locks. ContainerInjector enhancements.
     new 604efd338e Replace testing with programmatic configuration

The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/catalina/manager/TestManagerWebapp.java | 128 ++++++++++++++++++++-
 .../apache/catalina/startup/TomcatBaseTest.java    |  75 ++++++++++--
 2 files changed, 192 insertions(+), 11 deletions(-)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 05/07: Tweak LogCapture logic

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 3f0e084995dd05e8548944b717893f4123475a42
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Tue Sep 9 14:12:17 2025 +0300

    Tweak LogCapture logic
---
 .../apache/catalina/startup/TomcatBaseTest.java    | 23 ++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/test/org/apache/catalina/startup/TomcatBaseTest.java b/test/org/apache/catalina/startup/TomcatBaseTest.java
index d3901b4ff2..4e5e31c972 100644
--- a/test/org/apache/catalina/startup/TomcatBaseTest.java
+++ b/test/org/apache/catalina/startup/TomcatBaseTest.java
@@ -952,6 +952,7 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
         protected final String[] loggerNames;
         protected final List<LogRecord> logRecords = Collections.synchronizedList(new ArrayList<>());
         protected final Map<Logger, Level> previousLevelsOfLoggersMap = new IdentityHashMap<>();
+        private volatile boolean installed = false;
         protected final Handler handler = new Handler() {
             @Override
             public void publish(LogRecord record) {
@@ -973,11 +974,14 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
         }
 
         public void attach() {
-            for (String name : loggerNames) {
-                Logger logger = Logger.getLogger(name);
-                previousLevelsOfLoggersMap.put(logger, logger.getLevel());
-                logger.addHandler(handler);
-                logger.setLevel(level);
+            if (!installed) {
+                for (String name : loggerNames) {
+                    Logger logger = Logger.getLogger(name);
+                    previousLevelsOfLoggersMap.put(logger, logger.getLevel());
+                    logger.addHandler(handler);
+                    logger.setLevel(level);
+                }
+                installed = true;
             }
         }
 
@@ -1027,15 +1031,18 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
      * CONFIGURE_START phase of a {@link Context}.
      */
     public static class WebappLogCapture extends LogCapture implements LifecycleListener {
-        private volatile boolean installed = false;
+        private String lifecycleEvent = Lifecycle.CONFIGURE_START_EVENT;
+        public WebappLogCapture(String lifecycleEvent, Level level, String... loggerNames) {
+            this(level, loggerNames);
+            this.lifecycleEvent = lifecycleEvent;
+        }
         public WebappLogCapture(Level level, String... loggerNames) {
             super(level, loggerNames);
         }
 
         @Override
         public void lifecycleEvent(LifecycleEvent event) {
-            if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType()) && !installed) {
-                installed = true;
+            if (this.lifecycleEvent.equals(event.getType())) {
                 this.attach();
             }
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 06/07: Replace deployment of /examples with a new custom webapp to avoid Windows locks. ContainerInjector enhancements.

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit f660d8da5688a62bc5fc88ab60de7e18db8182e3
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Tue Sep 9 14:58:44 2025 +0300

    Replace deployment of /examples with a new custom webapp to avoid Windows locks.
    ContainerInjector enhancements.
---
 .../apache/catalina/manager/TestManagerWebapp.java | 53 +++++++++++++++++++---
 .../apache/catalina/startup/TomcatBaseTest.java    | 13 ++++--
 2 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/test/org/apache/catalina/manager/TestManagerWebapp.java b/test/org/apache/catalina/manager/TestManagerWebapp.java
index 68568fdf0a..3c418340a8 100644
--- a/test/org/apache/catalina/manager/TestManagerWebapp.java
+++ b/test/org/apache/catalina/manager/TestManagerWebapp.java
@@ -530,9 +530,40 @@ public class TestManagerWebapp extends TomcatBaseTest {
         HostConfig hostConfig = new HostConfig();
         ctx.getParent().addLifecycleListener(hostConfig);
 
+        File appRoot = new File(webappDir, "bug57700");
+        File webInf = new File(appRoot, "WEB-INF");
+        Assert.assertTrue(webInf.mkdirs() && webInf.isDirectory());
+        try (PrintWriter out = new PrintWriter(new File(appRoot, "index.html"), StandardCharsets.UTF_8)) {
+            out.println("ok");
+        }
+        try (PrintWriter out = new PrintWriter(new File(webInf, "web.xml"), StandardCharsets.UTF_8)) {
+            out.println("""
+                    <?xml version="1.0" encoding="UTF-8"?>
+                    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
+                             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                             xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
+                                                 https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
+                             version="6.0">
+                      <servlet>
+                        <servlet-name>default</servlet-name>
+                        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
+                        <init-param>
+                          <param-name>listings</param-name>
+                          <param-value>false</param-value>
+                        </init-param>
+                      </servlet>
+                      <servlet-mapping>
+                        <servlet-name>default</servlet-name>
+                        <url-pattern>/</url-pattern>
+                      </servlet-mapping>
+                    </web-app>
+                    """);
+        }
+        addDeleteOnTearDown(appRoot);
+
         try (TomcatBaseTest.ContainerInjector ignored =
                  TomcatBaseTest.ContainerInjector.inject(ctx.getParent(),
-                     c -> c.getPath().equals("/examples"),
+                     c -> c.getPath().equals("/bug57700"),
                      c -> c.addLifecycleListener(new FailOnceListener()))) {
 
             tomcat.start();
@@ -548,12 +579,11 @@ public class TestManagerWebapp extends TomcatBaseTest {
                 }
             };
 
-            appDir = new File(webappDir, "examples");
             client.setPort(getPort());
             String basicHeader = (new BasicAuthHeader("Basic", "admin", "sekr3t")).getHeader().toString();
 
             client.setRequest(new String[]{
-                    "GET /manager/text/deploy?war=" + URLEncoder.QUERY.encode(appDir.getAbsolutePath(), StandardCharsets.UTF_8) + " HTTP/1.1" + CRLF +
+                    "GET /manager/text/deploy?war=" + URLEncoder.QUERY.encode(appRoot.getAbsolutePath(), StandardCharsets.UTF_8) + " HTTP/1.1" + CRLF +
                         "Host: localhost" + CRLF +
                         "Authorization: " + basicHeader + CRLF +
                         "Connection: Close" + CRLF + CRLF
@@ -563,7 +593,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
             Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
 
             client.setRequest(new String[]{
-                    "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
+                    "GET /bug57700/index.html HTTP/1.1" + CRLF +
                         "Host: localhost" + CRLF +
                         "Connection: Close" + CRLF + CRLF
             });
@@ -572,7 +602,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
             Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, client.getStatusCode());
 
             client.setRequest(new String[]{
-                    "GET /manager/text/start?path=/examples HTTP/1.1" + CRLF +
+                    "GET /manager/text/start?path=/bug57700 HTTP/1.1" + CRLF +
                         "Host: localhost" + CRLF +
                         "Authorization: " + basicHeader + CRLF +
                         "Connection: Close" + CRLF + CRLF
@@ -582,7 +612,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
             Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
 
             client.setRequest(new String[]{
-                    "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
+                    "GET /bug57700/index.html HTTP/1.1" + CRLF +
                         "Host: localhost" + CRLF +
                         "Connection: Close" + CRLF + CRLF
             });
@@ -590,6 +620,17 @@ public class TestManagerWebapp extends TomcatBaseTest {
             client.processRequest(true);
             Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
 
+            client.setRequest(new String[] {
+                    "GET /manager/text/undeploy?path=/bug57700 HTTP/1.1" + CRLF +
+                        "Host: localhost" + CRLF +
+                        "Authorization: " + basicHeader + CRLF +
+                        "Connection: Close" + CRLF +
+                        CRLF
+            });
+            client.connect();
+            client.processRequest(true);
+            Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
             tomcat.stop();
         }
     }
diff --git a/test/org/apache/catalina/startup/TomcatBaseTest.java b/test/org/apache/catalina/startup/TomcatBaseTest.java
index 4e5e31c972..71d629e83d 100644
--- a/test/org/apache/catalina/startup/TomcatBaseTest.java
+++ b/test/org/apache/catalina/startup/TomcatBaseTest.java
@@ -1113,21 +1113,28 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
         private final Predicate<Context> filter;
         private final Consumer<Context> action;
         private volatile boolean installed = false;
+        private String containerEvent = Container.ADD_CHILD_EVENT;
 
-        private ContainerInjector(Container container, Predicate<Context> filter, Consumer<Context> action) {
+        private ContainerInjector(Container container, Predicate<Context> filter, Consumer<Context> action, String containerEvent) {
             this.container = container;
             this.filter = filter;
             this.action = action;
+            if (containerEvent != null) {
+                this.containerEvent = containerEvent;
+            }
             container.addContainerListener(this);
         }
 
         public static ContainerInjector inject(Container container, Predicate<Context> filter, Consumer<Context> action) {
-            return new ContainerInjector(container, filter, action);
+            return new ContainerInjector(container, filter, action, null);
+        }
+        public static ContainerInjector inject(Container container, Predicate<Context> filter, Consumer<Context> action, String containerEvent) {
+            return new ContainerInjector(container, filter, action, containerEvent);
         }
 
         @Override
         public void containerEvent(ContainerEvent event) {
-            if (Container.ADD_CHILD_EVENT.equals(event.getType()) && !installed) {
+            if (this.containerEvent.equals(event.getType()) && !installed) {
                 Object data = event.getData();
                 if (data instanceof Context ctx) {
                     if (filter != null && filter.test(ctx)) {


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 01/07: Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=57700

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit bcf169fa9bddbe659899ef7330cbf400740d686e
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Mon Sep 8 15:37:22 2025 +0300

    Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=57700
---
 .../apache/catalina/manager/TestManagerWebapp.java | 114 +++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/test/org/apache/catalina/manager/TestManagerWebapp.java b/test/org/apache/catalina/manager/TestManagerWebapp.java
index cfe4370bcd..bbe7e749e1 100644
--- a/test/org/apache/catalina/manager/TestManagerWebapp.java
+++ b/test/org/apache/catalina/manager/TestManagerWebapp.java
@@ -30,7 +30,12 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import static org.apache.catalina.startup.SimpleHttpClient.CRLF;
+import org.apache.catalina.Container;
+import org.apache.catalina.ContainerListener;
 import org.apache.catalina.Context;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.authenticator.TestBasicAuthParser.BasicAuthHeader;
 import org.apache.catalina.realm.MemoryRealm;
 import org.apache.catalina.realm.MessageDigestCredentialHandler;
@@ -43,6 +48,7 @@ import org.apache.catalina.storeconfig.StoreConfigLifecycleListener;
 import org.apache.catalina.util.IOTools;
 import org.apache.catalina.util.URLEncoder;
 
+
 public class TestManagerWebapp extends TomcatBaseTest {
 
     public static final String CONFIG = "<?xml version=\"1.0\" ?>" +
@@ -500,5 +506,113 @@ public class TestManagerWebapp extends TomcatBaseTest {
 
         tomcat.stop();
     }
+    /**
+     * Test case for <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=57700">Bug 57700</a>.
+     */
+    @Test
+    public void testBug57700() throws Exception {
+        ignoreTearDown = true;
+        Tomcat tomcat = getTomcatInstance();
+        tomcat.setAddDefaultWebXmlToWebapp(false);
+        File configFile = new File(getTemporaryDirectory(), "tomcat-users-manager-lifecycle.xml");
+        try (PrintWriter writer = new PrintWriter(configFile)) {
+            writer.write(CONFIG);
+        }
+        addDeleteOnTearDown(configFile);
+
+        MemoryRealm memoryRealm = new MemoryRealm();
+        memoryRealm.setCredentialHandler(new MessageDigestCredentialHandler());
+        memoryRealm.setPathname(configFile.getAbsolutePath());
+        tomcat.getEngine().setRealm(memoryRealm);
+
+        File webappDir = new File(getBuildDirectory(), "webapps");
+
+        File appDir = new File(webappDir, "manager");
+        Context ctx = tomcat.addWebapp(null, "/manager", appDir.getAbsolutePath());
+
+        HostConfig hostConfig = new HostConfig();
+        ctx.getParent().addLifecycleListener(hostConfig);
+
+        ContainerListener containerListener = event -> {
+            if (Container.ADD_CHILD_EVENT.equals(event.getType())) {
+                Container child = (Container) event.getData();
+                if (child instanceof Context c) {
+                    if ("/examples".equals(c.getPath())) {
+                        c.addLifecycleListener(new FailOnceListener());
+                    }
+                }
+            }
+        };
+        ctx.getParent().addContainerListener(containerListener);
+
+        tomcat.start();
+        SimpleHttpClient client = new SimpleHttpClient() {
+            @Override
+            public void connect() throws UnknownHostException, IOException {
+                connect(30000, 30000);
+            }
+
+            @Override
+            public boolean isResponseBodyOK() {
+                return true;
+            }
+        };
+
+        appDir = new File(webappDir, "examples");
+        client.setPort(getPort());
+        String basicHeader = (new BasicAuthHeader("Basic", "admin", "sekr3t")).getHeader().toString();
+
+        client.setRequest(new String[] {
+                "GET /manager/text/deploy?war=" + URLEncoder.QUERY.encode(appDir.getAbsolutePath(), StandardCharsets.UTF_8) + " HTTP/1.1" + CRLF +
+                    "Host: localhost" + CRLF +
+                    "Authorization: " + basicHeader + CRLF +
+                    "Connection: Close" + CRLF + CRLF
+        });
+        client.connect();
+        client.processRequest(true);
+        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
+        client.setRequest(new String[] {
+                "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
+                    "Host: localhost" + CRLF +
+                    "Connection: Close" + CRLF + CRLF
+        });
+        client.connect();
+        client.processRequest(true);
+        Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, client.getStatusCode());
+
+        client.setRequest(new String[] {
+                "GET /manager/text/start?path=/examples HTTP/1.1" + CRLF +
+                    "Host: localhost" + CRLF +
+                    "Authorization: " + basicHeader + CRLF +
+                    "Connection: Close" + CRLF + CRLF
+        });
+        client.connect();
+        client.processRequest(true);
+        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
+        client.setRequest(new String[] {
+                "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
+                    "Host: localhost" + CRLF +
+                    "Connection: Close" + CRLF + CRLF
+        });
+        client.connect();
+        client.processRequest(true);
+        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
+        tomcat.stop();
+    }
 
+    private static class FailOnceListener implements LifecycleListener {
+        private volatile boolean firstRun = true;
+        @Override
+        public void lifecycleEvent(LifecycleEvent event) {
+            if (event.getLifecycle() instanceof Context) {
+                if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType()) && firstRun) {
+                    firstRun = false;
+                    throw new RuntimeException("Configuration failure in first run only");
+                }
+            }
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 03/07: Create a helper in TomcatBaseTest to injects a LifecycleListener to a Context of a Container that sends code ADD_CHILD_EVENT and utilize this helper in TestManagerWebapp.

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit f9b917245a8aacd4e3274b1769d4c85f339abbf3
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Mon Sep 8 17:21:00 2025 +0300

    Create a helper in TomcatBaseTest to injects a LifecycleListener to a Context of a Container that sends code ADD_CHILD_EVENT and utilize this helper in TestManagerWebapp.
---
 .../apache/catalina/manager/TestManagerWebapp.java | 126 ++++++++++-----------
 .../apache/catalina/startup/TomcatBaseTest.java    |  48 ++++++++
 2 files changed, 106 insertions(+), 68 deletions(-)

diff --git a/test/org/apache/catalina/manager/TestManagerWebapp.java b/test/org/apache/catalina/manager/TestManagerWebapp.java
index ddae0e288a..a9aac4175d 100644
--- a/test/org/apache/catalina/manager/TestManagerWebapp.java
+++ b/test/org/apache/catalina/manager/TestManagerWebapp.java
@@ -29,8 +29,6 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import static org.apache.catalina.startup.SimpleHttpClient.CRLF;
-import org.apache.catalina.Container;
-import org.apache.catalina.ContainerListener;
 import org.apache.catalina.Context;
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleEvent;
@@ -532,74 +530,66 @@ public class TestManagerWebapp extends TomcatBaseTest {
         HostConfig hostConfig = new HostConfig();
         ctx.getParent().addLifecycleListener(hostConfig);
 
-        ContainerListener containerListener = event -> {
-            if (Container.ADD_CHILD_EVENT.equals(event.getType())) {
-                Container child = (Container) event.getData();
-                if (child instanceof Context c) {
-                    if ("/examples".equals(c.getPath())) {
-                        c.addLifecycleListener(new FailOnceListener());
-                    }
-                }
-            }
-        };
-        ctx.getParent().addContainerListener(containerListener);
-
-        tomcat.start();
-        SimpleHttpClient client = new SimpleHttpClient() {
-            @Override
-            public void connect() throws IOException {
-                connect(30000, 30000);
-            }
+        try (TomcatBaseTest.ContainerInjector ignored =
+                 TomcatBaseTest.ContainerInjector.inject(ctx.getParent(), "/examples", new FailOnceListener())) {
 
-            @Override
-            public boolean isResponseBodyOK() {
-                return true;
-            }
-        };
-
-        appDir = new File(webappDir, "examples");
-        client.setPort(getPort());
-        String basicHeader = (new BasicAuthHeader("Basic", "admin", "sekr3t")).getHeader().toString();
-
-        client.setRequest(new String[] {
-                "GET /manager/text/deploy?war=" + URLEncoder.QUERY.encode(appDir.getAbsolutePath(), StandardCharsets.UTF_8) + " HTTP/1.1" + CRLF +
-                    "Host: localhost" + CRLF +
-                    "Authorization: " + basicHeader + CRLF +
-                    "Connection: Close" + CRLF + CRLF
-        });
-        client.connect();
-        client.processRequest(true);
-        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
-
-        client.setRequest(new String[] {
-                "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
-                    "Host: localhost" + CRLF +
-                    "Connection: Close" + CRLF + CRLF
-        });
-        client.connect();
-        client.processRequest(true);
-        Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, client.getStatusCode());
-
-        client.setRequest(new String[] {
-                "GET /manager/text/start?path=/examples HTTP/1.1" + CRLF +
-                    "Host: localhost" + CRLF +
-                    "Authorization: " + basicHeader + CRLF +
-                    "Connection: Close" + CRLF + CRLF
-        });
-        client.connect();
-        client.processRequest(true);
-        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
-
-        client.setRequest(new String[] {
-                "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
-                    "Host: localhost" + CRLF +
-                    "Connection: Close" + CRLF + CRLF
-        });
-        client.connect();
-        client.processRequest(true);
-        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+            tomcat.start();
+            SimpleHttpClient client = new SimpleHttpClient() {
+                @Override
+                public void connect() throws IOException {
+                    connect(30000, 30000);
+                }
 
-        tomcat.stop();
+                @Override
+                public boolean isResponseBodyOK() {
+                    return true;
+                }
+            };
+
+            appDir = new File(webappDir, "examples");
+            client.setPort(getPort());
+            String basicHeader = (new BasicAuthHeader("Basic", "admin", "sekr3t")).getHeader().toString();
+
+            client.setRequest(new String[]{
+                    "GET /manager/text/deploy?war=" + URLEncoder.QUERY.encode(appDir.getAbsolutePath(), StandardCharsets.UTF_8) + " HTTP/1.1" + CRLF +
+                        "Host: localhost" + CRLF +
+                        "Authorization: " + basicHeader + CRLF +
+                        "Connection: Close" + CRLF + CRLF
+            });
+            client.connect();
+            client.processRequest(true);
+            Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
+            client.setRequest(new String[]{
+                    "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
+                        "Host: localhost" + CRLF +
+                        "Connection: Close" + CRLF + CRLF
+            });
+            client.connect();
+            client.processRequest(true);
+            Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, client.getStatusCode());
+
+            client.setRequest(new String[]{
+                    "GET /manager/text/start?path=/examples HTTP/1.1" + CRLF +
+                        "Host: localhost" + CRLF +
+                        "Authorization: " + basicHeader + CRLF +
+                        "Connection: Close" + CRLF + CRLF
+            });
+            client.connect();
+            client.processRequest(true);
+            Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
+            client.setRequest(new String[]{
+                    "GET /examples/servlets/servlet/RequestInfoExample HTTP/1.1" + CRLF +
+                        "Host: localhost" + CRLF +
+                        "Connection: Close" + CRLF + CRLF
+            });
+            client.connect();
+            client.processRequest(true);
+            Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+
+            tomcat.stop();
+        }
     }
 
     private static class FailOnceListener implements LifecycleListener {
diff --git a/test/org/apache/catalina/startup/TomcatBaseTest.java b/test/org/apache/catalina/startup/TomcatBaseTest.java
index 0957f9b159..1a1169d833 100644
--- a/test/org/apache/catalina/startup/TomcatBaseTest.java
+++ b/test/org/apache/catalina/startup/TomcatBaseTest.java
@@ -56,6 +56,8 @@ import org.junit.Assert;
 import org.junit.Before;
 
 import org.apache.catalina.Container;
+import org.apache.catalina.ContainerEvent;
+import org.apache.catalina.ContainerListener;
 import org.apache.catalina.Context;
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleEvent;
@@ -1091,4 +1093,50 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
         int insertIndex = formatted.indexOf("XXX");
         return (insertIndex == -1) ? formatted : formatted.substring(0, insertIndex);
     }
+
+    /**
+     * Injects a {@link LifecycleListener} to a {@link Context} of a {@link Container} that sends {@code ADD_CHILD_EVENT}.
+     * Useful when deploying with the Manager / HostConfig.
+     */
+    //TODO: make it generic to set other fields in the context as well like Valve, xmlValidation etc
+    public static class ContainerInjector implements ContainerListener, AutoCloseable {
+
+        private final Container container;
+        private final String contextPathToTest;
+        private final LifecycleListener listener;
+        private volatile boolean installed = false;
+
+        private ContainerInjector(Container container,
+                               String contextPathToTest,
+                               LifecycleListener listener) {
+            this.container = container;
+            this.contextPathToTest = contextPathToTest;
+            this.listener = listener;
+            container.addContainerListener(this);
+        }
+
+        public static ContainerInjector inject(Container container,
+                                            String contextPathToTest,
+                                            LifecycleListener listener) {
+            return new ContainerInjector(container, contextPathToTest, listener);
+        }
+
+        @Override
+        public void containerEvent(ContainerEvent event) {
+            if (Container.ADD_CHILD_EVENT.equals(event.getType()) && !installed) {
+                Object data = event.getData();
+                if (data instanceof Context ctx) {
+                    if (ctx.getPath().equals(contextPathToTest)) {
+                        ctx.addLifecycleListener(listener);
+                        installed = true;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void close() {
+            container.removeContainerListener(this);
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 07/07: Replace testing with programmatic configuration

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 604efd338ed7d576a0e954da2716b7d03491e197
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Tue Sep 9 18:11:05 2025 +0300

    Replace testing with programmatic configuration
---
 .../apache/catalina/manager/TestManagerWebapp.java | 40 +++++-----------------
 1 file changed, 8 insertions(+), 32 deletions(-)

diff --git a/test/org/apache/catalina/manager/TestManagerWebapp.java b/test/org/apache/catalina/manager/TestManagerWebapp.java
index 3c418340a8..e14d8008b4 100644
--- a/test/org/apache/catalina/manager/TestManagerWebapp.java
+++ b/test/org/apache/catalina/manager/TestManagerWebapp.java
@@ -531,40 +531,16 @@ public class TestManagerWebapp extends TomcatBaseTest {
         ctx.getParent().addLifecycleListener(hostConfig);
 
         File appRoot = new File(webappDir, "bug57700");
-        File webInf = new File(appRoot, "WEB-INF");
-        Assert.assertTrue(webInf.mkdirs() && webInf.isDirectory());
-        try (PrintWriter out = new PrintWriter(new File(appRoot, "index.html"), StandardCharsets.UTF_8)) {
-            out.println("ok");
-        }
-        try (PrintWriter out = new PrintWriter(new File(webInf, "web.xml"), StandardCharsets.UTF_8)) {
-            out.println("""
-                    <?xml version="1.0" encoding="UTF-8"?>
-                    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
-                             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-                             xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
-                                                 https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
-                             version="6.0">
-                      <servlet>
-                        <servlet-name>default</servlet-name>
-                        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
-                        <init-param>
-                          <param-name>listings</param-name>
-                          <param-value>false</param-value>
-                        </init-param>
-                      </servlet>
-                      <servlet-mapping>
-                        <servlet-name>default</servlet-name>
-                        <url-pattern>/</url-pattern>
-                      </servlet-mapping>
-                    </web-app>
-                    """);
-        }
+        Assert.assertTrue(appRoot.mkdirs() && appRoot.isDirectory());
         addDeleteOnTearDown(appRoot);
 
         try (TomcatBaseTest.ContainerInjector ignored =
                  TomcatBaseTest.ContainerInjector.inject(ctx.getParent(),
                      c -> c.getPath().equals("/bug57700"),
-                     c -> c.addLifecycleListener(new FailOnceListener()))) {
+                     c -> {
+                         c.addLifecycleListener(new FailOnceListener());
+                         Tomcat.initWebappDefaults(c);
+                     })) {
 
             tomcat.start();
             SimpleHttpClient client = new SimpleHttpClient() {
@@ -593,7 +569,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
             Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
 
             client.setRequest(new String[]{
-                    "GET /bug57700/index.html HTTP/1.1" + CRLF +
+                    "GET /bug57700 HTTP/1.1" + CRLF +
                         "Host: localhost" + CRLF +
                         "Connection: Close" + CRLF + CRLF
             });
@@ -612,13 +588,13 @@ public class TestManagerWebapp extends TomcatBaseTest {
             Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
 
             client.setRequest(new String[]{
-                    "GET /bug57700/index.html HTTP/1.1" + CRLF +
+                    "GET /bug57700 HTTP/1.1" + CRLF +
                         "Host: localhost" + CRLF +
                         "Connection: Close" + CRLF + CRLF
             });
             client.connect();
             client.processRequest(true);
-            Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+            Assert.assertEquals(HttpServletResponse.SC_FOUND, client.getStatusCode());
 
             client.setRequest(new String[] {
                     "GET /manager/text/undeploy?path=/bug57700 HTTP/1.1" + CRLF +


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 04/07: Make ContainerInjector generic to set other fields in the context as well like Valve, xmlValidation etc

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 9a532746838251d8663c858506518f40fcca102d
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Tue Sep 9 14:06:47 2025 +0300

    Make ContainerInjector generic to set other fields in the context as well like Valve, xmlValidation etc
---
 .../apache/catalina/manager/TestManagerWebapp.java |  4 +++-
 .../apache/catalina/startup/TomcatBaseTest.java    | 25 ++++++++++------------
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/test/org/apache/catalina/manager/TestManagerWebapp.java b/test/org/apache/catalina/manager/TestManagerWebapp.java
index a9aac4175d..68568fdf0a 100644
--- a/test/org/apache/catalina/manager/TestManagerWebapp.java
+++ b/test/org/apache/catalina/manager/TestManagerWebapp.java
@@ -531,7 +531,9 @@ public class TestManagerWebapp extends TomcatBaseTest {
         ctx.getParent().addLifecycleListener(hostConfig);
 
         try (TomcatBaseTest.ContainerInjector ignored =
-                 TomcatBaseTest.ContainerInjector.inject(ctx.getParent(), "/examples", new FailOnceListener())) {
+                 TomcatBaseTest.ContainerInjector.inject(ctx.getParent(),
+                     c -> c.getPath().equals("/examples"),
+                     c -> c.addLifecycleListener(new FailOnceListener()))) {
 
             tomcat.start();
             SimpleHttpClient client = new SimpleHttpClient() {
diff --git a/test/org/apache/catalina/startup/TomcatBaseTest.java b/test/org/apache/catalina/startup/TomcatBaseTest.java
index 1a1169d833..d3901b4ff2 100644
--- a/test/org/apache/catalina/startup/TomcatBaseTest.java
+++ b/test/org/apache/catalina/startup/TomcatBaseTest.java
@@ -39,6 +39,8 @@ import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -1098,27 +1100,22 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
      * Injects a {@link LifecycleListener} to a {@link Context} of a {@link Container} that sends {@code ADD_CHILD_EVENT}.
      * Useful when deploying with the Manager / HostConfig.
      */
-    //TODO: make it generic to set other fields in the context as well like Valve, xmlValidation etc
     public static class ContainerInjector implements ContainerListener, AutoCloseable {
 
         private final Container container;
-        private final String contextPathToTest;
-        private final LifecycleListener listener;
+        private final Predicate<Context> filter;
+        private final Consumer<Context> action;
         private volatile boolean installed = false;
 
-        private ContainerInjector(Container container,
-                               String contextPathToTest,
-                               LifecycleListener listener) {
+        private ContainerInjector(Container container, Predicate<Context> filter, Consumer<Context> action) {
             this.container = container;
-            this.contextPathToTest = contextPathToTest;
-            this.listener = listener;
+            this.filter = filter;
+            this.action = action;
             container.addContainerListener(this);
         }
 
-        public static ContainerInjector inject(Container container,
-                                            String contextPathToTest,
-                                            LifecycleListener listener) {
-            return new ContainerInjector(container, contextPathToTest, listener);
+        public static ContainerInjector inject(Container container, Predicate<Context> filter, Consumer<Context> action) {
+            return new ContainerInjector(container, filter, action);
         }
 
         @Override
@@ -1126,8 +1123,8 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
             if (Container.ADD_CHILD_EVENT.equals(event.getType()) && !installed) {
                 Object data = event.getData();
                 if (data instanceof Context ctx) {
-                    if (ctx.getPath().equals(contextPathToTest)) {
-                        ctx.addLifecycleListener(listener);
+                    if (filter != null && filter.test(ctx)) {
+                        action.accept(ctx);
                         installed = true;
                     }
                 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 02/07: Remove specific exception UnknownHostException as it's covered by general IOException and remove redundant initializer.

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dsoumis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit c9490bfe3c19d712c7d0cd37a8800ed03bf50c9a
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Mon Sep 8 15:42:28 2025 +0300

    Remove specific exception UnknownHostException as it's covered by general IOException and remove redundant initializer.
---
 test/org/apache/catalina/manager/TestManagerWebapp.java | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/test/org/apache/catalina/manager/TestManagerWebapp.java b/test/org/apache/catalina/manager/TestManagerWebapp.java
index bbe7e749e1..ddae0e288a 100644
--- a/test/org/apache/catalina/manager/TestManagerWebapp.java
+++ b/test/org/apache/catalina/manager/TestManagerWebapp.java
@@ -21,7 +21,6 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 
 import jakarta.servlet.http.HttpServletResponse;
@@ -282,7 +281,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
         SimpleHttpClient client = new SimpleHttpClient() {
             // 10s default too low for some CI systems
             @Override
-            public void connect() throws UnknownHostException, IOException {
+            public void connect() throws IOException {
                 connect(30000, 30000);
             }
 
@@ -403,7 +402,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
         File serverXml = new File(tomcat.getServer().getCatalinaBase(), Catalina.SERVER_XML);
         Assert.assertTrue(serverXml.canRead());
         addDeleteOnTearDown(serverXml);
-        String serverXmlDump = "";
+        String serverXmlDump;
         try (FileReader reader = new FileReader(serverXml); StringWriter writer = new StringWriter()) {
             IOTools.flow(reader, writer);
             serverXmlDump = writer.toString();
@@ -548,7 +547,7 @@ public class TestManagerWebapp extends TomcatBaseTest {
         tomcat.start();
         SimpleHttpClient client = new SimpleHttpClient() {
             @Override
-            public void connect() throws UnknownHostException, IOException {
+            public void connect() throws IOException {
                 connect(30000, 30000);
             }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org