diff --git a/pom.xml b/pom.xml index c0cc6ea3..c7ed39c9 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,6 @@ 1.8 2.7.7 1.3.2 - 3.6.2 1.0.0 1.3.0 1.01 @@ -211,7 +210,7 @@ org.assertj assertj-core - ${assertj.version} + ${assertj} test diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/RegionDataAccessTracingAspect.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/RegionDataAccessTracingAspect.java index 466e7b67..a71d9139 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/RegionDataAccessTracingAspect.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/RegionDataAccessTracingAspect.java @@ -18,12 +18,15 @@ package org.springframework.data.gemfire.config.annotation.support; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Optional; +import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; /** * The RegionDataAccessTracingAspect class... @@ -58,26 +61,48 @@ public class RegionDataAccessTracingAspect { } /* (non-Javadoc) */ - @Pointcut("target(com.gemstone.gemfire.cache.Region)") + @Pointcut("target(org.apache.geode.cache.Region)") private void regionPointcut() {} /* (non-Javadoc) */ - @Pointcut("execution(* com.gemstone.gemfire.cache.Region.create(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.get(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.getAll(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.put(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.putAll(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.putIfAbsent(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.remove(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.replace(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.selectValue(..))" - + " || execution(* com.gemstone.gemfire.cache.Region.values(..))" + @Pointcut("execution(* org.apache.geode.cache.Region.create(..))" + + " || execution(* org.apache.geode.cache.Region.get(..))" + + " || execution(* org.apache.geode.cache.Region.getAll(..))" + + " || execution(* org.apache.geode.cache.Region.getEntry(..))" + + " || execution(* org.apache.geode.cache.Region.invalidate(..))" + + " || execution(* org.apache.geode.cache.Region.keySet())" + + " || execution(* org.apache.geode.cache.Region.keySetOnServer())" + + " || execution(* org.apache.geode.cache.Region.localClear())" + + " || execution(* org.apache.geode.cache.Region.localDestroy(..))" + + " || execution(* org.apache.geode.cache.Region.localInvalidate(..))" + + " || execution(* org.apache.geode.cache.Region.put(..))" + + " || execution(* org.apache.geode.cache.Region.putAll(..))" + + " || execution(* org.apache.geode.cache.Region.putIfAbsent(..))" + + " || execution(* org.apache.geode.cache.Region.query(..))" + + " || execution(* org.apache.geode.cache.Region.remove(..))" + + " || execution(* org.apache.geode.cache.Region.removeAll(..))" + + " || execution(* org.apache.geode.cache.Region.replace(..))" + + " || execution(* org.apache.geode.cache.Region.selectValue(..))" + + " || execution(* org.apache.geode.cache.Region.size())" + + " || execution(* org.apache.geode.cache.Region.sizeOnServer())" + + " || execution(* org.apache.geode.cache.Region.values(..))" + "") private void regionDataAccessPointcut() {} /* (non-Javadoc) */ @Before("regionPointcut() && regionDataAccessPointcut()") - public void regionDataAccessTracingAdvice() { - getLogger().trace("Region data access call [{}]", getCurrentThreadStackTrace()); + public void regionDataAccessTracingAdvice(JoinPoint joinPoint) { + getLogger().trace("Region data access call [{}(..)] with stack trace [{}]", + toRegionMethodSignature(joinPoint), getCurrentThreadStackTrace()); + } + + /* (non-Javadoc) */ + private String toRegionMethodSignature(JoinPoint joinPoint) { + + return Optional.ofNullable(joinPoint) + .map(JoinPoint::getSignature) + .map(signature -> + String.format("%1$s.%2$s", ObjectUtils.nullSafeClassName(joinPoint.getTarget()), signature.getName())) + .orElse(""); } } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/RegionDataAccessTracingAspectUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/RegionDataAccessTracingAspectUnitTests.java new file mode 100644 index 00000000..62439379 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/RegionDataAccessTracingAspectUnitTests.java @@ -0,0 +1,516 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed 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.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.annotation.Resource; + +import org.apache.geode.cache.GemFireCache; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientRegionShortcut; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.annotation.Bean; +import org.springframework.data.gemfire.client.ClientRegionFactoryBean; +import org.springframework.data.gemfire.config.annotation.support.RegionDataAccessTracingAspect; +import org.springframework.data.gemfire.test.logging.slf4j.logback.TestAppender; +import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.ClassUtils; + +/** + * Unit tests for {@link RegionDataAccessTracingAspect}. + * + * @author John Blum + * @see org.junit.Test + * @see org.apache.geode.cache.GemFireCache + * @see org.apache.geode.cache.Region + * @see org.springframework.data.gemfire.client.ClientRegionFactoryBean + * @see org.springframework.data.gemfire.config.annotation.support.RegionDataAccessTracingAspect + * @see org.springframework.data.gemfire.test.logging.slf4j.logback.TestAppender + * @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @since 2.0.2 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +public class RegionDataAccessTracingAspectUnitTests { + + private static final String LOGBACK_LOGGER_CLASS_NAME = "ch.qos.logback.classic.Logger"; + + @BeforeClass + public static void setupBeforeTestSuite() { + assumeLogbackIsPresent(); + } + + private static void assumeLogbackIsPresent() { + Assume.assumeTrue(String.format("Ignoring test class [%s]; Logback is not on the classpath", + RegionDataAccessTracingAspectUnitTests.class.getName()), ClassUtils.isPresent(LOGBACK_LOGGER_CLASS_NAME, + Thread.currentThread().getContextClassLoader())); + } + + @Resource(name = "ClientRegion") + @SuppressWarnings("all") + private Region region; + + private Runnable regionCallbackArgument(AtomicBoolean called) { + return () -> called.set(true); + } + + @Test + public void logsRegionCreate() { + + this.region.create("testKey", "testValue"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.create\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionCreate", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionCreateWithCallbackArgument() { + + this.region.create("testKey", "testValue", + regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.create\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionCreateWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionGet() { + + this.region.get("testKey"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.get\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionGet", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionGetAll() { + + this.region.getAll(Arrays.asList("testKeyOne", "testKeyTwo", "testKeyThree")); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.getAll\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionGetAll", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionGetAllWithCallbackArgument() { + + this.region.getAll(Arrays.asList("testKeyOne", "testKeyTwo", "testKeyThree"), + regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.getAll\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionGetAllWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionGetEntry() { + + this.region.getEntry("testKey"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.getEntry\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionGetEntry", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionInvalidate() { + + this.region.invalidate("testKey"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.invalidate\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionInvalidate", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionInvalidateWithCallbackArgument() { + + this.region.invalidate("testKey", regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.invalidate\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionInvalidateWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionKeySet() { + + this.region.keySet(); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.keySet\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionKeySet", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionKeySetOnServer() { + + this.region.keySetOnServer(); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.keySetOnServer\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionKeySetOnServer", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionLocalClear() { + + this.region.localClear(); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.localClear\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionLocalClear", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionLocalDestroy() { + + this.region.localDestroy("testKey"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.localDestroy\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionLocalDestroy", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionLocalDestroyWithCallbackArgument() { + + this.region.localDestroy("testKey", regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.localDestroy\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionLocalDestroyWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionLocalInvalidate() { + + this.region.localInvalidate("testKey"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.localInvalidate\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionLocalInvalidate", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionLocalInvalidateWithCallbackArgument() { + + this.region.localInvalidate("testKey", regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.localInvalidate\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionLocalInvalidateWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionPut() { + + this.region.put("testKey", "testValue"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.put\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionPut", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionPutWithCallbackArgument() { + + this.region.put("testKey", "testValue", regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.put\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionPutWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionPutAll() { + + this.region.putAll(Collections.emptyMap()); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.putAll\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionPutAll", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionPutAllWithCallbackArgument() { + + this.region.putAll(Collections.emptyMap(), regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.putAll\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionPutAllWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionPutIfAbsent() { + + this.region.putIfAbsent("testKey", "testValue"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.putIfAbsent\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionPutIfAbsent", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionQuery() throws Exception { + + this.region.query("SELECT * FROM /Region WHERE id = ?"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.query\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionQuery", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionRemoveWithKey() { + + this.region.remove("testKey"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.remove\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionRemoveWithKey", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionRemoveWithKeyAndValue() { + + this.region.remove("testKey", "testValue"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.remove\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionRemoveWithKeyAndValue", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionRemoveAll() { + + this.region.removeAll(Arrays.asList("testKeyOne", "testKeyTwo", "testKeyThree")); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.removeAll\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionRemoveAll", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionRemoveAllWithCallbackArgument() { + + this.region.removeAll(Arrays.asList("testKeyOne", "testKeyTwo", "testKeyThree"), + regionCallbackArgument(new AtomicBoolean(false))); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.removeAll\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionRemoveAllWithCallbackArgument", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionReplace() { + + this.region.replace("testKey", "testValue"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.replace\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionReplace", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionReplaceWithKeyOldValueNewValue() { + + this.region.replace("testKey", "testOldValue", "testNewValue"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.replace\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionReplaceWithKeyOldValueNewValue", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionSelectValue() throws Exception { + + this.region.selectValue("id = ?"); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.selectValue\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionSelectValue", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionSize() throws Exception { + + this.region.size(); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.size\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionSize", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionSizeOnServer() throws Exception { + + this.region.sizeOnServer(); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.sizeOnServer\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionSizeOnServer", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void logsRegionValues() throws Exception { + + this.region.values(); + + String logMessage = TestAppender.getInstance().lastLogMessage(); + + assertThat(logMessage) + .containsPattern("Region data access call \\[org.apache.geode.cache.Region.*.values\\(..\\)\\] with stack trace"); + assertThat(logMessage).contains(String.format("%s.logsRegionValues", + RegionDataAccessTracingAspectUnitTests.class.getName())); + } + + @Test + public void doesNotLogRegionGetName() { + + this.region.getName(); + + assertThat(TestAppender.getInstance().lastLogMessage()).isNull(); + } + + @ClientCacheApplication + @EnableGemFireMockObjects + @EnableRegionDataAccessTracing + static class TestConfiguration { + + @Bean("ClientRegion") + @SuppressWarnings("unused") + public ClientRegionFactoryBean clientRegion(GemFireCache gemfireCache) { + + ClientRegionFactoryBean clientRegion = new ClientRegionFactoryBean<>(); + + clientRegion.setCache(gemfireCache); + clientRegion.setClose(false); + clientRegion.setShortcut(ClientRegionShortcut.LOCAL); + + return clientRegion; + } + + } +} diff --git a/src/test/java/org/springframework/data/gemfire/test/logging/slf4j/logback/TestAppender.java b/src/test/java/org/springframework/data/gemfire/test/logging/slf4j/logback/TestAppender.java new file mode 100644 index 00000000..7a171d00 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/test/logging/slf4j/logback/TestAppender.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed 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.springframework.data.gemfire.test.logging.slf4j.logback; + +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; + +import java.util.Optional; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicReference; + +import org.springframework.util.StringUtils; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.AppenderBase; + +/** + * The {@link TestAppender} class is a SLF4J, Logback {@link Appender} implementation used for testing purposes. + * + * @author John Blum + * @see ch.qos.logback.core.Appender + * @see ch.qos.logback.core.AppenderBase + * @since 2.0.2 + */ +@SuppressWarnings("unused") +public class TestAppender extends AppenderBase implements Appender { + + private static final AtomicReference INSTANCE = new AtomicReference<>(null); + + private static final Stack logMessages = new Stack<>(); + + public static TestAppender getInstance() { + + return Optional.ofNullable(INSTANCE.get()) + .orElseThrow(() -> newIllegalStateException("[%s] was not properly configured", + TestAppender.class.getName())); + } + + public TestAppender() { + INSTANCE.compareAndSet(null, this); + } + + @Override + protected void append(ILoggingEvent event) { + + Optional.ofNullable(event) + .map(ILoggingEvent::getFormattedMessage) + .filter(StringUtils::hasText) + .ifPresent(logMessages::push); + } + + public String lastLogMessage() { + synchronized (logMessages) { + return (logMessages.empty() ? null : logMessages.pop()); + } + } + + public void clear() { + logMessages.clear(); + } +} diff --git a/src/test/java/org/springframework/data/gemfire/test/mock/MockGemFireObjectsSupport.java b/src/test/java/org/springframework/data/gemfire/test/mock/MockGemFireObjectsSupport.java index 8191eff6..752c6ba3 100644 --- a/src/test/java/org/springframework/data/gemfire/test/mock/MockGemFireObjectsSupport.java +++ b/src/test/java/org/springframework/data/gemfire/test/mock/MockGemFireObjectsSupport.java @@ -1326,7 +1326,8 @@ public abstract class MockGemFireObjectsSupport extends MockObjectsSupport { data.get(invocation.getArgument(0))); when(mockRegion.getEntry(ArgumentMatchers.any())).thenAnswer(invocation -> - data.entrySet().stream().filter(entry -> entry.getKey().equals(invocation.getArgument(0))).findFirst()); + data.entrySet().stream().filter(entry -> entry.getKey().equals(invocation.getArgument(0))) + .findFirst().orElse(null)); when(mockRegion.put(any(), any())).thenAnswer(invocation -> data.put(invocation.getArgument(0), invocation.getArgument(1))); diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml index 2db6ee44..05ced12f 100644 --- a/src/test/resources/logback.xml +++ b/src/test/resources/logback.xml @@ -1,14 +1,26 @@ + %d %5p %40.40c:%4L - %m%n + + + TEST - %m%n + + + + + + + +