com.github.tomakehurst
wiremock-standalone
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/ClientLogger.java b/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/ClientLogger.java
index f07249162cb73..556b1b745adb9 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/ClientLogger.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/ClientLogger.java
@@ -6,12 +6,13 @@
import com.azure.core.implementation.logging.DefaultLogger;
import com.azure.core.util.Configuration;
import com.azure.core.util.CoreUtils;
-import java.util.Arrays;
-import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.NOPLogger;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* This is a fluent logger helper class that wraps a pluggable {@link Logger}.
*
@@ -134,23 +135,46 @@ public void error(String format, Object... args) {
/**
* Logs the {@link RuntimeException} at the warning level and returns it to be thrown.
+ *
+ * This API covers the cases where a runtime exception type needs to be thrown and logged. If a {@link Throwable} is
+ * being logged use {@link #logThowableAsWarning(Throwable)} instead.
*
* @param runtimeException RuntimeException to be logged and returned.
- * @return The passed {@code RuntimeException}.
+ * @return The passed {@link RuntimeException}.
* @throws NullPointerException If {@code runtimeException} is {@code null}.
*/
public RuntimeException logExceptionAsWarning(RuntimeException runtimeException) {
Objects.requireNonNull(runtimeException, "'runtimeException' cannot be null.");
+
+ return logThowableAsWarning(runtimeException);
+ }
+
+ /**
+ * Logs the {@link Throwable} at the warning level and returns it to be thrown.
+ *
+ * This API covers the cases where a checked exception type needs to be thrown and logged. If a {@link
+ * RuntimeException} is being logged use {@link #logExceptionAsWarning(RuntimeException)} instead.
+ *
+ * @param throwable Throwable to be logged and returned.
+ * @param Type of the Throwable being logged.
+ * @return The passed {@link Throwable}.
+ * @throws NullPointerException If {@code throwable} is {@code null}.
+ */
+ public T logThowableAsWarning(T throwable) {
+ Objects.requireNonNull(throwable, "'throwable' cannot be null.");
if (!logger.isWarnEnabled()) {
- return runtimeException;
+ return throwable;
}
- performLogging(LogLevel.WARNING, true, runtimeException.getMessage(), runtimeException);
- return runtimeException;
+ performLogging(LogLevel.WARNING, true, throwable.getMessage(), throwable);
+ return throwable;
}
/**
* Logs the {@link RuntimeException} at the error level and returns it to be thrown.
+ *
+ * This API covers the cases where a runtime exception type needs to be thrown and logged. If a {@link Throwable} is
+ * being logged use {@link #logThrowableAsError(Throwable)} instead.
*
* @param runtimeException RuntimeException to be logged and returned.
* @return The passed {@code RuntimeException}.
@@ -158,13 +182,29 @@ public RuntimeException logExceptionAsWarning(RuntimeException runtimeException)
*/
public RuntimeException logExceptionAsError(RuntimeException runtimeException) {
Objects.requireNonNull(runtimeException, "'runtimeException' cannot be null.");
+
+ return logThrowableAsError(runtimeException);
+ }
+
+ /**
+ * Logs the {@link Throwable} at the error level and returns it to be thrown.
+ *
+ * This API covers the cases where a checked exception type needs to be thrown and logged. If a {@link
+ * RuntimeException} is being logged use {@link #logExceptionAsError(RuntimeException)} instead.
+ *
+ * @param throwable Throwable to be logged and returned.
+ * @param Type of the Throwable being logged.
+ * @return The passed {@link Throwable}.
+ * @throws NullPointerException If {@code throwable} is {@code null}.
+ */
+ public T logThrowableAsError(T throwable) {
+ Objects.requireNonNull(throwable, "'throwable' cannot be null.");
if (!logger.isErrorEnabled()) {
- return runtimeException;
+ return throwable;
}
- performLogging(LogLevel.VERBOSE, true, runtimeException.getMessage(), runtimeException);
-
- return runtimeException;
+ performLogging(LogLevel.ERROR, true, throwable.getMessage(), throwable);
+ return throwable;
}
/*
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/LogLevel.java b/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/LogLevel.java
index 83b603d17b1e8..7f3d5e1716572 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/LogLevel.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/util/logging/LogLevel.java
@@ -7,7 +7,7 @@
import java.util.Locale;
/**
- * Enum which represent logging levels used in Azure SDKs.
+ * Enum which represent logging levels used in Azure SDKs.
*/
public enum LogLevel {
/**
@@ -33,7 +33,7 @@ public enum LogLevel {
/**
* Indicates that no log level is set.
*/
- NOT_SET(5);
+ NOT_SET(5, "5");
private final int numericValue;
private final String[] allowedLogLevelVariables;
@@ -65,7 +65,7 @@ public int getLogLevel() {
* Converts the passed log level string to the corresponding {@link LogLevel}.
*
* @param logLevelVal The log level value which needs to convert
- * @return The LogLevel Enum if pass in the valid string.
+ * @return The LogLevel Enum if pass in the valid string.
* The valid strings for {@link LogLevel} are:
*
* - VERBOSE: "verbose", "debug"
diff --git a/sdk/core/azure-core/src/test/java/com/azure/core/http/policy/HttpLoggingPolicyTests.java b/sdk/core/azure-core/src/test/java/com/azure/core/http/policy/HttpLoggingPolicyTests.java
index 80143d0cc40fc..7741ab3b33524 100644
--- a/sdk/core/azure-core/src/test/java/com/azure/core/http/policy/HttpLoggingPolicyTests.java
+++ b/sdk/core/azure-core/src/test/java/com/azure/core/http/policy/HttpLoggingPolicyTests.java
@@ -15,6 +15,7 @@
import com.azure.core.util.Context;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.FluxUtil;
+import com.azure.core.util.logging.LogLevel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -26,6 +27,7 @@
import reactor.test.StepVerifier;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
@@ -37,6 +39,7 @@
import java.util.Set;
import java.util.stream.Stream;
+import static com.azure.core.util.Configuration.PROPERTY_AZURE_LOG_LEVEL;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
/**
@@ -47,41 +50,37 @@ public class HttpLoggingPolicyTests {
private static final Context CONTEXT = new Context("caller-method", HttpLoggingPolicyTests.class.getName());
private String originalLogLevel;
- private PrintStream originalErr;
+ private PrintStream originalSystemOut;
private ByteArrayOutputStream logCaptureStream;
@BeforeEach
public void prepareForTest() {
// Set the log level to information for the test.
- originalLogLevel = System.getProperty(Configuration.PROPERTY_AZURE_LOG_LEVEL);
- System.setProperty(Configuration.PROPERTY_AZURE_LOG_LEVEL, "2");
+ originalLogLevel = Configuration.getGlobalConfiguration().get(PROPERTY_AZURE_LOG_LEVEL);
+ Configuration.getGlobalConfiguration().put(PROPERTY_AZURE_LOG_LEVEL,
+ String.valueOf(LogLevel.INFORMATIONAL.getLogLevel()));
/*
- * Indicate to SLF4J to enable trace level logging for a logger named
- * com.azure.core.util.logging.ClientLoggerTests. Trace is the maximum level of logging supported by the
- * ClientLogger.
+ * DefaultLogger uses System.out to log. Inject a custom PrintStream to log into for the duration of the test to
+ * capture the log messages.
*/
- System.setProperty("org.slf4j.simpleLogger.log.com.azure.core.util.logging.HttpLoggingPolicyTests", "trace");
-
- // Override System.err as that is where SLF4J will log by default.
- originalErr = System.out;
+ originalSystemOut = System.out;
logCaptureStream = new ByteArrayOutputStream();
System.setOut(new PrintStream(logCaptureStream));
}
@AfterEach
- public void cleanupAfterTest() {
+ public void cleanupAfterTest() throws IOException {
// Reset or clear the log level after the test completes.
if (CoreUtils.isNullOrEmpty(originalLogLevel)) {
- System.clearProperty(Configuration.PROPERTY_AZURE_LOG_LEVEL);
+ Configuration.getGlobalConfiguration().remove(PROPERTY_AZURE_LOG_LEVEL);
} else {
- System.setProperty(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ Configuration.getGlobalConfiguration().put(PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
}
- System.clearProperty("org.slf4j.simpleLogger.log.com.azure.core.util.logging.HttpLoggingPolicyTests");
-
// Reset System.err to the original PrintStream.
- System.setOut(originalErr);
+ System.setOut(originalSystemOut);
+ logCaptureStream.close();
}
/**
diff --git a/sdk/core/azure-core/src/test/java/com/azure/core/util/logging/ClientLoggerTests.java b/sdk/core/azure-core/src/test/java/com/azure/core/util/logging/ClientLoggerTests.java
index 41a0d25dea08c..2d7bc1519cdee 100644
--- a/sdk/core/azure-core/src/test/java/com/azure/core/util/logging/ClientLoggerTests.java
+++ b/sdk/core/azure-core/src/test/java/com/azure/core/util/logging/ClientLoggerTests.java
@@ -7,17 +7,19 @@
import com.azure.core.util.CoreUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
+import java.util.stream.Stream;
+import static com.azure.core.util.Configuration.PROPERTY_AZURE_LOG_LEVEL;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -25,25 +27,14 @@
* Tests for {@link ClientLogger}.
*/
public class ClientLoggerTests {
- private static final String PARAMETERIZED_TEST_NAME_TEMPLATE = "[" + ParameterizedTest.INDEX_PLACEHOLDER
- + "] " + ParameterizedTest.DISPLAY_NAME_PLACEHOLDER;
-
private PrintStream originalSystemOut;
private ByteArrayOutputStream logCaptureStream;
-
@BeforeEach
public void setupLoggingConfiguration() {
/*
- * Indicate to SLF4J to enable trace level logging for a logger named
- * com.azure.core.util.logging.ClientLoggerTests. Trace is the maximum level of logging supported by the
- * ClientLogger.
- */
- System.setProperty("org.slf4j.simpleLogger.log.com.azure.core.util.logging.ClientLoggerTests", "trace");
-
- /*
- * The default configuration for SLF4J's SimpleLogger uses System.err to log. Inject a custom PrintStream to
- * log into for the duration of the test to capture the log messages.
+ * DefaultLogger uses System.out to log. Inject a custom PrintStream to log into for the duration of the test to
+ * capture the log messages.
*/
originalSystemOut = System.out;
logCaptureStream = new ByteArrayOutputStream();
@@ -52,259 +43,204 @@ public void setupLoggingConfiguration() {
@AfterEach
public void revertLoggingConfiguration() throws Exception {
- System.clearProperty("org.slf4j.simpleLogger.log.com.azure.core.util.logging.ClientLoggerTests");
System.setOut(originalSystemOut);
logCaptureStream.close();
}
- private void setPropertyToOriginalOrClear(String propertyName, String originalValue) {
- if (CoreUtils.isNullOrEmpty(originalValue)) {
- System.clearProperty(propertyName);
- } else {
- System.setProperty(propertyName, originalValue);
- }
- }
-
/**
- * Tests that logging at the same level as the environment logging level will log.
- *
- * @param logLevel Logging level to log a message
+ * Test whether the logger supports a given log level based on its configured log level.
*/
- @ParameterizedTest(name = PARAMETERIZED_TEST_NAME_TEMPLATE)
- @ValueSource(ints = { 1, 2, 3, 4 })
- public void logAtSupportedLevel(int logLevel) {
- String logMessage = "This is a test";
-
- String originalLogLevel = setupLogLevel(logLevel);
- logMessage(new ClientLogger(ClientLoggerTests.class), logLevel, logMessage);
-
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
-
- String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(logMessage));
+ @ParameterizedTest
+ @MethodSource("singleLevelCheckSupplier")
+ public void canLogAtLevel(LogLevel logLevelToConfigure, LogLevel logLevelToValidate, boolean expected) {
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ assertEquals(expected, new ClientLogger(ClientLoggerTests.class).canLogAtLevel(logLevelToValidate));
+ setPropertyToOriginalOrClear(originalLogLevel);
}
/**
- * Tests that logging at a level that is less than the environment logging level doesn't log anything.
- *
- * @param logLevel Logging level to log a message
+ * Test whether a log will be captured when the ClientLogger and message are configured to the passed log levels.
*/
- @ParameterizedTest(name = PARAMETERIZED_TEST_NAME_TEMPLATE)
- @ValueSource(ints = { 1, 2, 3 })
- public void logAtUnsupportedLevel(int logLevel) {
+ @ParameterizedTest
+ @MethodSource("singleLevelCheckSupplier")
+ public void log(LogLevel logLevelToConfigure, LogLevel logLevelToUse, boolean logContainsMessage) {
String logMessage = "This is a test";
- String originalLogLevel = setupLogLevel(logLevel + 1);
- logMessage(new ClientLogger(ClientLoggerTests.class), logLevel, logMessage);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
-
- String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertFalse(logValues.contains(logMessage));
- }
-
- /**
- * Tests that logging when the environment log level is disabled nothing is logged.
- */
- @Test
- public void logWhenLoggingNotSet() {
- assertEquals(LogLevel.NOT_SET, LogLevel.fromString(null));
- }
-
- /**
- * Tests that logging an exception when the log level isn't VERBOSE only log the exception message.
- */
- @Test
- public void onlyLogExceptionMessage() {
- String logMessage = "This is an exception";
- String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
-
- String originalLogLevel = setupLogLevel(2);
- logMessage(new ClientLogger(ClientLoggerTests.class), 3, logMessage, runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
-
- String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(logMessage + System.lineSeparator() + runtimeException.getMessage()));
- assertFalse(logValues.contains(runtimeException.getStackTrace()[0].toString()));
- }
-
- /**
- * Tests that logging an exception when the log level is VERBOSE the stack trace is logged.
- */
- @Test
- public void logExceptionStackTrace() {
- String logMessage = "This is an exception fdsafdafdomcklamfd fdsafdafmlkdfmalsf fdsafdcacdalmd";
- String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ logMessage(new ClientLogger(ClientLoggerTests.class), logLevelToUse, logMessage);
- String originalLogLevel = setupLogLevel(1);
- logMessage(new ClientLogger(ClientLoggerTests.class), 3, logMessage, runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ setPropertyToOriginalOrClear(originalLogLevel);
String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(logMessage + System.lineSeparator() + runtimeException.getMessage()));
- assertTrue(logValues.contains(runtimeException.getStackTrace()[0].toString()));
+ assertEquals(logContainsMessage, logValues.contains(logMessage));
}
/**
- * Tests that logging an exception when the log level is ERROR the stack trace is logged.
+ * Tests whether a log will contain the exception message when the ClientLogger and message are configured to the
+ * passed log levels.
*/
- @Test
- public void logExceptionStackTraceWithErrorLevel() {
+ @ParameterizedTest
+ @MethodSource("multiLevelCheckSupplier")
+ public void logException(LogLevel logLevelToConfigure, LogLevel logLevelToUse, boolean logContainsMessage,
+ boolean logContainsStackTrace) {
String logMessage = "This is an exception";
String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
+ RuntimeException runtimeException = createIllegalStateException(exceptionMessage);
- String originalLogLevel = setupLogLevel(1);
- logMessage(new ClientLogger(ClientLoggerTests.class), 4, logMessage, runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ logMessage(new ClientLogger(ClientLoggerTests.class), logLevelToUse, logMessage, runtimeException);
+ setPropertyToOriginalOrClear(originalLogLevel);
String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(logMessage + System.lineSeparator() + runtimeException.getMessage()));
- assertTrue(logValues.contains(runtimeException.getStackTrace()[0].toString()));
+ assertEquals(logContainsMessage, logValues.contains(logMessage + System.lineSeparator() + runtimeException.getMessage()));
+ assertEquals(logContainsStackTrace, logValues.contains(runtimeException.getStackTrace()[0].toString()));
}
-
/**
- * Tests that logging an exception when the log level is ERROR the stack trace is logged.
+ * Tests that logging a RuntimeException as warning will log a message and stack trace appropriately based on the
+ * configured log level.
*/
- @Test
- public void logExceptionStackTraceWithNoLogLevel() {
- String logMessage = "This is an exception";
+ @ParameterizedTest
+ @MethodSource("logExceptionAsWarningSupplier")
+ public void logExceptionAsWarning(LogLevel logLevelToConfigure, boolean logContainsMessage,
+ boolean logContainsStackTrace) {
String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
+ IllegalStateException illegalStateException = createIllegalStateException(exceptionMessage);
- String originalLogLevel = setupLogLevel(1);
- logMessage(new ClientLogger(ClientLoggerTests.class), 5, logMessage, runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ try {
+ throw new ClientLogger(ClientLoggerTests.class).logExceptionAsWarning(illegalStateException);
+ } catch (RuntimeException exception) {
+ assertTrue(exception instanceof IllegalStateException);
+ }
+ setPropertyToOriginalOrClear(originalLogLevel);
String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.isEmpty());
+ assertEquals(logContainsMessage, logValues.contains(exceptionMessage + System.lineSeparator()));
+ assertEquals(logContainsStackTrace, logValues.contains(illegalStateException.getStackTrace()[0].toString()));
}
/**
- * Tests that logging an exception when the log level is ERROR the stack trace is logged.
+ * Tests that logging a Throwable as warning will log a message and stack trace appropriately based on the
+ * configured log level.
*/
- @Test
- public void logExceptionWithInvalidLogLevel() {
- String logMessage = "This is an exception";
- Object runtimeException = new Object();
+ @ParameterizedTest
+ @MethodSource("logExceptionAsWarningSupplier")
+ public void logCheckedExceptionAsWarning(LogLevel logLevelToConfigure, boolean logContainsMessage,
+ boolean logContainsStackTrace) {
+ String exceptionMessage = "An exception message";
+ IOException ioException = createIOException(exceptionMessage);
- String originalLogLevel = setupLogLevel(1);
- logMessage(new ClientLogger(ClientLoggerTests.class), 3, logMessage, runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ try {
+ throw new ClientLogger(ClientLoggerTests.class).logThowableAsWarning(ioException);
+ } catch (Throwable throwable) {
+ assertTrue(throwable instanceof IOException);
+ }
+ setPropertyToOriginalOrClear(originalLogLevel);
String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(logMessage));
+ assertEquals(logContainsMessage, logValues.contains(exceptionMessage + System.lineSeparator()));
+ assertEquals(logContainsStackTrace, logValues.contains(ioException.getStackTrace()[0].toString()));
}
/**
- * Tests that logging an exception as warning won't include the stack trace when the environment log level isn't
- * VERBOSE. Additionally, this tests that the exception message isn't logged twice as logging an exception uses
- * the exception message as the format string.
+ * Tests that logging a RuntimeException as error will log a message and stack trace appropriately based on the
+ * configured log level.
*/
- @Test
- public void logExceptionAsWarningOnlyExceptionMessage() {
+ @ParameterizedTest
+ @MethodSource("logExceptionAsErrorSupplier")
+ public void logExceptionAsError(LogLevel logLevelToConfigure, boolean logContainsMessage,
+ boolean logContainsStackTrace) {
String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
+ IllegalStateException illegalStateException = createIllegalStateException(exceptionMessage);
- String originalLogLevel = setupLogLevel(2);
- new ClientLogger(ClientLoggerTests.class).logExceptionAsWarning(runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ try {
+ throw new ClientLogger(ClientLoggerTests.class).logExceptionAsError(illegalStateException);
+ } catch (RuntimeException exception) {
+ assertTrue(exception instanceof IllegalStateException);
+ }
+ setPropertyToOriginalOrClear(originalLogLevel);
String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(exceptionMessage + System.lineSeparator()));
- assertFalse(logValues.contains(runtimeException.getStackTrace()[0].toString()));
+ assertEquals(logContainsMessage, logValues.contains(exceptionMessage + System.lineSeparator()));
+ assertEquals(logContainsStackTrace, logValues.contains(illegalStateException.getStackTrace()[0].toString()));
}
/**
- * Tests that logging an exception as warning will include the stack trace when the environment log level is set to
- * VERBOSE.
+ * Tests that logging a Throwable as error will log a message and stack trace appropriately based on the configured
+ * log level.
*/
- @Test
- public void logExceptionAsWarningStackTrace() {
+ @ParameterizedTest
+ @MethodSource("logExceptionAsErrorSupplier")
+ public void logCheckedExceptionAsError(LogLevel logLevelToConfigure, boolean logContainsMessage,
+ boolean logContainsStackTrace) {
String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
+ IOException ioException = createIOException(exceptionMessage);
- String originalLogLevel = setupLogLevel(1);
- new ClientLogger(ClientLoggerTests.class).logExceptionAsWarning(runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
+ String originalLogLevel = setupLogLevel(logLevelToConfigure.getLogLevel());
+ try {
+ throw new ClientLogger(ClientLoggerTests.class).logThrowableAsError(ioException);
+ } catch (Throwable throwable) {
+ assertTrue(throwable instanceof IOException);
+ }
+ setPropertyToOriginalOrClear(originalLogLevel);
String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(exceptionMessage + System.lineSeparator()));
- assertTrue(logValues.contains(runtimeException.getStackTrace()[0].toString()));
+ assertEquals(logContainsMessage, logValues.contains(exceptionMessage + System.lineSeparator()));
+ assertEquals(logContainsStackTrace, logValues.contains(ioException.getStackTrace()[0].toString()));
}
/**
- * Tests that logging an exception as error won't include the stack trace when the environment log level isn't
- * VERBOSE. Additionally, this tests that the exception message isn't logged twice as logging an exception uses
- * the exception message as the format string.
+ * Tests that LogLevel.fromString returns the expected LogLevel enum based on the passed environment configuration.
*/
- @Test
- public void logExceptionAsErrorOnlyExceptionMessage() {
- String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
-
- String originalLogLevel = setupLogLevel(2);
- new ClientLogger(ClientLoggerTests.class).logExceptionAsError(runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
-
- String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(exceptionMessage + System.lineSeparator()));
- assertFalse(logValues.contains(runtimeException.getStackTrace()[0].toString()));
+ @ParameterizedTest
+ @MethodSource("validLogLevelSupplier")
+ public void logLevelFromString(String environmentLogLevel, LogLevel expected) {
+ assertEquals(expected, LogLevel.fromString(environmentLogLevel));
}
/**
- * Tests that logging an exception as error will include the stack trace when the environment log level is set to
- * VERBOSE.
+ * Tests that LogLevel.fromString will throw an illegal argument exception when passed an environment configuration
+ * it doesn't support.
*/
- @Test
- public void logExceptionAsErrorStackTrace() {
- String exceptionMessage = "An exception message";
- RuntimeException runtimeException = createRuntimeException(exceptionMessage);
-
- String originalLogLevel = setupLogLevel(1);
- new ClientLogger(ClientLoggerTests.class).logExceptionAsError(runtimeException);
- setPropertyToOriginalOrClear(Configuration.PROPERTY_AZURE_LOG_LEVEL, originalLogLevel);
-
- String logValues = new String(logCaptureStream.toByteArray(), StandardCharsets.UTF_8);
- assertTrue(logValues.contains(exceptionMessage + System.lineSeparator()));
- assertTrue(logValues.contains(runtimeException.getStackTrace()[0].toString()));
+ @ParameterizedTest
+ @ValueSource(strings = {"errs", "not_set", "12", "onlyerrorsplease"})
+ public void invalidLogLevelFromString(String environmentLogLevel) {
+ assertThrows(IllegalArgumentException.class, () -> LogLevel.fromString(environmentLogLevel));
}
- @ParameterizedTest(name = "{index} from logLevelToConfigure = {0}, logLevelToValidate = {1}, expected = {2}")
- @CsvSource({"1, 1, true", "1, 2, true", "1, 3, true", "1, 4, true", "2, 1, false", "1, VERBOSE, true", "1, info, true", "1, warning, true", "1, error, true", "2, verbose, false"})
- public void canLogAtLevel(int logLevelToConfigure, String logLevelToValidate, boolean expected) {
- setupLogLevel(logLevelToConfigure);
- LogLevel logLevel = LogLevel.fromString(logLevelToValidate);
- assertEquals(new ClientLogger(ClientLoggerTests.class).canLogAtLevel(logLevel), expected);
+ private String setupLogLevel(int logLevelToSet) {
+ String originalLogLevel = Configuration.getGlobalConfiguration().get(PROPERTY_AZURE_LOG_LEVEL);
+ Configuration.getGlobalConfiguration().put(PROPERTY_AZURE_LOG_LEVEL, String.valueOf(logLevelToSet));
+ return originalLogLevel;
}
- @ParameterizedTest(name = PARAMETERIZED_TEST_NAME_TEMPLATE)
- @ValueSource(strings = {"5", "invalid"})
- public void canLogAtLevelInvalid(String logLevelToValidate) {
- assertThrows(IllegalArgumentException.class, () -> LogLevel.fromString(logLevelToValidate));
+ private void setPropertyToOriginalOrClear(String originalValue) {
+ if (CoreUtils.isNullOrEmpty(originalValue)) {
+ Configuration.getGlobalConfiguration().remove(PROPERTY_AZURE_LOG_LEVEL);
+ } else {
+ Configuration.getGlobalConfiguration().put(PROPERTY_AZURE_LOG_LEVEL, originalValue);
+ }
}
- private String setupLogLevel(int logLevelToSet) {
- String originalLogLevel = Configuration.getGlobalConfiguration().get(Configuration.PROPERTY_AZURE_LOG_LEVEL);
- Configuration.getGlobalConfiguration()
- .put(Configuration.PROPERTY_AZURE_LOG_LEVEL, String.valueOf(logLevelToSet));
- return originalLogLevel;
- }
+ private void logMessage(ClientLogger logger, LogLevel logLevel, String logFormat, Object... arguments) {
+ if (logLevel == null) {
+ return;
+ }
- private void logMessage(ClientLogger logger, int logLevelToLog, String logFormat, Object... arguments) {
- switch (logLevelToLog) {
- case 1:
+ switch (logLevel) {
+ case VERBOSE:
logger.verbose(logFormat, arguments);
break;
- case 2:
+ case INFORMATIONAL:
logger.info(logFormat, arguments);
break;
- case 3:
+ case WARNING:
logger.warning(logFormat, arguments);
break;
- case 4:
+ case ERROR:
logger.error(logFormat, arguments);
break;
default:
@@ -312,12 +248,232 @@ private void logMessage(ClientLogger logger, int logLevelToLog, String logFormat
}
}
- private RuntimeException createRuntimeException(String message) {
- RuntimeException runtimeException = new RuntimeException(message);
- StackTraceElement[] stackTraceElements = { new StackTraceElement("ClientLoggerTests", "onlyLogExceptionMessage",
- "ClientLoggerTests", 117) };
- runtimeException.setStackTrace(stackTraceElements);
+ private static IllegalStateException createIllegalStateException(String message) {
+ return fillInStackTrace(new IllegalStateException(message));
+ }
+
+ private static IOException createIOException(String message) {
+ return fillInStackTrace(new IOException(message));
+ }
+
+ private static T fillInStackTrace(T throwable) {
+ StackTraceElement[] stackTraceElements = {new StackTraceElement("ClientLoggerTests", "onlyLogExceptionMessage",
+ "ClientLoggerTests", 117)};
+ throwable.setStackTrace(stackTraceElements);
+
+ return throwable;
+ }
+
+ private static Stream singleLevelCheckSupplier() {
+ return Stream.of(
+ // Supported logging level set to VERBOSE.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.VERBOSE, true),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.INFORMATIONAL, true),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.WARNING, true),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.ERROR, true),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.NOT_SET, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.VERBOSE, null, false),
+
+ // Supported logging level set to INFORMATIONAL.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.VERBOSE, false),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.INFORMATIONAL, true),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.WARNING, true),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.ERROR, true),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.NOT_SET, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.INFORMATIONAL, null, false),
+
+ // Supported logging level set to WARNING.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.WARNING, LogLevel.VERBOSE, false),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.WARNING, LogLevel.INFORMATIONAL, false),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.WARNING, LogLevel.WARNING, true),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.WARNING, LogLevel.ERROR, true),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.WARNING, LogLevel.NOT_SET, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.WARNING, null, false),
+
+ // Supported logging level set to ERROR.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.ERROR, LogLevel.VERBOSE, false),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.ERROR, LogLevel.INFORMATIONAL, false),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.ERROR, LogLevel.WARNING, false),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.ERROR, LogLevel.ERROR, true),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.NOT_SET, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.VERBOSE, null, false)
+ );
+ }
+
+ private static Stream multiLevelCheckSupplier() {
+ return Stream.of(
+ // Supported logging level set to VERBOSE.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.VERBOSE, false, true),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.INFORMATIONAL, false, true),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.WARNING, true, true),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.ERROR, true, true),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.NOT_SET, false, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.VERBOSE, null, false, false),
+
+ // Supported logging level set to INFORMATIONAL.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.VERBOSE, false, false),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.INFORMATIONAL, false, false),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.WARNING, true, false),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.ERROR, true, false),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.INFORMATIONAL, LogLevel.NOT_SET, false, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.INFORMATIONAL, null, false, false),
+
+ // Supported logging level set to WARNING.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.WARNING, LogLevel.VERBOSE, false, false),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.WARNING, LogLevel.INFORMATIONAL, false, false),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.WARNING, LogLevel.WARNING, true, false),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.WARNING, LogLevel.ERROR, true, false),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.WARNING, LogLevel.NOT_SET, false, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.WARNING, null, false, false),
+
+ // Supported logging level set to ERROR.
+ // Checking VERBOSE.
+ Arguments.of(LogLevel.ERROR, LogLevel.VERBOSE, false, false),
+
+ // Checking INFORMATIONAL.
+ Arguments.of(LogLevel.ERROR, LogLevel.INFORMATIONAL, false, false),
+
+ // Checking WARNING.
+ Arguments.of(LogLevel.ERROR, LogLevel.WARNING, false, false),
+
+ // Checking ERROR.
+ Arguments.of(LogLevel.ERROR, LogLevel.ERROR, true, false),
+
+ // Checking NOT_SET.
+ Arguments.of(LogLevel.VERBOSE, LogLevel.NOT_SET, false, false),
+
+ // Checking null.
+ Arguments.of(LogLevel.VERBOSE, null, false, false)
+ );
+ }
+
+ private static Stream logExceptionAsWarningSupplier() {
+ return Stream.of(
+ Arguments.of(LogLevel.VERBOSE, true, true),
+ Arguments.of(LogLevel.INFORMATIONAL, true, false),
+ Arguments.of(LogLevel.WARNING, true, false),
+ Arguments.of(LogLevel.ERROR, false, false),
+ Arguments.of(LogLevel.NOT_SET, false, false)
+ );
+ }
+
+ private static Stream logExceptionAsErrorSupplier() {
+ return Stream.of(
+ Arguments.of(LogLevel.VERBOSE, true, true),
+ Arguments.of(LogLevel.INFORMATIONAL, true, false),
+ Arguments.of(LogLevel.WARNING, true, false),
+ Arguments.of(LogLevel.ERROR, true, false),
+ Arguments.of(LogLevel.NOT_SET, false, false)
+ );
+ }
- return runtimeException;
+ private static Stream validLogLevelSupplier() {
+ return Stream.of(
+ // Valid VERBOSE environment variables.
+ Arguments.of("1", LogLevel.VERBOSE),
+ Arguments.of("verbose", LogLevel.VERBOSE),
+ Arguments.of("debug", LogLevel.VERBOSE),
+ Arguments.of("deBUG", LogLevel.VERBOSE),
+
+ // Valid INFORMATIONAL environment variables.
+ Arguments.of("2", LogLevel.INFORMATIONAL),
+ Arguments.of("info", LogLevel.INFORMATIONAL),
+ Arguments.of("information", LogLevel.INFORMATIONAL),
+ Arguments.of("informational", LogLevel.INFORMATIONAL),
+ Arguments.of("InForMATiONaL", LogLevel.INFORMATIONAL),
+
+ // Valid WARNING environment variables.
+ Arguments.of("3", LogLevel.WARNING),
+ Arguments.of("warn", LogLevel.WARNING),
+ Arguments.of("warning", LogLevel.WARNING),
+ Arguments.of("WARniNg", LogLevel.WARNING),
+
+ // Valid ERROR environment variables.
+ Arguments.of("4", LogLevel.ERROR),
+ Arguments.of("err", LogLevel.ERROR),
+ Arguments.of("error", LogLevel.ERROR),
+ Arguments.of("ErRoR", LogLevel.ERROR),
+
+ // Valid NOT_SET environment variables.
+ Arguments.of("5", LogLevel.NOT_SET),
+ Arguments.of(null, LogLevel.NOT_SET)
+ );
}
}