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

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


The following commit(s) were added to refs/heads/main by this push:
     new c2e932b70 Fix arg-matching in 
ExceptionMapperTest.testFullExceptionIsLogged() (#2531)
c2e932b70 is described below

commit c2e932b7064e7ae5551e192c8dd273de2da9fd0d
Author: Robert Stupp <[email protected]>
AuthorDate: Thu Sep 11 10:14:02 2025 +0200

    Fix arg-matching in ExceptionMapperTest.testFullExceptionIsLogged() (#2531)
    
    The above test asserts the the log record passed to 
`org.jboss.logmanager.Logger#logRaw(org.jboss.logmanager.ExtLogRecord)`. For 
the sake of this test, both the `IcebergJsonProcessingExceptionMapper` and 
`IcebergExceptionMapper` have a visible-for-testing function `getLogger()` to 
provide a mocked logger. `getLogger()` however is used for "all the logging", 
which makes the behavior `verify(JBOSS_LOGGER).logRaw(argThat(...))` 
"interesting" - the test fails with #2461 although no relate [...]
    
    But eventually the test failure's caused by using `getLogger()` for all 
logging, which may provide the _wrong_ log record and cause the test to fail.
    
    This change renames the `getLogger()` functions to make their special 
meaning clear, and adds some clarifying comments in the code.
    
    Also adding some more test cases for the various exception mapper code 
paths.
    
    Co-authored-by: Alexandre Dutra <[email protected]>
---
 .../service/exception/IcebergExceptionMapper.java  | 23 ++++---
 .../IcebergJsonProcessingExceptionMapper.java      | 12 ++--
 .../service/exception/ExceptionMapperTest.java     | 70 +++++++++++++++++-----
 3 files changed, 76 insertions(+), 29 deletions(-)

diff --git 
a/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
 
b/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
index 6e2dec197..c9d91815d 100644
--- 
a/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
+++ 
b/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
@@ -89,15 +89,16 @@ public class IcebergExceptionMapper implements 
ExceptionMapper<RuntimeException>
 
   @Override
   public Response toResponse(RuntimeException runtimeException) {
-    getLogger().info("Handling runtimeException {}", 
runtimeException.getMessage());
+    LOGGER.info("Handling runtimeException {}", runtimeException.getMessage());
 
     int responseCode = mapExceptionToResponseCode(runtimeException);
-    getLogger()
-        .atLevel(responseCode >= 500 ? Level.INFO : Level.DEBUG)
-        .log("Full RuntimeException", runtimeException);
-
-    if (responseCode == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) 
{
-      getLogger().error("Unhandled exception returning INTERNAL_SERVER_ERROR", 
runtimeException);
+    if (responseCode == Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
+      getLoggerForExceptionLogging()
+          .error("Unhandled exception returning INTERNAL_SERVER_ERROR", 
runtimeException);
+    } else {
+      getLoggerForExceptionLogging()
+          .atLevel(responseCode > 500 ? Level.INFO : Level.DEBUG)
+          .log("Full RuntimeException", runtimeException);
     }
 
     ErrorResponse icebergErrorResponse =
@@ -111,7 +112,7 @@ public class IcebergExceptionMapper implements 
ExceptionMapper<RuntimeException>
             .entity(icebergErrorResponse)
             .type(MediaType.APPLICATION_JSON_TYPE)
             .build();
-    getLogger().debug("Mapped exception to errorResp: {}", errorResp);
+    LOGGER.debug("Mapped exception to errorResp: {}", errorResp);
     return errorResp;
   }
 
@@ -261,8 +262,12 @@ public class IcebergExceptionMapper implements 
ExceptionMapper<RuntimeException>
     return Optional.of(Status.INTERNAL_SERVER_ERROR.getStatusCode());
   }
 
+  /**
+   * This function is only present for the {@code ExceptionMapperTest} and 
must only be used once
+   * during any execution of {@link #toResponse(RuntimeException)}.
+   */
   @VisibleForTesting
-  Logger getLogger() {
+  Logger getLoggerForExceptionLogging() {
     return LOGGER;
   }
 }
diff --git 
a/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergJsonProcessingExceptionMapper.java
 
b/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergJsonProcessingExceptionMapper.java
index 10130700c..7d9674f90 100644
--- 
a/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergJsonProcessingExceptionMapper.java
+++ 
b/runtime/service/src/main/java/org/apache/polaris/service/exception/IcebergJsonProcessingExceptionMapper.java
@@ -61,7 +61,7 @@ public class IcebergJsonProcessingExceptionMapper
     if (exception instanceof JsonGenerationException
         || exception instanceof InvalidDefinitionException) {
       long id = ThreadLocalRandom.current().nextLong();
-      getLogger()
+      getLoggerForExceptionLogging()
           .error(String.format(Locale.ROOT, "Error handling a request: %016x", 
id), exception);
       String message =
           String.format(
@@ -77,8 +77,8 @@ public class IcebergJsonProcessingExceptionMapper
     /*
      * Otherwise, it's those pesky users.
      */
-    getLogger().info("Unable to process JSON: {}", exception.getMessage());
-    getLogger().debug("Full JsonProcessingException", exception);
+    LOGGER.info("Unable to process JSON: {}", exception.getMessage());
+    getLoggerForExceptionLogging().debug("Full JsonProcessingException", 
exception);
 
     String messagePrefix =
         switch (exception) {
@@ -99,8 +99,12 @@ public class IcebergJsonProcessingExceptionMapper
         .build();
   }
 
+  /**
+   * This function is only present for the {@code ExceptionMapperTest} and 
must only be used during
+   * once any execution of {@link #toResponse(JsonProcessingException)}.
+   */
   @VisibleForTesting
-  Logger getLogger() {
+  Logger getLoggerForExceptionLogging() {
     return LOGGER;
   }
 }
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java
index 7ba2bd3e6..f37d34db5 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java
@@ -18,21 +18,25 @@
  */
 package org.apache.polaris.service.exception;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.assertArg;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.fasterxml.jackson.core.JsonGenerationException;
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import jakarta.ws.rs.ForbiddenException;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.ext.ExceptionMapper;
+import java.io.IOException;
 import java.util.Optional;
 import java.util.stream.Stream;
+import org.apache.iceberg.exceptions.RuntimeIOException;
 import org.apache.polaris.core.exceptions.AlreadyExistsException;
 import org.apache.polaris.core.exceptions.CommitConflictException;
-import org.assertj.core.api.Assertions;
 import org.jboss.logmanager.Level;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -67,27 +71,25 @@ public class ExceptionMapperTest {
 
     verify(JBOSS_LOGGER)
         .logRaw(
-            argThat(
+            assertArg(
                 record -> {
-                  if (record.getLevel() != level) {
-                    return false;
-                  }
+                  assertThat(record.getLevel()).isEqualTo(level);
 
                   String message = record.getMessage();
                   if (message == null) {
-                    return false;
+                    return;
                   }
 
                   Throwable error = record.getThrown();
                   if (error == null) {
-                    return false;
+                    return;
                   }
 
-                  return message.contains(CAUSE)
-                      || Optional.ofNullable(error.getCause())
-                          .map(Throwable::getMessage)
-                          .orElse("")
-                          .contains(CAUSE);
+                  assertThat(
+                          Optional.ofNullable(error.getCause())
+                              .map(Throwable::getMessage)
+                              .orElse(message))
+                      .contains(CAUSE);
                 }));
   }
 
@@ -95,7 +97,7 @@ public class ExceptionMapperTest {
   public void testNamespaceException() {
     PolarisExceptionMapper mapper = new PolarisExceptionMapper();
     Response response = mapper.toResponse(new CommitConflictException("test"));
-    Assertions.assertThat(response.getStatus()).isEqualTo(409);
+    assertThat(response.getStatus()).isEqualTo(409);
   }
 
   static Stream<Arguments> testFullExceptionIsLogged() {
@@ -105,21 +107,57 @@ public class ExceptionMapperTest {
         Arguments.of(
             new IcebergExceptionMapper() {
               @Override
-              Logger getLogger() {
+              Logger getLoggerForExceptionLogging() {
                 return new Slf4jLogger(JBOSS_LOGGER);
               }
             },
             new RuntimeException(MESSAGE, new RuntimeException(CAUSE)),
             Level.ERROR),
+        Arguments.of(
+            new IcebergExceptionMapper() {
+              @Override
+              Logger getLoggerForExceptionLogging() {
+                return new Slf4jLogger(JBOSS_LOGGER);
+              }
+            },
+            new RuntimeIOException(new IOException(new 
RuntimeException(CAUSE)), "%s", MESSAGE),
+            Level.INFO),
+        Arguments.of(
+            new IcebergExceptionMapper() {
+              @Override
+              Logger getLoggerForExceptionLogging() {
+                return new Slf4jLogger(JBOSS_LOGGER);
+              }
+            },
+            new ForbiddenException(MESSAGE, new RuntimeException(CAUSE)),
+            Level.DEBUG),
         Arguments.of(
             new IcebergJsonProcessingExceptionMapper() {
               @Override
-              Logger getLogger() {
+              Logger getLoggerForExceptionLogging() {
                 return new Slf4jLogger(JBOSS_LOGGER);
               }
             },
             new TestJsonProcessingException(MESSAGE, null, new 
RuntimeException(CAUSE)),
             Level.DEBUG),
+        Arguments.of(
+            new IcebergJsonProcessingExceptionMapper() {
+              @Override
+              Logger getLoggerForExceptionLogging() {
+                return new Slf4jLogger(JBOSS_LOGGER);
+              }
+            },
+            new TestJsonProcessingException(MESSAGE, null, new 
RuntimeException(CAUSE)),
+            Level.DEBUG),
+        Arguments.of(
+            new IcebergJsonProcessingExceptionMapper() {
+              @Override
+              Logger getLoggerForExceptionLogging() {
+                return new Slf4jLogger(JBOSS_LOGGER);
+              }
+            },
+            new JsonGenerationException(MESSAGE, new RuntimeException(CAUSE), 
null),
+            Level.ERROR),
         Arguments.of(
             new PolarisExceptionMapper() {
               @Override

Reply via email to