This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 7dd925c456 TODO-366: consolidate REST-server debug on RichLogger
7dd925c456 is described below
commit 7dd925c456475f7561c5f7724ff8caf325e35a85
Author: James Bognar <[email protected]>
AuthorDate: Sat Aug 15 14:44:09 2026 -0400
TODO-366: consolidate REST-server debug on RichLogger
Widen RestOpContext.getLogger() to return RichLogger, delete
CapturingRestDebugFormatter and its rest-server test plus the TestBeanStore
overlay, and port the rest-mock end-to-end debug tests to name-based
RichLogger.captureEvents (including the new 404/mixin host-logger-name case).
Keep BasicTestRestDebugFormatter. Update juneau-docs testing topic + 10.0.0
release notes to the RichLogger capture pattern.
---
.../mock/CapturingRestDebugFormatter_Test.java | 128 ----------------
.../juneau/rest/mock/RestDebugCapture_Test.java | 153 ++++++++++++++++++++
.../apache/juneau/rest/server/RestOpContext.java | 13 +-
.../logging/CapturingRestDebugFormatter.java | 161 ---------------------
.../juneau/rest/server/RestOpContext_Test.java | 29 ++++
.../logging/CapturingRestDebugFormatter_Test.java | 92 ------------
6 files changed, 189 insertions(+), 387 deletions(-)
diff --git
a/juneau-rest/juneau-rest-mock/src/test/java/org/apache/juneau/rest/mock/CapturingRestDebugFormatter_Test.java
b/juneau-rest/juneau-rest-mock/src/test/java/org/apache/juneau/rest/mock/CapturingRestDebugFormatter_Test.java
deleted file mode 100644
index 61a4175b9d..0000000000
---
a/juneau-rest/juneau-rest-mock/src/test/java/org/apache/juneau/rest/mock/CapturingRestDebugFormatter_Test.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.juneau.rest.mock;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.logging.*;
-
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.rest.server.logging.*;
-import org.apache.juneau.test.junit.*;
-import org.junit.jupiter.api.*;
-
-/**
- * End-to-end tests for {@link CapturingRestDebugFormatter} dispatched through
- * {@code mock.classic.MockRestClient} — exercises the classic client's
{@code Builder.debug()} →
- * {@code MockServletRequest.logLevel(...)} →
save/restore-around-dispatch path that replaced the removed
- * {@code BasicTestCaptureCallLogger}.
- *
- * @since 10.0.0
- */
-@SuppressWarnings("resource") // MockRestClient instances are short-lived test
fixtures.
-class CapturingRestDebugFormatter_Test {
-
- @Rest(path="/api")
- public static class A_Resource {
-
- @RestGet(path="/who")
- public String who() {
- return "ok";
- }
-
- @RestGet(path="/err")
- public String err(RestResponse res) {
- // Resource code explicitly reports a handled exception
via RestResponse#setException(Throwable),
- // which is what
CapturingRestDebugFormatter.getThrown()/assertThrown() surface after dispatch.
- res.setException(new RuntimeException("boom"));
- return "handled";
- }
- }
-
- @Test void a01_debugEnabled_capturesAtFinestTier() throws Exception {
- var formatter = new CapturingRestDebugFormatter();
- var overlay = new
TestBeanStore().override(RestDebugFormatter.class, formatter);
-
- var client = org.apache.juneau.rest.mock.classic.MockRestClient
- .create(A_Resource.class)
- .overridingBeanStore(overlay)
- .debug()
- .build();
-
- client.get("/who").run().getContent().asString();
-
- assertEquals(Level.FINEST, formatter.getLevel());
- formatter.assertMessage().isContains("[200] HTTP GET /api/who");
- assertNull(formatter.getThrown());
- }
-
- @Test void a02_assertMessageAndReset_clearsCapturedState() throws
Exception {
- var formatter = new CapturingRestDebugFormatter();
- var overlay = new
TestBeanStore().override(RestDebugFormatter.class, formatter);
-
- var client = org.apache.juneau.rest.mock.classic.MockRestClient
- .create(A_Resource.class)
- .overridingBeanStore(overlay)
- .debug()
- .build();
-
- client.get("/who").run().getContent().asString();
-
- formatter.assertMessageAndReset().isContains("HTTP GET");
- assertNull(formatter.getMessage());
- assertNull(formatter.getLevel());
- }
-
- @Test void a03_debugDisabled_leavesResourceLoggerLevelUnchanged()
throws Exception {
- var target = Logger.getLogger(A_Resource.class.getName());
- var prevLevel = target.getLevel();
- target.setLevel(Level.OFF);
- try {
- var formatter = new CapturingRestDebugFormatter();
- var overlay = new
TestBeanStore().override(RestDebugFormatter.class, formatter);
-
- // No .debug() call -> logLevel(null) -> the
save/restore wrapper is never engaged.
- var client =
org.apache.juneau.rest.mock.classic.MockRestClient
- .create(A_Resource.class)
- .overridingBeanStore(overlay)
- .build();
-
- client.get("/who").run().getContent().asString();
-
- assertNull(formatter.getMessage(), "Nothing should be
captured below the resource logger's resolved level");
- assertEquals(Level.OFF, target.getLevel(), "Logger
level must be left untouched when no debug override is requested");
- } finally {
- target.setLevel(prevLevel);
- }
- }
-
- @Test void a04_thrownExceptionIsCaptured() throws Exception {
- var formatter = new CapturingRestDebugFormatter();
- var overlay = new
TestBeanStore().override(RestDebugFormatter.class, formatter);
-
- var client = org.apache.juneau.rest.mock.classic.MockRestClient
- .create(A_Resource.class)
- .overridingBeanStore(overlay)
- .debug()
- .build();
-
- client.get("/err").run().assertStatus().asCode().is(200);
-
- assertNotNull(formatter.getThrown());
- formatter.assertThrown().asMessage().is("boom");
- }
-}
diff --git
a/juneau-rest/juneau-rest-mock/src/test/java/org/apache/juneau/rest/mock/RestDebugCapture_Test.java
b/juneau-rest/juneau-rest-mock/src/test/java/org/apache/juneau/rest/mock/RestDebugCapture_Test.java
new file mode 100644
index 0000000000..70627714aa
--- /dev/null
+++
b/juneau-rest/juneau-rest-mock/src/test/java/org/apache/juneau/rest/mock/RestDebugCapture_Test.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.juneau.rest.mock;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.logging.*;
+
+import org.apache.juneau.commons.logging.*;
+import org.apache.juneau.rest.server.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * End-to-end REST debug capture tests through {@code
mock.classic.MockRestClient}.
+ *
+ * @since 10.0.0
+ */
+@SuppressWarnings({
+ "resource" // MockRestClient instances are short-lived test fixtures.
+})
+class RestDebugCapture_Test {
+
+ @Rest(path="/api")
+ public static class A_Resource {
+
+ @RestGet(path="/who")
+ public String who() {
+ return "ok";
+ }
+
+ @RestGet(path="/err")
+ public String err(RestResponse res) {
+ res.setException(new RuntimeException("boom"));
+ return "handled";
+ }
+ }
+
+ public static class A05_Mixin {
+ @RestGet(path="/who")
+ public String who() {
+ return "ok";
+ }
+ }
+
+ @Rest(path="/mix", mixins=A05_Mixin.class)
+ public static class A05_HostResource {}
+
+ @Test void a01_debugEnabled_capturesAtFinestTier() throws Exception {
+ try (var c =
RichLogger.getLogger(A_Resource.class).captureEvents(Level.FINEST)) {
+ var client =
org.apache.juneau.rest.mock.classic.MockRestClient
+ .create(A_Resource.class)
+ .debug()
+ .build();
+
+ client.get("/who").run().getContent().asString();
+
+ assertFalse(c.isEmpty());
+ assertEquals(Level.FINEST, c.last().getLevel());
+ assertTrue(c.last().getMessage().contains("[200] HTTP
GET /api/who"));
+ assertNull(c.last().getThrown());
+ }
+ }
+
+ @Test void a02_clear_resetsCapturedState() throws Exception {
+ try (var c =
RichLogger.getLogger(A_Resource.class).captureEvents(Level.FINEST)) {
+ var client =
org.apache.juneau.rest.mock.classic.MockRestClient
+ .create(A_Resource.class)
+ .debug()
+ .build();
+
+ client.get("/who").run().getContent().asString();
+ assertFalse(c.isEmpty());
+
+ c.clear();
+ assertTrue(c.isEmpty());
+ assertNull(c.last());
+
+ client.get("/who").run().getContent().asString();
+ assertFalse(c.isEmpty());
+ }
+ }
+
+ @Test void a03_debugDisabled_leavesResourceLoggerLevelUnchanged()
throws Exception {
+ var target = Logger.getLogger(A_Resource.class.getName());
+ var prevLevel = target.getLevel();
+ target.setLevel(Level.OFF);
+ try (var c =
RichLogger.getLogger(A_Resource.class).captureEvents(Level.FINEST)) {
+ var client =
org.apache.juneau.rest.mock.classic.MockRestClient
+ .create(A_Resource.class)
+ .build();
+
+ client.get("/who").run().getContent().asString();
+
+ assertTrue(c.isEmpty(), "No records should be captured
below the resolved logger tier");
+ assertEquals(Level.OFF, target.getLevel(), "Logger
level should remain unchanged without .debug()");
+ } finally {
+ target.setLevel(prevLevel);
+ }
+ }
+
+ @Test void a04_thrownExceptionIsCaptured() throws Exception {
+ try (var c =
RichLogger.getLogger(A_Resource.class).captureEvents(Level.FINEST)) {
+ var client =
org.apache.juneau.rest.mock.classic.MockRestClient
+ .create(A_Resource.class)
+ .debug()
+ .build();
+
+
client.get("/err").run().assertStatus().asCode().is(200);
+
+ assertNotNull(c.last());
+ assertNotNull(c.last().getThrown());
+ assertEquals("boom", c.last().getThrown().getMessage());
+ }
+ }
+
+ @Test void a05_captureByHostName_observesOpAndNoOpLoggerPaths() throws
Exception {
+ var hostName = A05_HostResource.class.getName();
+ try (var c =
RichLogger.getLogger(A05_HostResource.class).captureEvents(Level.FINEST)) {
+ var client =
org.apache.juneau.rest.mock.classic.MockRestClient
+ .create(A05_HostResource.class)
+ .debug()
+ .build();
+
+
client.get("/who").run().assertStatus().asCode().is(200);
+
client.get("/missing").ignoreErrors().run().assertStatus().asCode().is(404);
+
+ var records = c.getRecords();
+
assertTrue(records.stream().map(java.util.logging.LogRecord::getLoggerName).anyMatch((hostName
+ ".who")::equals));
+
assertTrue(records.stream().map(java.util.logging.LogRecord::getLoggerName).anyMatch(hostName::equals));
+
+ var noOpRecord = records.stream()
+ .filter(x -> hostName.equals(x.getLoggerName()))
+ .reduce((a, b) -> b)
+ .orElse(null);
+ assertNotNull(noOpRecord);
+ assertTrue(noOpRecord.getMessage().contains("[404] HTTP
GET /mix/missing"));
+ }
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
index e9be4d6303..4f11a0112e 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
@@ -42,6 +42,7 @@ import org.apache.juneau.commons.function.*;
import org.apache.juneau.commons.http.*;
import org.apache.juneau.commons.inject.*;
import org.apache.juneau.commons.lang.*;
+import org.apache.juneau.commons.logging.*;
import org.apache.juneau.commons.reflect.*;
import org.apache.juneau.commons.svl.*;
import org.apache.juneau.commons.utils.*;
@@ -260,7 +261,7 @@ public class RestOpContext extends Context implements
Comparable<RestOpContext>
});
/**
- * The per-operation JUL logger for debug capture.
+ * The per-operation logger for debug capture.
*
* <p>
* A hierarchical child of the <b>host</b> resource logger ({@code
<hostResourceClass>.<methodName>}) so an operator
@@ -273,8 +274,8 @@ public class RestOpContext extends Context implements
Comparable<RestOpContext>
* distinct, host-isolated loggers. Non-mixin operations (including
child resources, which are their own resources)
* resolve to their own resource class as before.
*/
- private final Memoizer<Logger> logger = memoizer(() ->
- Logger.getLogger(hostResourceClass().getName() + "." +
getJavaMethod().getName()));
+ private final Memoizer<RichLogger> logger = memoizer(() ->
+ RichLogger.getLogger(hostResourceClass().getName() + "." +
getJavaMethod().getName()));
/**
* Returns the host / top-level resource class for logger naming.
@@ -1749,15 +1750,15 @@ public class RestOpContext extends Context implements
Comparable<RestOpContext>
public List<RestMatcher> getRequiredMatchers() { return
requiredMatchersView.get(); }
/**
- * Returns the per-operation JUL logger used for debug capture.
+ * Returns the per-operation logger used for debug capture.
*
* <p>
- * A hierarchical child of the resource logger ({@code
<resourceClass>.<methodName>}).
+ * A hierarchical child of the host resource logger ({@code
<hostResourceClass>.<methodName>}).
*
* @return The per-operation logger.
* <br>Never <jk>null</jk>.
*/
- public Logger getLogger() { return logger.get(); }
+ public RichLogger getLogger() { return logger.get(); }
/**
* Returns metadata about the specified response object if it's
annotated with {@link Response @Response}.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/logging/CapturingRestDebugFormatter.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/logging/CapturingRestDebugFormatter.java
deleted file mode 100644
index f69332b57e..0000000000
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/logging/CapturingRestDebugFormatter.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.juneau.rest.server.logging;
-
-import java.util.logging.*;
-
-import org.apache.juneau.rest.server.*;
-import org.apache.juneau.test.assertions.*;
-
-/**
- * A {@link RestDebugFormatter} that captures the last fully-rendered
(cumulative) debug message for test assertions.
- *
- * <p>
- * Replaces the pre-10.0 {@code CapturingFormat}/{@code
BasicTestCaptureCallLogger} test utilities. Instead of emitting
- * the rendered message to a log file, the cumulative message is retained in
an internal holder alongside the resolved
- * tier level and thrown exception. After a request, tests can inspect them
via {@link #getMessage()}/
- * {@link #assertMessage()} (and the {@code *AndReset} variants), {@link
#getLevel()}, and {@link #getThrown()}.
- *
- * <p>
- * The tier {@link #getLevel() level} is inferred from which tier methods the
pipeline invoked for the current record:
- * {@link #formatBasic(RestRequest,RestResponse) formatBasic} always begins a
new capture ({@code INFO});
- * {@link #formatHeaders(RestRequest,RestResponse) formatHeaders} raises it to
{@code FINE};
- * {@link #formatBody(RestRequest,RestResponse) formatBody} raises it to
{@code FINEST}.
- *
- * <h5 class='section'>See Also:</h5><ul>
- * <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/RestServerLoggingAndDebugging">Logging
/ Debugging</a>
- * </ul>
- *
- * @since 10.0.0
- */
-public class CapturingRestDebugFormatter extends BasicRestDebugFormatter {
-
- private StringBuilder buffer;
- private String message;
- private Level level;
- private Throwable thrown;
-
- @Override /* Overridden from BasicRestDebugFormatter */
- public synchronized String formatBasic(RestRequest req, RestResponse
res) {
- var s = super.formatBasic(req, res);
- buffer = new StringBuilder(s);
- message = buffer.toString();
- level = Level.INFO;
- thrown = req.getException();
- return s;
- }
-
- @Override /* Overridden from BasicRestDebugFormatter */
- public synchronized String formatHeaders(RestRequest req, RestResponse
res) {
- var s = super.formatHeaders(req, res);
- if (buffer != null) {
- buffer.append(s);
- message = buffer.toString();
- }
- level = Level.FINE;
- return s;
- }
-
- @Override /* Overridden from BasicRestDebugFormatter */
- public synchronized String formatBody(RestRequest req, RestResponse
res) {
- var s = super.formatBody(req, res);
- if (buffer != null) {
- buffer.append(s);
- message = buffer.toString();
- }
- level = Level.FINEST;
- return s;
- }
-
- /**
- * Returns an assertion of the last captured message.
- *
- * @return The last captured message as an assertion object. Never
<jk>null</jk>.
- */
- public StringAssertion assertMessage() {
- return new StringAssertion(getMessage());
- }
-
- /**
- * Returns an assertion of the last captured message and then clears
the holder.
- *
- * @return The last captured message as an assertion object. Never
<jk>null</jk>.
- */
- public StringAssertion assertMessageAndReset() {
- return new StringAssertion(getMessageAndReset());
- }
-
- /**
- * Returns an assertion of the last captured throwable.
- *
- * @return The last captured throwable as an assertion object. Never
<jk>null</jk>.
- */
- public ThrowableAssertion<Throwable> assertThrown() {
- return new ThrowableAssertion<>(getThrown());
- }
-
- /**
- * Returns the resolved tier level of the last captured message.
- *
- * @return The last captured level, or <jk>null</jk> if nothing was
captured.
- */
- public synchronized Level getLevel() {
- return level;
- }
-
- /**
- * Returns the last captured (cumulative) message.
- *
- * @return The last captured message, or <jk>null</jk> if nothing was
captured.
- */
- public synchronized String getMessage() {
- return message;
- }
-
- /**
- * Returns the last captured message and then clears the holder.
- *
- * @return The last captured message, or <jk>null</jk> if nothing was
captured.
- */
- public synchronized String getMessageAndReset() {
- var m = message;
- reset();
- return m;
- }
-
- /**
- * Returns the last captured throwable.
- *
- * @return The last captured throwable, or <jk>null</jk> if nothing was
captured.
- */
- public synchronized Throwable getThrown() {
- return thrown;
- }
-
- /**
- * Clears the internal holder.
- *
- * @return This object.
- */
- public synchronized CapturingRestDebugFormatter reset() {
- buffer = null;
- message = null;
- level = null;
- thrown = null;
- return this;
- }
-}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/RestOpContext_Test.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/RestOpContext_Test.java
index 86a7a21812..185e1009d0 100644
---
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/RestOpContext_Test.java
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/RestOpContext_Test.java
@@ -17,10 +17,13 @@
package org.apache.juneau.rest.server;
import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
import java.util.concurrent.*;
+import java.util.logging.*;
import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.commons.logging.*;
import org.apache.juneau.rest.server.converter.*;
import org.apache.juneau.rest.server.httppart.*;
import org.junit.jupiter.api.*;
@@ -445,4 +448,30 @@ class RestOpContext_Test extends
org.apache.juneau.TestBase {
var ctx = new RestContext(argsOf(Fix_ValueShorthand.class,
Fix_ValueShorthand::new));
assertEquals("PATCH", opOf(ctx, "opNoPath").getHttpMethod());
}
+
+
//-----------------------------------------------------------------------------------------------------------
+ // k - getLogger(): RichLogger canonical identity and FINEST
session-capture gate wiring.
+
//-----------------------------------------------------------------------------------------------------------
+
+ @Test void k01_getLogger_returnsCanonicalRichLogger_forHostMethodName()
throws Exception {
+ var ctx = new RestContext(argsOf(Fix_Bare.class,
Fix_Bare::new));
+ var op = opOf(ctx, "op");
+ var name = Fix_Bare.class.getName() + ".op";
+ assertSame(RichLogger.getLogger(name), op.getLogger());
+ }
+
+ @Test void
k02_createSession_installsBodyCapture_whenLoggerIsFinestLoggable() throws
Exception {
+ var ctx = new RestContext(argsOf(Fix_Bare.class,
Fix_Bare::new));
+ var op = opOf(ctx, "op");
+ var session = mock(RestSession.class);
+ var target = Logger.getLogger(Fix_Bare.class.getName());
+ var prevLevel = target.getLevel();
+ target.setLevel(Level.FINEST);
+ try {
+ op.createSession(session);
+ verify(session).installCapture();
+ } finally {
+ target.setLevel(prevLevel);
+ }
+ }
}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/logging/CapturingRestDebugFormatter_Test.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/logging/CapturingRestDebugFormatter_Test.java
deleted file mode 100644
index 2480855297..0000000000
---
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/server/logging/CapturingRestDebugFormatter_Test.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.juneau.rest.server.logging;
-
-import static java.util.Collections.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.util.logging.*;
-
-import org.apache.juneau.rest.server.*;
-import org.junit.jupiter.api.*;
-
-import jakarta.servlet.http.*;
-
-/**
- * Unit tests for {@link CapturingRestDebugFormatter} — message capture, tier
inference, and thrown capture.
- *
- * @since 10.0.0
- */
-@SuppressWarnings("resource") // Mockito mocks; nothing to close.
-class CapturingRestDebugFormatter_Test {
-
- private final CapturingRestDebugFormatter f = new
CapturingRestDebugFormatter();
-
- private RestRequest req;
- private RestResponse res;
-
- @BeforeEach void setUp() {
- req = mock(RestRequest.class);
- res = mock(RestResponse.class);
- var sreq = mock(HttpServletRequest.class);
- var sres = mock(HttpServletResponse.class);
- when(req.getHttpServletRequest()).thenReturn(sreq);
- when(res.getHttpServletResponse()).thenReturn(sres);
- when(sres.getStatus()).thenReturn(200);
- when(sreq.getMethod()).thenReturn("GET");
- when(sreq.getRequestURI()).thenReturn("/foo");
- when(sreq.getHeaderNames()).thenReturn(emptyEnumeration());
- when(sres.getHeaderNames()).thenReturn(emptyList());
- when(req.getCachedContentLength()).thenReturn(-1L);
- when(res.getCachedContentLength()).thenReturn(-1L);
- }
-
- @Test void a01_capturesBasicMessage_atInfoTier() {
- f.formatBasic(req, res);
- assertEquals("[200] HTTP GET /foo", f.getMessage());
- assertEquals(Level.INFO, f.getLevel());
- }
-
- @Test void a02_headersRaiseTierToFine() {
- f.formatBasic(req, res);
- f.formatHeaders(req, res);
- assertEquals(Level.FINE, f.getLevel());
- assertTrue(f.getMessage().startsWith("[200] HTTP GET /foo"));
- }
-
- @Test void a03_bodyRaisesTierToFinest() {
- f.formatBasic(req, res);
- f.formatHeaders(req, res);
- f.formatBody(req, res);
- assertEquals(Level.FINEST, f.getLevel());
- }
-
- @Test void a04_capturesThrown() {
- var t = new RuntimeException("boom");
- when(req.getException()).thenReturn(t);
- f.formatBasic(req, res);
- assertSame(t, f.getThrown());
- }
-
- @Test void a05_getMessageAndReset_clears() {
- f.formatBasic(req, res);
- assertNotNull(f.getMessageAndReset());
- assertNull(f.getMessage());
- assertNull(f.getLevel());
- }
-}