/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * */ package org.opensearch.test.framework.log; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import org.junit.rules.ExternalResource; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasItem; /** * The class is a JUnit 4 rule and enables developers to write assertion related to log messages generated in the course of test. To use * {@link LogsRule} appender {@link LogCapturingAppender} must be properly configured. The rule also manages {@link LogCapturingAppender} * so that memory occupied by gathered log messages is released after each test. */ public class LogsRule extends ExternalResource { private final String[] loggerNames; /** * Constructor used to start gathering log messages from certain loggers * @param loggerNames Loggers names. Log messages are collected only if the log message is associated with the logger with a name which * is present in loggerNames parameter. */ public LogsRule(String... loggerNames) { this.loggerNames = Objects.requireNonNull(loggerNames, "Logger names are required"); } @Override protected void before() { LogCapturingAppender.enable(loggerNames); } @Override protected void after() { LogCapturingAppender.disable(); } /** * Check if during the tests certain log message was logged * @param expectedLogMessage expected log message */ public void assertThatContainExactly(String expectedLogMessage) { List messages = LogCapturingAppender.getLogMessagesAsString(); String reason = reasonMessage(expectedLogMessage, messages); assertThat(reason, messages, hasItem(expectedLogMessage)); } /** * Check if during the tests certain log message was logged * @param messageFragment expected log message fragment */ public void assertThatContain(String messageFragment) { List messages = LogCapturingAppender.getLogMessagesAsString(); ; String reason = reasonMessage(messageFragment, messages); assertThat(reason, messages, hasItem(containsString(messageFragment))); } /** * Check if during the tests a stack trace was logged which contain given fragment * @param stackTraceFragment stack trace fragment */ public void assertThatStackTraceContain(String stackTraceFragment) { long count = LogCapturingAppender.getLogMessages() .stream() .filter(logMessage -> logMessage.stackTraceContains(stackTraceFragment)) .count(); String reason = "Stack trace does not contain element " + stackTraceFragment; assertThat(reason, count, greaterThan(0L)); } private static String reasonMessage(String expectedLogMessage, List messages) { String concatenatedLogMessages = messages.stream().map(message -> String.format("'%s'", message)).collect(Collectors.joining(", ")); return String.format( "Expected message '%s' has not been found in logs. All captured log messages: %s", expectedLogMessage, concatenatedLogMessages ); } }