Refactor to make it more apparent when a race condition occurs in concurrent Session access Integration Tests.

This commit is contained in:
John Blum
2022-04-28 15:03:20 -07:00
parent 9aecc6117b
commit fb23ebf55c
3 changed files with 34 additions and 21 deletions

View File

@@ -37,7 +37,9 @@ import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/** /**
* Abstract base class encapsulating functionality common to all concurrent {@link Session} data access operation * Abstract base class encapsulating functionality common to all concurrent {@link Session} data access operation
@@ -95,12 +97,23 @@ public abstract class AbstractConcurrentSessionOperationsIntegrationTests extend
return this.sessionRepository; return this.sessionRepository;
} }
protected @NonNull String getSessionId() { protected void setSessionId(@Nullable String sessionId) {
this.sessionId.set(sessionId);
}
protected @Nullable String getSessionId() {
return this.sessionId.get(); return this.sessionId.get();
} }
protected void setSessionId(@Nullable String sessionId) { protected @NonNull String requireSessionId() {
this.sessionId.set(sessionId);
String sessionId = getSessionId();
Assert.state(StringUtils.hasText(sessionId), () -> "Session ID [%s] is not set;"
+ " A race condition may have occurred between the Thread setting the Session ID and the Threads"
+ " using the Session ID due to untimely operations in the Apache Geode client/server topology");
return sessionId;
} }
protected @Nullable Session findById(@NonNull String id) { protected @Nullable Session findById(@NonNull String id) {
@@ -116,7 +129,7 @@ public abstract class AbstractConcurrentSessionOperationsIntegrationTests extend
return session; return session;
} }
protected void waitOnAvailableSessionId() { protected void waitOnRequiredSessionId() {
AbstractConcurrentSessionOperationsIntegrationTests.waitOn(() -> Objects.nonNull(this.sessionId.get())); AbstractConcurrentSessionOperationsIntegrationTests.waitOn(() -> Objects.nonNull(this.sessionId.get()));
} }
} }
@@ -151,7 +164,6 @@ public abstract class AbstractConcurrentSessionOperationsIntegrationTests extend
assertThat(session.getAttributeNames()).containsOnly("attributeOne", "attributeTwo"); assertThat(session.getAttributeNames()).containsOnly("attributeOne", "attributeTwo");
save(session); save(session);
setSessionId(session.getId()); setSessionId(session.getId());
waitForTick(4); waitForTick(4);
@@ -170,9 +182,9 @@ public abstract class AbstractConcurrentSessionOperationsIntegrationTests extend
waitForTick(1); waitForTick(1);
assertTick(1); assertTick(1);
waitOnAvailableSessionId(); waitOnRequiredSessionId();
Session session = findById(getSessionId()); Session session = findById(requireSessionId());
assertThat(session).isNotNull(); assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(getSessionId()); assertThat(session.getId()).isEqualTo(getSessionId());
@@ -199,8 +211,9 @@ public abstract class AbstractConcurrentSessionOperationsIntegrationTests extend
waitForTick(1); waitForTick(1);
assertTick(1); assertTick(1);
waitOnRequiredSessionId();
Session session = findById(getSessionId()); Session session = findById(requireSessionId());
assertThat(session).isNotNull(); assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(getSessionId()); assertThat(session.getId()).isEqualTo(getSessionId());

View File

@@ -54,6 +54,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.data.gemfire.config.annotation.CacheServerApplication; import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication; import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession; import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration; import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
@@ -160,7 +161,7 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
Instant beforeLastAccessedTime = Instant.now(); Instant beforeLastAccessedTime = Instant.now();
Session session = findById(getSessionId()); Session session = findById(requireSessionId());
assertThat(session).isNotNull(); assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(getSessionId()); assertThat(session.getId()).isEqualTo(getSessionId());
@@ -188,7 +189,7 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
Instant beforeLastAccessedTime = Instant.now(); Instant beforeLastAccessedTime = Instant.now();
Session session = findById(getSessionId()); Session session = findById(requireSessionId());
assertThat(session).isNotNull(); assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(getSessionId()); assertThat(session.getId()).isEqualTo(getSessionId());
@@ -218,7 +219,7 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
private final Region<Object, Session> sessions; private final Region<Object, Session> sessions;
public RegionPutWithNonDirtySessionTestCase( public RegionPutWithNonDirtySessionTestCase(
ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegrationTests testInstance) { @NonNull ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegrationTests testInstance) {
super(testInstance); super(testInstance);
@@ -226,7 +227,7 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
this.sessionSerializer = reregisterDataSerializer(resolveDataSerializer()); this.sessionSerializer = reregisterDataSerializer(resolveDataSerializer());
} }
private DataSerializer reregisterDataSerializer(DataSerializer dataSerializer) { private @NonNull DataSerializer reregisterDataSerializer(@NonNull DataSerializer dataSerializer) {
InternalDataSerializer.unregister(dataSerializer.getId()); InternalDataSerializer.unregister(dataSerializer.getId());
InternalDataSerializer._register(dataSerializer, false); InternalDataSerializer._register(dataSerializer, false);
@@ -234,7 +235,7 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
return dataSerializer; return dataSerializer;
} }
private DataSerializer resolveDataSerializer() { private @NonNull DataSerializer resolveDataSerializer() {
return Arrays.stream(nullSafeArray(InternalDataSerializer.getSerializers(), DataSerializer.class)) return Arrays.stream(nullSafeArray(InternalDataSerializer.getSerializers(), DataSerializer.class))
.filter(this.sessionSerializerFilter()) .filter(this.sessionSerializerFilter())
@@ -243,7 +244,7 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
.orElseThrow(() -> newIllegalStateException(DATA_SERIALIZER_NOT_FOUND_EXCEPTION_MESSAGE)); .orElseThrow(() -> newIllegalStateException(DATA_SERIALIZER_NOT_FOUND_EXCEPTION_MESSAGE));
} }
private Predicate<? super DataSerializer> sessionSerializerFilter() { private @NonNull Predicate<? super DataSerializer> sessionSerializerFilter() {
return dataSerializer -> { return dataSerializer -> {
@@ -260,11 +261,11 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
}; };
} }
private Session get(String id) { private @Nullable Session get(@NonNull String id) {
return this.sessions.get(id); return this.sessions.get(id);
} }
private void put(Session session) { private void put(@NonNull Session session) {
this.sessions.put(session.getId(), session); this.sessions.put(session.getId(), session);
@@ -313,9 +314,9 @@ public class ConcurrentSessionOperationsUsingClientCachingProxyRegionIntegration
waitForTick(1); waitForTick(1);
assertTick(1); assertTick(1);
waitOnAvailableSessionId(); waitOnRequiredSessionId();
Session session = get(getSessionId()); Session session = get(requireSessionId());
assertThat(session).isInstanceOf(GemFireSession.class); assertThat(session).isInstanceOf(GemFireSession.class);
assertThat(session.getId()).isEqualTo(getSessionId()); assertThat(session.getId()).isEqualTo(getSessionId());

View File

@@ -83,7 +83,6 @@ public class ConcurrentSessionOperationsUsingClientLocalRegionIntegrationTests
assertThat(session.getAttributeNames()).isEmpty(); assertThat(session.getAttributeNames()).isEmpty();
save(session); save(session);
setSessionId(session.getId()); setSessionId(session.getId());
waitForTick(2); waitForTick(2);
@@ -100,9 +99,9 @@ public class ConcurrentSessionOperationsUsingClientLocalRegionIntegrationTests
waitForTick(1); waitForTick(1);
assertTick(1); assertTick(1);
waitOnAvailableSessionId(); waitOnRequiredSessionId();
Session session = findById(getSessionId()); Session session = findById(requireSessionId());
assertThat(session).isNotNull(); assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(getSessionId()); assertThat(session.getId()).isEqualTo(getSessionId());