Add additional Unit Tests using Always Dirty, Never Dirty and a custom IsDirtyPredicate strategy interface.

Add additional Unit Tests for org.apache.geode.Delta implementing objects.

Resolves gh-17.
This commit is contained in:
John Blum
2018-12-17 20:52:47 -08:00
parent deb774f94f
commit ba678e8b41
6 changed files with 295 additions and 35 deletions

View File

@@ -85,7 +85,6 @@ import org.apache.commons.logging.LogFactory;
* @see org.apache.geode.DataSerializer
* @see org.apache.geode.Delta
* @see org.apache.geode.cache.EntryEvent
* @see org.apache.geode.cache.Operation
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.util.CacheListenerAdapter
* @see org.springframework.context.ApplicationEvent
@@ -97,6 +96,7 @@ import org.apache.commons.logging.LogFactory;
* @see org.springframework.session.SessionRepository
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
* @see org.springframework.session.data.gemfire.support.IsDirtyPredicate
* @see org.springframework.session.data.gemfire.support.SessionIdHolder
* @see org.springframework.session.events.AbstractSessionEvent
* @see org.springframework.session.events.SessionCreatedEvent
@@ -1066,7 +1066,7 @@ public abstract class AbstractGemFireOperationsSessionRepository
super(lock);
}
protected Set<String> getSessionAttributeDeltas() {
Set<String> getSessionAttributeDeltas() {
synchronized (getLock()) {
return this.sessionAttributeDeltas;
@@ -1198,6 +1198,16 @@ public abstract class AbstractGemFireOperationsSessionRepository
this.lock = lock != null ? lock : this;
}
/**
* Returns a reference to the internal, {@link Session} attributes data structure.
*
* @return a reference to the internal, {@link Session} attributes data structure.
* @see java.util.Map
*/
Map<String, Object> getMap() {
return this.sessionAttributes;
}
/**
* Returns the {@link Object} used as the {@literal lock} guarding the methods of this object
* from concurrent access by multiple {@link Thread Threads}.
@@ -1236,7 +1246,9 @@ public abstract class AbstractGemFireOperationsSessionRepository
private Object doSetAttribute(String attributeName, Object attributeValue) {
Object previousAttributeValue = this.sessionAttributes.put(attributeName, attributeValue);
Map<String, Object> sessionAttributes = getMap();
Object previousAttributeValue = sessionAttributes.put(attributeName, attributeValue);
this.delta |= getIsDirtyPredicate().isDirty(previousAttributeValue, attributeValue)
&& sessionAttributesChangeInterceptor().apply(attributeName, attributeValue);
@@ -1248,10 +1260,12 @@ public abstract class AbstractGemFireOperationsSessionRepository
synchronized (getLock()) {
this.delta |= this.sessionAttributes.containsKey(attributeName)
Map<String, Object> sessionAttributes = getMap();
this.delta |= sessionAttributes.containsKey(attributeName)
&& sessionAttributesChangeInterceptor().apply(attributeName, null);
return this.sessionAttributes.remove(attributeName);
return sessionAttributes.remove(attributeName);
}
}
@@ -1259,14 +1273,14 @@ public abstract class AbstractGemFireOperationsSessionRepository
public <T> T getAttribute(String attributeName) {
synchronized (getLock()) {
return (T) this.sessionAttributes.get(attributeName);
return (T) getMap().get(attributeName);
}
}
public Set<String> getAttributeNames() {
synchronized (getLock()) {
return Collections.unmodifiableSet(this.sessionAttributes.keySet());
return Collections.unmodifiableSet(getMap().keySet());
}
}
@@ -1280,13 +1294,13 @@ public abstract class AbstractGemFireOperationsSessionRepository
@Override
public Iterator<Entry<String, Object>> iterator() {
return Collections.unmodifiableMap(GemFireSessionAttributes.this.sessionAttributes)
return Collections.unmodifiableMap(GemFireSessionAttributes.this.getMap())
.entrySet().iterator();
}
@Override
public int size() {
return GemFireSessionAttributes.this.sessionAttributes.size();
return GemFireSessionAttributes.this.getMap().size();
}
};
}
@@ -1343,7 +1357,7 @@ public abstract class AbstractGemFireOperationsSessionRepository
public String toString() {
synchronized (getLock()) {
return this.sessionAttributes.toString();
return getMap().toString();
}
}
}

View File

@@ -54,6 +54,9 @@ public class DeltaAwareDirtyPredicate implements IsDirtyPredicate {
*/
@Override
public boolean isDirty(@Nullable Object oldValue, @Nullable Object newValue) {
return !(newValue instanceof Delta) || ((Delta) newValue).hasDelta();
return newValue != oldValue
|| !(newValue instanceof Delta)
|| ((Delta) newValue).hasDelta();
}
}

View File

@@ -30,8 +30,8 @@ import org.springframework.lang.Nullable;
@SuppressWarnings("unused")
public interface IsDirtyPredicate {
IsDirtyPredicate ALWAYS_DIRTY = (oldValue, newValue) -> false;
IsDirtyPredicate NEVER_DIRTY = (oldValue, newValue) -> true;
IsDirtyPredicate ALWAYS_DIRTY = (oldValue, newValue) -> true;
IsDirtyPredicate NEVER_DIRTY = (oldValue, newValue) -> false;
/**
* Determines whether the {@link Object newValue} is dirty relative to the {@link Object oldValue}.

View File

@@ -70,6 +70,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import edu.umd.cs.mtc.MultithreadedTestCase;
import edu.umd.cs.mtc.TestFramework;
import org.apache.geode.Delta;
import org.apache.geode.cache.AttributesMutator;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.InterestResultPolicy;
@@ -3199,6 +3200,217 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
assertThat(sessionAttributes.hasDelta()).isFalse();
}
@Test
public void deltaSessionAttributesHasDeltaWhenExistingDeltaObjectHasDeltaIsTrue() {
Delta mockDelta = mock(Delta.class);
when(mockDelta.hasDelta()).thenReturn(true);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.getMap().put("1", mockDelta);
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(DeltaAwareDirtyPredicate.INSTANCE);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", mockDelta);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isTrue();
assertThat(sessionAttributes.getSessionAttributeDeltas()).containsExactly("1");
verify(mockDelta, times(1)).hasDelta();
}
@Test
public void deltaSessionAttributesHasDeltaWhenExistingObjectIsReplacedByDeltaObject() {
Delta mockDelta = mock(Delta.class);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.getMap().put("1", new Tombstone());
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(DeltaAwareDirtyPredicate.INSTANCE);
assertThat(sessionAttributes.<Tombstone>getAttribute("1")).isInstanceOf(Tombstone.class);
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", mockDelta);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isTrue();
assertThat(sessionAttributes.getSessionAttributeDeltas()).containsExactly("1");
verify(mockDelta, never()).hasDelta();
}
@Test
public void deltaSessionAttributesHasDeltaEvenWhenNonExistingDeltaObjectHasDeltaIsFalse() {
Delta mockDelta = mock(Delta.class);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(DeltaAwareDirtyPredicate.INSTANCE);
assertThat(sessionAttributes.<Object>getAttribute("1")).isNull();
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", mockDelta);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isTrue();
assertThat(sessionAttributes.getSessionAttributeDeltas()).containsExactly("1");
verify(mockDelta, never()).hasDelta();
}
@Test
public void deltaSessionAttributesHasDeltaWhenExistingDeltaObjectIsRemoved() {
Delta mockDelta = mock(Delta.class);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.getMap().put("1", mockDelta);
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(DeltaAwareDirtyPredicate.INSTANCE);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.removeAttribute("1");
assertThat(sessionAttributes.<Delta>getAttribute("1")).isNull();
assertThat(sessionAttributes.hasDelta()).isTrue();
assertThat(sessionAttributes.getSessionAttributeDeltas()).containsExactly("1");
verify(mockDelta, never()).hasDelta();
}
@Test
public void deltaSessionAttributesHasNoDeltaWhenExistingDeltaObjectHasDeltaIsFalse() {
Delta mockDelta = mock(Delta.class);
when(mockDelta.hasDelta()).thenReturn(false);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.getMap().put("1", mockDelta);
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(DeltaAwareDirtyPredicate.INSTANCE);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", mockDelta);
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
verify(mockDelta, times(1)).hasDelta();
}
@Test
public void deltaSessionAttributesOnlyHasDeltaWhenIsDirtyPredicateReturnsTrue() {
Delta mockDelta = mock(Delta.class, withSettings().lenient());
when(mockDelta.hasDelta()).thenReturn(true);
IsDirtyPredicate mockDirtyPredicate = mock(IsDirtyPredicate.class);
when(mockDirtyPredicate.isDirty(any(), any())).thenReturn(false).thenReturn(true);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.setIsDirtyPredicate(mockDirtyPredicate);
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(mockDirtyPredicate);
assertThat(sessionAttributes.getAttributeNames()).isEmpty();
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", mockDelta);
assertThat(sessionAttributes.getAttributeNames()).containsExactly("1");
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("2", "TEST");
assertThat(sessionAttributes.getAttributeNames()).containsOnly("1", "2");
assertThat(sessionAttributes.<Delta>getAttribute("1")).isEqualTo(mockDelta);
assertThat(sessionAttributes.<String>getAttribute("2")).isEqualTo("TEST");
assertThat(sessionAttributes.hasDelta()).isTrue();
assertThat(sessionAttributes.getSessionAttributeDeltas()).containsExactly("2");
verify(mockDelta, never()).hasDelta();
verify(mockDirtyPredicate, times(1)).isDirty(eq(null), eq("TEST"));
verify(mockDirtyPredicate, times(1)).isDirty(eq(null), eq(mockDelta));
}
@Test
public void deltaSessionAttributesWillAlwaysHaveDeltaWhenIsDirtyPredicateAlwaysReturnsTrue() {
Delta mockDelta = mock(Delta.class, withSettings().lenient());
when(mockDelta.hasDelta()).thenReturn(false);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.setIsDirtyPredicate(IsDirtyPredicate.ALWAYS_DIRTY);
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(IsDirtyPredicate.ALWAYS_DIRTY);
assertThat(sessionAttributes.getAttributeNames()).isEmpty();
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", mockDelta);
sessionAttributes.setAttribute("1", mockDelta);
sessionAttributes.setAttribute("1", mockDelta);
assertThat(sessionAttributes.getAttributeNames()).containsExactly("1");
assertThat(sessionAttributes.hasDelta()).isTrue();
assertThat(sessionAttributes.getSessionAttributeDeltas()).containsExactly("1");
verify(mockDelta, never()).hasDelta();
}
@Test
public void deltaSessionAttributesWillNeverHaveDeltaWhenIsDirtyPredicateAlwaysReturnsFalse() {
Delta mockDelta = mock(Delta.class, withSettings().lenient());
when(mockDelta.hasDelta()).thenReturn(true);
DeltaCapableGemFireSessionAttributes sessionAttributes = new DeltaCapableGemFireSessionAttributes();
sessionAttributes.setIsDirtyPredicate(IsDirtyPredicate.NEVER_DIRTY);
assertThat(sessionAttributes.getIsDirtyPredicate()).isEqualTo(IsDirtyPredicate.NEVER_DIRTY);
assertThat(sessionAttributes.getAttributeNames()).isEmpty();
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
sessionAttributes.setAttribute("1", "TEST");
sessionAttributes.setAttribute("2", mockDelta);
sessionAttributes.setAttribute("3", new Object());
assertThat(sessionAttributes.getAttributeNames()).containsOnly("1", "2", "3");
assertThat(sessionAttributes.hasDelta()).isFalse();
assertThat(sessionAttributes.getSessionAttributeDeltas()).isEmpty();
verify(mockDelta, never()).hasDelta();
}
@Test
public void sessionAttributesEntrySetIteratesAttributeNamesAndValues() {

View File

@@ -18,6 +18,7 @@ package org.springframework.session.data.gemfire.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -52,26 +53,56 @@ public class DeltaAwareDirtyPredicateUnitTests {
}
@Test
public void isDirtyWithDeltaObjectReturnsTrue() {
public void isDirtyWithSameDeltaObjectReturnsTrue() {
Delta mockDelta = mock(Delta.class);
when(mockDelta.hasDelta()).thenReturn(true);
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty(null, mockDelta)).isTrue();
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty(mockDelta, mockDelta)).isTrue();
verify(mockDelta, times(1)).hasDelta();
}
@Test
public void isDirtyWithDeltaObjectReturnsFalse() {
public void isDirtyWithSameDeltaObjectReturnsFalse() {
Delta mockDelta = mock(Delta.class);
when(mockDelta.hasDelta()).thenReturn(false);
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty("one", mockDelta)).isFalse();
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty(mockDelta, mockDelta)).isFalse();
verify(mockDelta, times(1)).hasDelta();
}
@Test
public void isDirtyWithStringAndDeltaObjectReturnsTrue() {
Delta mockDelta = mock(Delta.class);
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty("one", mockDelta)).isTrue();
verify(mockDelta, never()).hasDelta();
}
@Test
public void isDirtyWithNullAndDeltaObjectReturnsTrue() {
Delta mockDelta = mock(Delta.class);
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty(null, mockDelta)).isTrue();
verify(mockDelta, never()).hasDelta();
}
@Test
public void isDirtyWithDeltaObjectAndNullReturnsTrue() {
Delta mockDelta = mock(Delta.class);
assertThat(DeltaAwareDirtyPredicate.INSTANCE.isDirty(mockDelta, null)).isTrue();
verify(mockDelta, never()).hasDelta();
}
}

View File

@@ -37,31 +37,31 @@ public class IsDirtyPredicateUnitTests {
@Test
public void alwaysDirtyPredicateIsAlwaysTrue() {
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty("one", "one")).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty("one", "two")).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty("one", "one")).isTrue();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty("one", "two")).isTrue();
}
@Test
public void alwaysDirtyPredicateIsNullSafe() {
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty("one", null)).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty(null, "one")).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty(null, null)).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty("one", null)).isTrue();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty(null, "one")).isTrue();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.isDirty(null, null)).isTrue();
}
@Test
public void neverDirtyPredicateIsAlwaysTrue() {
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty("one", "one")).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty("one", "two")).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty("one", "one")).isFalse();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty("one", "two")).isFalse();
}
@Test
public void neverDirtyPredicateIsNullSafe() {
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty("one", null)).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty(null, "one")).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty(null, null)).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty(null, null)).isFalse();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty("one", null)).isFalse();
assertThat(IsDirtyPredicate.NEVER_DIRTY.isDirty(null, "one")).isFalse();
}
@Test
@@ -94,18 +94,18 @@ public class IsDirtyPredicateUnitTests {
@Test
public void andThenIsDirtyReturnsTrue() {
assertThat(IsDirtyPredicate.NEVER_DIRTY.andThen(IsDirtyPredicate.NEVER_DIRTY)
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.andThen(IsDirtyPredicate.ALWAYS_DIRTY)
.isDirty("one", "one")).isTrue();
}
@Test
public void andThenIsDirtyReturnsFalse() {
assertThat(IsDirtyPredicate.NEVER_DIRTY.andThen(IsDirtyPredicate.ALWAYS_DIRTY)
.isDirty("one", "two")).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.andThen(IsDirtyPredicate.NEVER_DIRTY)
.isDirty("one", "two")).isFalse();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.andThen(IsDirtyPredicate.ALWAYS_DIRTY)
assertThat(IsDirtyPredicate.NEVER_DIRTY.andThen(IsDirtyPredicate.ALWAYS_DIRTY)
.isDirty("one", "two")).isFalse();
assertThat(IsDirtyPredicate.NEVER_DIRTY.andThen(IsDirtyPredicate.NEVER_DIRTY)
.isDirty("one", "two")).isFalse();
}
@@ -139,18 +139,18 @@ public class IsDirtyPredicateUnitTests {
@Test
public void orThenIsDirtyReturnsTrue() {
assertThat(IsDirtyPredicate.NEVER_DIRTY.orThen(IsDirtyPredicate.NEVER_DIRTY)
.isDirty("one", "one")).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.orThen(IsDirtyPredicate.ALWAYS_DIRTY)
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.orThen(IsDirtyPredicate.ALWAYS_DIRTY)
.isDirty("one", "one")).isTrue();
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.orThen(IsDirtyPredicate.NEVER_DIRTY)
.isDirty("one", "one")).isTrue();
assertThat(IsDirtyPredicate.NEVER_DIRTY.orThen(IsDirtyPredicate.ALWAYS_DIRTY)
.isDirty("one", "one")).isTrue();
}
@Test
public void orThenIsDirtyReturnsFalse() {
assertThat(IsDirtyPredicate.ALWAYS_DIRTY.andThen(IsDirtyPredicate.ALWAYS_DIRTY)
assertThat(IsDirtyPredicate.NEVER_DIRTY.andThen(IsDirtyPredicate.NEVER_DIRTY)
.isDirty("one", "two")).isFalse();
}
}