Extract spring-session-data-redis
Issue gh-806
This commit is contained in:
@@ -0,0 +1,725 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.redis.connection.DefaultMessage;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.BoundHashOperations;
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.BoundValueOperations;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository.PrincipalNameResolver;
|
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession;
|
||||
import org.springframework.session.events.AbstractSessionEvent;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public class RedisOperationsSessionRepositoryTests {
|
||||
static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
@Mock
|
||||
RedisConnectionFactory factory;
|
||||
@Mock
|
||||
RedisConnection connection;
|
||||
@Mock
|
||||
RedisOperations<Object, Object> redisOperations;
|
||||
@Mock
|
||||
BoundValueOperations<Object, Object> boundValueOperations;
|
||||
@Mock
|
||||
BoundHashOperations<Object, Object, Object> boundHashOperations;
|
||||
@Mock
|
||||
BoundSetOperations<Object, Object> boundSetOperations;
|
||||
@Mock
|
||||
ApplicationEventPublisher publisher;
|
||||
@Mock
|
||||
RedisSerializer<Object> defaultSerializer;
|
||||
@Captor
|
||||
ArgumentCaptor<AbstractSessionEvent> event;
|
||||
@Captor
|
||||
ArgumentCaptor<Map<String, Object>> delta;
|
||||
|
||||
private MapSession cached;
|
||||
|
||||
private RedisOperationsSessionRepository redisRepository;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.redisRepository = new RedisOperationsSessionRepository(this.redisOperations);
|
||||
this.redisRepository.setDefaultSerializer(this.defaultSerializer);
|
||||
|
||||
this.cached = new MapSession();
|
||||
this.cached.setId("session-id");
|
||||
this.cached.setCreationTime(Instant.ofEpochMilli(1404360000000L));
|
||||
this.cached.setLastAccessedTime(Instant.ofEpochMilli(1404360000000L));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorNullConnectionFactory() {
|
||||
new RedisOperationsSessionRepository((RedisConnectionFactory) null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setApplicationEventPublisherNull() {
|
||||
this.redisRepository.setApplicationEventPublisher(null);
|
||||
}
|
||||
|
||||
// gh-61
|
||||
@Test
|
||||
public void constructorConnectionFactory() {
|
||||
this.redisRepository = new RedisOperationsSessionRepository(this.factory);
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
|
||||
given(this.factory.getConnection()).willReturn(this.connection);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() throws Exception {
|
||||
Session session = this.redisRepository.createSession();
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(new MapSession().getMaxInactiveInterval());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionCustomMaxInactiveInterval() throws Exception {
|
||||
int interval = 1;
|
||||
this.redisRepository.setDefaultMaxInactiveInterval(interval);
|
||||
Session session = this.redisRepository.createSession();
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(Duration.ofSeconds(interval));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewSession() {
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
Map<String, Object> delta = getDelta();
|
||||
assertThat(delta.size()).isEqualTo(3);
|
||||
Object creationTime = delta
|
||||
.get(RedisOperationsSessionRepository.CREATION_TIME_ATTR);
|
||||
assertThat(creationTime).isEqualTo(session.getCreationTime().toEpochMilli());
|
||||
assertThat(delta.get(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR))
|
||||
.isEqualTo((int) Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS).getSeconds());
|
||||
assertThat(delta.get(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR))
|
||||
.isEqualTo(session.getCreationTime().toEpochMilli());
|
||||
}
|
||||
|
||||
// gh-467
|
||||
@Test
|
||||
public void saveSessionNothingChanged() {
|
||||
RedisSession session = this.redisRepository.new RedisSession(this.cached);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveJavadocSummary() {
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
|
||||
String sessionKey = "spring:session:sessions:" + session.getId();
|
||||
String backgroundExpireKey = "spring:session:expirations:"
|
||||
+ RedisSessionExpirationPolicy.roundUpToNextMinute(
|
||||
RedisSessionExpirationPolicy.expiresInMillis(session));
|
||||
String destroyedTriggerKey = "spring:session:sessions:expires:" + session.getId();
|
||||
|
||||
given(this.redisOperations.boundHashOps(sessionKey))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(backgroundExpireKey))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(destroyedTriggerKey))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
// the actual data in the session expires 5 minutes after expiration so the data
|
||||
// can be accessed in expiration events
|
||||
// if the session is retrieved and expired it will not be returned since
|
||||
// getSession checks if it is expired
|
||||
long fiveMinutesAfterExpires = session.getMaxInactiveInterval().plusMinutes(5)
|
||||
.getSeconds();
|
||||
verify(this.boundHashOperations).expire(fiveMinutesAfterExpires,
|
||||
TimeUnit.SECONDS);
|
||||
verify(this.boundSetOperations).expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
|
||||
verify(this.boundSetOperations).add("expires:" + session.getId());
|
||||
verify(this.boundValueOperations).expire(1800L, TimeUnit.SECONDS);
|
||||
verify(this.boundValueOperations).append("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveJavadoc() {
|
||||
RedisSession session = this.redisRepository.new RedisSession(this.cached);
|
||||
session.setLastAccessedTime(session.getLastAccessedTime());
|
||||
|
||||
given(this.redisOperations.boundHashOps("spring:session:sessions:session-id"))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations
|
||||
.boundSetOps("spring:session:expirations:1404361860000"))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations
|
||||
.boundValueOps("spring:session:sessions:expires:session-id"))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
// the actual data in the session expires 5 minutes after expiration so the data
|
||||
// can be accessed in expiration events
|
||||
// if the session is retrieved and expired it will not be returned since
|
||||
// getSession checks if it is expired
|
||||
verify(this.boundHashOperations).expire(
|
||||
session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveLastAccessChanged() {
|
||||
RedisSession session = this.redisRepository.new RedisSession(
|
||||
new MapSession(this.cached));
|
||||
session.setLastAccessedTime(Instant.ofEpochMilli(12345678L));
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
assertThat(getDelta())
|
||||
.isEqualTo(map(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
session.getLastAccessedTime().toEpochMilli()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveSetAttribute() {
|
||||
String attrName = "attrName";
|
||||
RedisSession session = this.redisRepository.new RedisSession(new MapSession());
|
||||
session.setAttribute(attrName, "attrValue");
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
assertThat(getDelta()).isEqualTo(
|
||||
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
session.getAttribute(attrName).orElse(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveRemoveAttribute() {
|
||||
String attrName = "attrName";
|
||||
RedisSession session = this.redisRepository.new RedisSession(new MapSession());
|
||||
session.removeAttribute(attrName);
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
assertThat(getDelta()).isEqualTo(map(
|
||||
RedisOperationsSessionRepository.getSessionAttrNameKey(attrName), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveExpired() {
|
||||
RedisSession session = this.redisRepository.new RedisSession(new MapSession());
|
||||
session.setMaxInactiveInterval(Duration.ZERO);
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
|
||||
this.redisRepository.save(session);
|
||||
|
||||
String id = session.getId();
|
||||
verify(this.redisOperations, atLeastOnce()).delete(getKey("expires:" + id));
|
||||
verify(this.redisOperations, never()).boundValueOps(getKey("expires:" + id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisSessionGetAttributes() {
|
||||
String attrName = "attrName";
|
||||
RedisSession session = this.redisRepository.new RedisSession();
|
||||
assertThat(session.getAttributeNames()).isEmpty();
|
||||
session.setAttribute(attrName, "attrValue");
|
||||
assertThat(session.getAttributeNames()).containsOnly(attrName);
|
||||
session.removeAttribute(attrName);
|
||||
assertThat(session.getAttributeNames()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() {
|
||||
String attrName = "attrName";
|
||||
MapSession expected = new MapSession();
|
||||
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
|
||||
expected.setAttribute(attrName, "attrValue");
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
expected.getAttribute(attrName).orElse(null),
|
||||
RedisOperationsSessionRepository.CREATION_TIME_ATTR,
|
||||
expected.getCreationTime().toEpochMilli(),
|
||||
RedisOperationsSessionRepository.MAX_INACTIVE_ATTR,
|
||||
(int) expected.getMaxInactiveInterval().getSeconds(),
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
expected.getLastAccessedTime().toEpochMilli());
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
|
||||
String id = expected.getId();
|
||||
this.redisRepository.delete(id);
|
||||
|
||||
assertThat(getDelta().get(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR))
|
||||
.isEqualTo(0);
|
||||
verify(this.redisOperations, atLeastOnce()).delete(getKey("expires:" + id));
|
||||
verify(this.redisOperations, never()).boundValueOps(getKey("expires:" + id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteNullSession() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
|
||||
String id = "abc";
|
||||
this.redisRepository.delete(id);
|
||||
verify(this.redisOperations, times(0)).delete(anyString());
|
||||
verify(this.redisOperations, times(0)).delete(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionNotFound() {
|
||||
String id = "abc";
|
||||
given(this.redisOperations.boundHashOps(getKey(id)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.boundHashOperations.entries()).willReturn(map());
|
||||
|
||||
assertThat(this.redisRepository.getSession(id)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionFound() {
|
||||
String attrName = "attrName";
|
||||
MapSession expected = new MapSession();
|
||||
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
|
||||
expected.setAttribute(attrName, "attrValue");
|
||||
given(this.redisOperations.boundHashOps(getKey(expected.getId())))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
expected.getAttribute(attrName).orElse(null),
|
||||
RedisOperationsSessionRepository.CREATION_TIME_ATTR,
|
||||
expected.getCreationTime().toEpochMilli(),
|
||||
RedisOperationsSessionRepository.MAX_INACTIVE_ATTR,
|
||||
(int) expected.getMaxInactiveInterval().getSeconds(),
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
expected.getLastAccessedTime().toEpochMilli());
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
|
||||
RedisSession session = this.redisRepository.getSession(expected.getId());
|
||||
assertThat(session.getId()).isEqualTo(expected.getId());
|
||||
assertThat(session.getAttributeNames()).isEqualTo(expected.getAttributeNames());
|
||||
assertThat(session.<String>getAttribute(attrName))
|
||||
.isEqualTo(expected.getAttribute(attrName));
|
||||
assertThat(session.getCreationTime()).isEqualTo(expected.getCreationTime());
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(expected.getMaxInactiveInterval());
|
||||
assertThat(session.getLastAccessedTime())
|
||||
.isEqualTo(expected.getLastAccessedTime());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionExpired() {
|
||||
String expiredId = "expired-id";
|
||||
given(this.redisOperations.boundHashOps(getKey(expiredId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR, 1,
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
Instant.now().minus(5, ChronoUnit.MINUTES).toEpochMilli());
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
|
||||
assertThat(this.redisRepository.getSession(expiredId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByPrincipalNameExpired() {
|
||||
String expiredId = "expired-id";
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.boundSetOperations.members())
|
||||
.willReturn(Collections.<Object>singleton(expiredId));
|
||||
given(this.redisOperations.boundHashOps(getKey(expiredId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR, 1,
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
Instant.now().minus(5, ChronoUnit.MINUTES).toEpochMilli());
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
|
||||
assertThat(this.redisRepository.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, "principal"))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByPrincipalName() {
|
||||
Instant lastAccessed = Instant.now().minusMillis(10);
|
||||
Instant createdTime = lastAccessed.minusMillis(10);
|
||||
Duration maxInactive = Duration.ofHours(1);
|
||||
String sessionId = "some-id";
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.boundSetOperations.members())
|
||||
.willReturn(Collections.<Object>singleton(sessionId));
|
||||
given(this.redisOperations.boundHashOps(getKey(sessionId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.CREATION_TIME_ATTR, createdTime.toEpochMilli(),
|
||||
RedisOperationsSessionRepository.MAX_INACTIVE_ATTR, (int) maxInactive.getSeconds(),
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR, lastAccessed.toEpochMilli());
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
|
||||
Map<String, RedisSession> sessionIdToSessions = this.redisRepository
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
"principal");
|
||||
|
||||
assertThat(sessionIdToSessions).hasSize(1);
|
||||
RedisSession session = sessionIdToSessions.get(sessionId);
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.getId()).isEqualTo(sessionId);
|
||||
assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessed);
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(maxInactive);
|
||||
assertThat(session.getCreationTime()).isEqualTo(createdTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cleanupExpiredSessions() {
|
||||
String expiredId = "expired-id";
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
|
||||
Set<Object> expiredIds = new HashSet<>(
|
||||
Arrays.asList("expired-key1", "expired-key2"));
|
||||
given(this.boundSetOperations.members()).willReturn(expiredIds);
|
||||
|
||||
this.redisRepository.cleanupExpiredSessions();
|
||||
|
||||
for (Object id : expiredIds) {
|
||||
String expiredKey = "spring:session:sessions:" + id;
|
||||
// https://github.com/spring-projects/spring-session/issues/93
|
||||
verify(this.redisOperations).hasKey(expiredKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMessageCreated() throws Exception {
|
||||
MapSession session = this.cached;
|
||||
byte[] pattern = "".getBytes("UTF-8");
|
||||
String channel = "spring:session:event:created:" + session.getId();
|
||||
JdkSerializationRedisSerializer defaultSerailizer = new JdkSerializationRedisSerializer();
|
||||
this.redisRepository.setDefaultSerializer(defaultSerailizer);
|
||||
byte[] body = defaultSerailizer.serialize(new HashMap());
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body);
|
||||
|
||||
this.redisRepository.setApplicationEventPublisher(this.publisher);
|
||||
|
||||
this.redisRepository.onMessage(message, pattern);
|
||||
|
||||
verify(this.publisher).publishEvent(this.event.capture());
|
||||
assertThat(this.event.getValue().getSessionId()).isEqualTo(session.getId());
|
||||
}
|
||||
|
||||
// gh-309
|
||||
@Test
|
||||
public void onMessageCreatedCustomSerializer() throws Exception {
|
||||
MapSession session = this.cached;
|
||||
byte[] pattern = "".getBytes("UTF-8");
|
||||
byte[] body = new byte[0];
|
||||
String channel = "spring:session:event:created:" + session.getId();
|
||||
given(this.defaultSerializer.deserialize(body))
|
||||
.willReturn(new HashMap<String, Object>());
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body);
|
||||
this.redisRepository.setApplicationEventPublisher(this.publisher);
|
||||
|
||||
this.redisRepository.onMessage(message, pattern);
|
||||
|
||||
verify(this.publisher).publishEvent(this.event.capture());
|
||||
assertThat(this.event.getValue().getSessionId()).isEqualTo(session.getId());
|
||||
verify(this.defaultSerializer).deserialize(body);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePrincipalIndex() {
|
||||
PrincipalNameResolver resolver = RedisOperationsSessionRepository.PRINCIPAL_NAME_RESOLVER;
|
||||
String username = "username";
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
username);
|
||||
|
||||
assertThat(resolver.resolvePrincipal(session)).isEqualTo(username);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveIndexOnSecurityContext() {
|
||||
String principal = "resolveIndexOnSecurityContext";
|
||||
Authentication authentication = new UsernamePasswordAuthenticationToken(principal,
|
||||
"notused", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext context = new SecurityContextImpl();
|
||||
context.setAuthentication(authentication);
|
||||
|
||||
PrincipalNameResolver resolver = RedisOperationsSessionRepository.PRINCIPAL_NAME_RESOLVER;
|
||||
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, context);
|
||||
|
||||
assertThat(resolver.resolvePrincipal(session)).isEqualTo(principal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeOnSaveCreate() {
|
||||
this.redisRepository.createSession();
|
||||
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeOnSaveSetAttribute() {
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
session.setAttribute("something", "here");
|
||||
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeOnSaveRemoveAttribute() {
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
session.removeAttribute("remove");
|
||||
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeOnSaveSetLastAccessedTime() {
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
session.setLastAccessedTime(Instant.ofEpochMilli(1L));
|
||||
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeOnSaveSetMaxInactiveIntervalInSeconds() {
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
session.setMaxInactiveInterval(Duration.ofSeconds(1));
|
||||
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeImmediateCreate() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE);
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
|
||||
Map<String, Object> delta = getDelta();
|
||||
assertThat(delta.size()).isEqualTo(3);
|
||||
Object creationTime = delta
|
||||
.get(RedisOperationsSessionRepository.CREATION_TIME_ATTR);
|
||||
assertThat(creationTime).isEqualTo(session.getCreationTime().toEpochMilli());
|
||||
assertThat(delta.get(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR))
|
||||
.isEqualTo((int) Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS).getSeconds());
|
||||
assertThat(delta.get(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR))
|
||||
.isEqualTo(session.getCreationTime().toEpochMilli());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeImmediateSetAttribute() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE);
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
String attrName = "someAttribute";
|
||||
session.setAttribute(attrName, "someValue");
|
||||
|
||||
Map<String, Object> delta = getDelta(2);
|
||||
assertThat(delta.size()).isEqualTo(1);
|
||||
assertThat(delta).isEqualTo(
|
||||
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
session.getAttribute(attrName).orElse(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeImmediateRemoveAttribute() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE);
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
String attrName = "someAttribute";
|
||||
session.removeAttribute(attrName);
|
||||
|
||||
Map<String, Object> delta = getDelta(2);
|
||||
assertThat(delta.size()).isEqualTo(1);
|
||||
assertThat(delta).isEqualTo(
|
||||
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
session.getAttribute(attrName).orElse(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeSetMaxInactiveIntervalInSeconds() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE);
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
|
||||
reset(this.boundHashOperations);
|
||||
|
||||
session.setMaxInactiveInterval(Duration.ofSeconds(1));
|
||||
|
||||
verify(this.boundHashOperations).expire(anyLong(), any(TimeUnit.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushModeSetLastAccessedTime() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE);
|
||||
RedisSession session = this.redisRepository.createSession();
|
||||
|
||||
session.setLastAccessedTime(Instant.now());
|
||||
|
||||
Map<String, Object> delta = getDelta(2);
|
||||
assertThat(delta.size()).isEqualTo(1);
|
||||
assertThat(delta)
|
||||
.isEqualTo(map(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
session.getLastAccessedTime().toEpochMilli()));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setRedisFlushModeNull() {
|
||||
this.redisRepository.setRedisFlushMode(null);
|
||||
}
|
||||
|
||||
private String getKey(String id) {
|
||||
return "spring:session:sessions:" + id;
|
||||
}
|
||||
|
||||
private Map map(Object... objects) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (objects == null) {
|
||||
return result;
|
||||
}
|
||||
for (int i = 0; i < objects.length; i += 2) {
|
||||
result.put((String) objects[i], objects[i + 1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Object> getDelta() {
|
||||
return getDelta(1);
|
||||
}
|
||||
|
||||
private Map<String, Object> getDelta(int times) {
|
||||
verify(this.boundHashOperations, times(times)).putAll(this.delta.capture());
|
||||
return this.delta.getAllValues().get(times - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.redis.core.BoundHashOperations;
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.BoundValueOperations;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.session.MapSession;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RedisSessionExpirationPolicyTests {
|
||||
// Wed Apr 15 10:28:32 CDT 2015
|
||||
final static Long NOW = 1429111712346L;
|
||||
|
||||
// Wed Apr 15 10:27:32 CDT 2015
|
||||
final static Long ONE_MINUTE_AGO = 1429111652346L;
|
||||
|
||||
@Mock
|
||||
RedisOperations<Object, Object> sessionRedisOperations;
|
||||
@Mock
|
||||
BoundSetOperations<Object, Object> setOperations;
|
||||
@Mock
|
||||
BoundHashOperations<Object, Object, Object> hashOperations;
|
||||
@Mock
|
||||
BoundValueOperations<Object, Object> valueOperations;
|
||||
|
||||
RedisSessionExpirationPolicy policy;
|
||||
|
||||
private MapSession session;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(
|
||||
this.sessionRedisOperations);
|
||||
this.policy = new RedisSessionExpirationPolicy(this.sessionRedisOperations,
|
||||
repository);
|
||||
this.session = new MapSession();
|
||||
this.session.setLastAccessedTime(Instant.ofEpochMilli(1429116694675L));
|
||||
this.session.setId("12345");
|
||||
|
||||
given(this.sessionRedisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.setOperations);
|
||||
given(this.sessionRedisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.hashOperations);
|
||||
given(this.sessionRedisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.valueOperations);
|
||||
}
|
||||
|
||||
// gh-169
|
||||
@Test
|
||||
public void onExpirationUpdatedRemovesOriginalExpirationTimeRoundedUp()
|
||||
throws Exception {
|
||||
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
|
||||
long originalRoundedToNextMinInMs = RedisSessionExpirationPolicy
|
||||
.roundUpToNextMinute(originalExpirationTimeInMs);
|
||||
String originalExpireKey = this.policy
|
||||
.getExpirationKey(originalRoundedToNextMinInMs);
|
||||
|
||||
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
|
||||
|
||||
// verify the original is removed
|
||||
verify(this.sessionRedisOperations).boundSetOps(originalExpireKey);
|
||||
verify(this.setOperations).remove("expires:" + this.session.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedDoNotSendDeleteWhenExpirationTimeDoesNotChange()
|
||||
throws Exception {
|
||||
long originalExpirationTimeInMs = RedisSessionExpirationPolicy
|
||||
.expiresInMillis(this.session) - 10;
|
||||
long originalRoundedToNextMinInMs = RedisSessionExpirationPolicy
|
||||
.roundUpToNextMinute(originalExpirationTimeInMs);
|
||||
String originalExpireKey = this.policy
|
||||
.getExpirationKey(originalRoundedToNextMinInMs);
|
||||
|
||||
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
|
||||
|
||||
// verify the original is not removed
|
||||
verify(this.sessionRedisOperations).boundSetOps(originalExpireKey);
|
||||
verify(this.setOperations, never()).remove("expires:" + this.session.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedAddsExpirationTimeRoundedUp() throws Exception {
|
||||
long expirationTimeInMs = RedisSessionExpirationPolicy
|
||||
.expiresInMillis(this.session);
|
||||
long expirationRoundedUpInMs = RedisSessionExpirationPolicy
|
||||
.roundUpToNextMinute(expirationTimeInMs);
|
||||
String expectedExpireKey = this.policy.getExpirationKey(expirationRoundedUpInMs);
|
||||
|
||||
this.policy.onExpirationUpdated(null, this.session);
|
||||
|
||||
verify(this.sessionRedisOperations).boundSetOps(expectedExpireKey);
|
||||
verify(this.setOperations).add("expires:" + this.session.getId());
|
||||
verify(this.setOperations).expire(
|
||||
this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedSetExpireSession() throws Exception {
|
||||
String sessionKey = this.policy.getSessionKey(this.session.getId());
|
||||
|
||||
this.policy.onExpirationUpdated(null, this.session);
|
||||
|
||||
verify(this.sessionRedisOperations).boundHashOps(sessionKey);
|
||||
verify(this.hashOperations).expire(
|
||||
this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedDeleteOnZero() throws Exception {
|
||||
String sessionKey = this.policy.getSessionKey("expires:" + this.session.getId());
|
||||
|
||||
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
|
||||
|
||||
this.session.setMaxInactiveInterval(Duration.ZERO);
|
||||
|
||||
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
|
||||
|
||||
// verify the original is removed
|
||||
verify(this.setOperations).remove("expires:" + this.session.getId());
|
||||
verify(this.setOperations).add("expires:" + this.session.getId());
|
||||
verify(this.sessionRedisOperations).delete(sessionKey);
|
||||
verify(this.setOperations).expire(
|
||||
this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedPersistOnNegativeExpiration() throws Exception {
|
||||
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
|
||||
|
||||
this.session.setMaxInactiveInterval(Duration.ofSeconds(-1));
|
||||
|
||||
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
|
||||
|
||||
verify(this.setOperations).remove("expires:" + this.session.getId());
|
||||
verify(this.valueOperations).append("");
|
||||
verify(this.valueOperations).persist();
|
||||
verify(this.hashOperations).persist();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class EnableRedisKeyspaceNotificationsInitializerTests {
|
||||
static final String CONFIG_NOTIFY_KEYSPACE_EVENTS = "notify-keyspace-events";
|
||||
|
||||
@Mock
|
||||
RedisConnectionFactory connectionFactory;
|
||||
@Mock
|
||||
RedisConnection connection;
|
||||
@Captor
|
||||
ArgumentCaptor<String> options;
|
||||
|
||||
RedisHttpSessionConfiguration.EnableRedisKeyspaceNotificationsInitializer initializer;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
given(this.connectionFactory.getConnection()).willReturn(this.connection);
|
||||
|
||||
this.initializer = new RedisHttpSessionConfiguration.EnableRedisKeyspaceNotificationsInitializer(
|
||||
this.connectionFactory, new ConfigureNotifyKeyspaceEventsAction());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetUnset() throws Exception {
|
||||
setConfigNotification("");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("E", "g", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetA() throws Exception {
|
||||
setConfigNotification("A");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("A", "E");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetE() throws Exception {
|
||||
setConfigNotification("E");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("E", "g", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetK() throws Exception {
|
||||
setConfigNotification("K");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("K", "E", "g", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetAE() throws Exception {
|
||||
setConfigNotification("AE");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
verify(this.connection, never()).setConfig(anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetAK() throws Exception {
|
||||
setConfigNotification("AK");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("A", "K", "E");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetEK() throws Exception {
|
||||
setConfigNotification("EK");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("E", "K", "g", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetEg() throws Exception {
|
||||
setConfigNotification("Eg");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("E", "g", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetE$() throws Exception {
|
||||
setConfigNotification("E$");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("E", "$", "g", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetKg() throws Exception {
|
||||
setConfigNotification("Kg");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
assertOptionsContains("K", "g", "E", "x");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetAEK() throws Exception {
|
||||
setConfigNotification("AEK");
|
||||
|
||||
this.initializer.afterPropertiesSet();
|
||||
|
||||
verify(this.connection, never()).setConfig(anyString(), anyString());
|
||||
}
|
||||
|
||||
private void assertOptionsContains(String... expectedValues) {
|
||||
verify(this.connection).setConfig(eq(CONFIG_NOTIFY_KEYSPACE_EVENTS),
|
||||
this.options.capture());
|
||||
for (String expectedValue : expectedValues) {
|
||||
assertThat(this.options.getValue()).contains(expectedValue);
|
||||
}
|
||||
assertThat(this.options.getValue().length()).isEqualTo(expectedValues.length);
|
||||
}
|
||||
|
||||
private void setConfigNotification(String value) {
|
||||
given(this.connection.getConfig(CONFIG_NOTIFY_KEYSPACE_EVENTS))
|
||||
.willReturn(Arrays.asList(CONFIG_NOTIFY_KEYSPACE_EVENTS, value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class RedisHttpSessionConfigurationClassPathXmlApplicationContextTests {
|
||||
|
||||
// gh-318
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
static RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
public class RedisHttpSessionConfigurationCustomCronTests {
|
||||
|
||||
AnnotationConfigApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
}
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overrideCron() {
|
||||
this.context.register(Config.class);
|
||||
|
||||
assertThatThrownBy(() ->
|
||||
RedisHttpSessionConfigurationCustomCronTests.this.context.refresh())
|
||||
.hasStackTraceContaining(
|
||||
"Encountered invalid @Scheduled method 'cleanupExpiredSessions': Cron expression must consist of 6 fields (found 1 in \"oops\")");
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
@PropertySource("classpath:spring-session-cleanup-cron-expression-oops.properties")
|
||||
static class Config {
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration.EnableRedisKeyspaceNotificationsInitializer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RedisHttpSessionConfigurationMockTests {
|
||||
@Mock
|
||||
RedisConnectionFactory factory;
|
||||
@Mock
|
||||
RedisConnection connection;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
given(this.factory.getConnection()).willReturn(this.connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenNoOpThenNoInteractionWithConnectionFactory()
|
||||
throws Exception {
|
||||
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(
|
||||
this.factory, ConfigureRedisAction.NO_OP);
|
||||
|
||||
init.afterPropertiesSet();
|
||||
|
||||
verifyZeroInteractions(this.factory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenExceptionThenCloseConnection()
|
||||
throws Exception {
|
||||
ConfigureRedisAction action = mock(ConfigureRedisAction.class);
|
||||
willThrow(new RuntimeException()).given(action).configure(this.connection);
|
||||
|
||||
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(
|
||||
this.factory, action);
|
||||
|
||||
try {
|
||||
init.afterPropertiesSet();
|
||||
failBecauseExceptionWasNotThrown(Throwable.class);
|
||||
}
|
||||
catch (Throwable success) {
|
||||
}
|
||||
|
||||
verify(this.connection).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenNoExceptionThenCloseConnection()
|
||||
throws Exception {
|
||||
ConfigureRedisAction action = mock(ConfigureRedisAction.class);
|
||||
|
||||
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(
|
||||
this.factory, action);
|
||||
|
||||
init.afterPropertiesSet();
|
||||
|
||||
verify(this.connection).close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class RedisHttpSessionConfigurationNoOpConfigureRedisActionTests {
|
||||
|
||||
@Test
|
||||
public void redisConnectionFactoryNotUsedSinceNoValidation() {
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public static ConfigureRedisAction configureRedisAction() {
|
||||
return ConfigureRedisAction.NO_OP;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
return mock(RedisConnectionFactory.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class RedisHttpSessionConfigurationOverrideDefaultSerializerTests {
|
||||
|
||||
@Autowired
|
||||
RedisTemplate<Object, Object> template;
|
||||
|
||||
@Autowired
|
||||
RedisSerializer<Object> defaultRedisSerializer;
|
||||
|
||||
@Test
|
||||
public void overrideDefaultRedisTemplate() {
|
||||
assertThat(this.template.getDefaultSerializer())
|
||||
.isSameAs(this.defaultRedisSerializer);
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
|
||||
return mock(RedisSerializer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.scheduling.SchedulingAwareRunnable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Vladimir Tsanev
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class RedisHttpSessionConfigurationOverrideSessionTaskExecutor {
|
||||
|
||||
@Autowired
|
||||
RedisMessageListenerContainer redisMessageListenerContainer;
|
||||
|
||||
@Autowired
|
||||
Executor springSessionRedisTaskExecutor;
|
||||
|
||||
@Test
|
||||
public void overrideSessionTaskExecutor() {
|
||||
verify(this.springSessionRedisTaskExecutor, times(1))
|
||||
.execute(any(SchedulingAwareRunnable.class));
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
public Executor springSessionRedisTaskExecutor() {
|
||||
return mock(Executor.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2014-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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.scheduling.SchedulingAwareRunnable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Vladimir Tsanev
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class RedisHttpSessionConfigurationOverrideSessionTaskExecutors {
|
||||
|
||||
@Autowired
|
||||
RedisMessageListenerContainer redisMessageListenerContainer;
|
||||
|
||||
@Autowired
|
||||
Executor springSessionRedisTaskExecutor;
|
||||
|
||||
@Autowired
|
||||
Executor springSessionRedisSubscriptionExecutor;
|
||||
|
||||
@Test
|
||||
public void overrideSessionTaskExecutors() {
|
||||
verify(this.springSessionRedisSubscriptionExecutor, times(1))
|
||||
.execute(any(SchedulingAwareRunnable.class));
|
||||
verify(this.springSessionRedisTaskExecutor, never()).execute(any(Runnable.class));
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
public Executor springSessionRedisTaskExecutor() {
|
||||
return mock(Executor.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Executor springSessionRedisSubscriptionExecutor() {
|
||||
return mock(Executor.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
public class RedisHttpSessionConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveValue() {
|
||||
registerAndRefresh(RedisConfig.class, CustomRedisHttpSessionConfiguration.class);
|
||||
RedisHttpSessionConfiguration configuration = this.context.getBean(RedisHttpSessionConfiguration.class);
|
||||
assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")).isEqualTo("myRedisNamespace");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveValueByPlaceholder() {
|
||||
this.context.setEnvironment(new MockEnvironment().withProperty("session.redis.namespace", "customRedisNamespace"));
|
||||
registerAndRefresh(RedisConfig.class, PropertySourceConfiguration.class, CustomRedisHttpSessionConfiguration2.class);
|
||||
RedisHttpSessionConfiguration configuration = this.context.getBean(RedisHttpSessionConfiguration.class);
|
||||
assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")).isEqualTo("customRedisNamespace");
|
||||
}
|
||||
|
||||
private void registerAndRefresh(Class<?>... annotatedClasses) {
|
||||
this.context.register(annotatedClasses);
|
||||
this.context.refresh();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class PropertySourceConfiguration {
|
||||
|
||||
@Bean
|
||||
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
RedisConnectionFactory connectionFactory = mock(RedisConnectionFactory.class);
|
||||
given(connectionFactory.getConnection()).willReturn(mock(RedisConnection.class));
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableRedisHttpSession(redisNamespace = "myRedisNamespace")
|
||||
static class CustomRedisHttpSessionConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableRedisHttpSession(redisNamespace = "${session.redis.namespace}")
|
||||
static class CustomRedisHttpSessionConfiguration2 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class RedisHttpSessionConfigurationXmlCustomExpireTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
static RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class RedisHttpSessionConfigurationXmlTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
static RedisConnectionFactory connectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.session.data.redis.config.annotation.web.http.gh109;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* This test must be in a different package than RedisHttpSessionConfiguration.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0.2
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class Gh109Tests {
|
||||
|
||||
@Test
|
||||
public void loads() {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends RedisHttpSessionConfiguration {
|
||||
|
||||
int sessionTimeout = 100;
|
||||
|
||||
/**
|
||||
* override sessionRepository construction to set the custom session-timeout
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public RedisOperationsSessionRepository sessionRepository(
|
||||
RedisOperations<Object, Object> sessionRedisTemplate,
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
|
||||
sessionRedisTemplate);
|
||||
sessionRepository.setDefaultMaxInactiveInterval(this.sessionTimeout);
|
||||
return sessionRepository;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = mock(RedisConnection.class);
|
||||
|
||||
given(factory.getConnection()).willReturn(connection);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
|
||||
|
||||
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfigurationClassPathXmlApplicationContextTests"
|
||||
factory-method="connectionFactory"/>
|
||||
</beans>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"
|
||||
p:maxInactiveIntervalInSeconds="3600"/>
|
||||
|
||||
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfigurationXmlCustomExpireTests"
|
||||
factory-method="connectionFactory"/>
|
||||
</beans>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
|
||||
|
||||
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfigurationXmlTests"
|
||||
factory-method="connectionFactory"/>
|
||||
</beans>
|
||||
@@ -0,0 +1 @@
|
||||
spring.session.cleanup.cron.expression=oops
|
||||
Reference in New Issue
Block a user